Analizzatore di spettro con dsPIC

Utilizzando un dspic 30F4013 è possibile realizzare un analizzatore di spettro con display grafico. Il codice sorgente è riportato nel listato 1 ed è scritto per il compilatore mikroPascal di mikroelektronika. Il programma usa il canale 10 per l’acquisizione del dato analogico. In figura 1 il risultato visualizzato sul display grafico.

Figura 1. L’analizzatore di spettro in funzione

Figura 1. L’analizzatore di spettro in funzione

program spectrum_analyzer;

uses FFTLib, BitReverseComplex, TwiddleFactors;

var Samples : array[512] of word; absolute $1800; // Y data space
    Written : array[128] of word;
    freq : word;
    txt : string[5];

procedure InitAdc;
begin
  ADPCFG := 0;
  ADCON1 := $00E0; // internal counter ends conversion
  ADCHS := 10; // connect RBxx/ANxx as CH10 input
  ADCSSL := 0;
  ADCON3 := $1F3F; // sample time = 31 Tad.
  ADCON2 := 0;
  ADCON1 := $83E0; // turn ADC ON, fractional result

  TRISB.10 := 1;
end;

procedure Init;
var i: word;
begin
  for i := 0 to 127 do
   begin
     Written[i] := 255;
   end;
 Glcd_Init(LATD.8, LATD.9, LATD.10, LATD.3, LATG.12, LATD.11, LATB);
 Glcd_Set_Font(@FontSystem5x8, 5, 8, 32);
 Glcd_Fill(0xAA);
 Delay_ms(500);
 Glcd_Fill(0x00); // clear screen
 InitAdc;
 txt := ‘ Hz’;
 Glcd_Write_Text(txt, 100, 0, 1);
end;

function Fract2Float(input: integer): real;
begin
   if (input < 0) then
     input := - input;
   result := input/32768.;
end;
procedure WriteData;
var Re, Im, tmpw,
    j, k, l, max : word;
    Rer, Imr, tmpR : real;
begin
 ADPCFG := $FFFF; // PORTB is digital
 j := 2;
 k := 0;
 max := 0;
 freq := 0;
 while k <= 62 do
   begin
     re := Samples[j];
     inc(j);
     im := Samples[j];
     inc(j);
     Rer := Fract2Float(re);
     Imr := Fract2Float(im);

     tmpR := Rer * Rer;
     Rer := tmpR;
     tmpR := Imr * Imr;
     Imr := tmpR;
     tmpR := sqrt(Rer + Imr);

     Rer := tmpR*512.;
     re := Rer;
     re := re and $FF;
     if Re > 63 then
       re := Written[k-1]; // k = 0?

     if Re > max then
       begin
         max := re;
         freq := k;
       end;
    tmpw := Written[k];
    if tmpw <> Re then
      begin
        l := 64 - tmpw;
        while l <= 63 do
          begin
            Glcd_Dot(k, l, 0);
            inc(l);
          end;
         l := 64 - Re;
         while l <= 63 do
          begin
            Glcd_Dot(k, l, 1);
            inc(l);
           end;
        Written[k] := Re;
      end;
   inc(k);
  end;
end;

function readadc: word;
begin
  ADCON1.1 := 1; // start conversion
  while ADCON1.0 = 0 do nop;
  result := ADCBUF0;
end;
procedure SampleInput;
var i: integer;
begin
  // We use PORTB for GLCD as well, so we
  // have to set it to analogue input mode
  ADPCFG := $0000;
  TRISB.10 := 1;
  i :=0;
  while i <= 511 do
    begin
       Samples[i] := readadc;
       inc(i);
       Samples[i] := 0;
       inc(i);
    end;
end;

begin
  Init;
  while true do
   begin
     freq := 0;
     SampleInput;

     FFT(8, @TwiddleCoeff_256, Samples);
     BitReverseComplex(8, Samples);
     WriteData;
     freq := freq * 100;
     WordToStr(freq, txt);
     Glcd_Write_Text(txt, 70, 0, 1);
  end;
end.
Listato 1
Scarica subito una copia gratis

Una risposta

  1. Avatar photo Maurizio 30 Ottobre 2016

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend