ADC Treiber mit ATXMega 384C3

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • Page 4 of 6
Torsten
Benutzer
Avatar
Gender:
Location: Bad Doberan
Age: 59
Posts: 62
Registered: 11 / 2005
Subject:

Re: ADC Treiber mit ATXMega 384C3

 · 
Posted: 09.10.2019 - 11:44  ·  #25
Hallo,

ich habe mal eine Versuch unternommen. Das Ergebnis sieht nicht so schlecht aus. Ich hoffe, eine kleine Anregung für den ADC-Treiber geben zu können.
Es wird kein IRQ benutzt und ich prüfe auch nicht ob der ADC fertig ist. Ich wollte nur mal sehen ob
ich überhaupt ein Ergebnis bekomme. Die Funktion readADC macht nichts weiter als die Register
ADCAResLCH0 und ADCAResHCH0 zu lesen, den Code spare ich mir mal. Es gibt bei dem ADC auch einen SCAN-Mode bei dem dann mehrere Eingänge nacheinander abgearbeitet werden. Die Ergebnisse landen immer in den CH0-Ergebnisregistern. Ob der SCAN-Mode mit dem Freerun-Flag etwas zu tun hat, habe ich nicht verstanden.
Wenn man die ADC's in den verschieden ATXMega-Serien vergleicht, dann werden dort verschiedene Unteschiede in der Version mit und ohne Pipe's aufgelistet. Dazu gibt es auch eine kleine Doku die sich auf die Auswahl der Versionen bezieht, hatte Thorsten auch schon gefunden.
Weiterhin viel Erfolg bei der Arbeit.

Torsten

@ Thorsten und Rolf : Vielen Dank für die Unterstützung!

Code
 // Init ADC_A
  ADCACTRLA       := %00000001; // 2- CH0Start , 1-Flush, 0-Enable

  ADCACTRLB       := %00000000; // 12Bit

  ADCAREFCTRL     := %00000000;  // REF 1V

  ADCAEVCTRL      := %00000000;   // no events input

  ADCAPRESCALER   := %00000111; // clk DIV512

  //
  ADCACH0CTRL     := %00000001; // single-ended pos input signal
  //               //x0000xxx
  ADCACH0MUXCTRL  := %00000000; // pin-0
  //
  ADCACH0INTCTRL  := %00000000;




  EnableInts($87);
  loop
  // Start Messung
  //               //x0000xxx
  ADCACH0MUXCTRL := %00000000; // PortA pin-0
  mdelay(1);
  ADCACH0CTRL := ADCACH0CTRL or $80;  // Start
  mdelay(10);
  temp := readADC;
  writeln(SeroutD0,'ADC 0 '+ inttostr(temp));

  //               //x0000xxx
  ADCACH0MUXCTRL := %00001000; // PortA pin-1
  mdelay(1);
  ADCACH0CTRL := ADCACH0CTRL or $80;  // Start
  mdelay(10);
  temp := readADC;
  writeln(SeroutD0,'ADC 1 '+ inttostr(temp));


  //               //x0000xxx
  ADCACH0MUXCTRL := %00010000; // PortA pin-2
  mdelay(1);
  ADCACH0CTRL := ADCACH0CTRL or $80;  // Start
  mdelay(10);
  temp := readADC;
  writeln(SeroutD0,'ADC 2 '+ inttostr(temp));

  mdelay(1000);
  endloop;
pvs-deck
PowerUser
Avatar
Gender:
Age: 53
Homepage: pvs-deck.de
Posts: 1341
Registered: 02 / 2009
Subject:

Re: ADC Treiber mit ATXMega 384C3

 · 
Posted: 09.10.2019 - 15:47  ·  #26
Hallo Thorsten,

ich bin jetzt soweit das mit meinen Messungen ADC0, ADC1 und ADC2 sauber gemessen werden. Alles über den CH0.

Problem was ich jetzt nur noch habe, der ADC0 wird auf dem ADC3 gespiegelt, ich komme nicht an die richtigen Werte/Messungen vom ADC3.

Code
program X384_Test;
{ $NOSHADOW}
{ $WG}                     {global Warnings off}

Device = xmega384C3, VCC = 3.3;

Define_Fuses
  Override_Fuses;
  NoteBook               = D;
  COMport                = USB;
//   LockBits0 = [BLBB0, BLBB1, LB0, LB1];   // Sichere Boot und MainApp gegen das auslesen
  LockBits0     = [];                        // Für Debug ISP muss dies leer sein !!!
  FuseBits0     = [];
//  FuseBits1   = [ WDPER0, WDPER3 ];        // Watchdog   0:3 / 0110 512CLK 0.512s
  FuseBits1     = [];                        // Watchdog   leer nutze Hardwarewatchdog
// DEBUG   FuseBits2     = [BootRst];                    // Bootloader Einsprung, sonst springt er nicht in den Bootloader
  FuseBits2     = [];                    //
  // Brown-out is obligatory with USB !!!
  FuseBits5     = [BodLevel0,BodLevel2, BodAct0, EESAVE]; //  2.6V:

  ProgFuses     = true;
  ProgFlash     = TRUE;  // program Flash
  ProgEEprom    = false; // program EEprom sonst werden die Einstellungen überschrieben !!!
  AutoRelease   = true;  // Release Target    // Wichtig für Programmierung über UPP !!


//----------------------------

import SysTick,
       SerPortD0;

from System import Processes, longword, longint;

define
  // XMega USB must use the internal 32MHz OSC. So the system must use the 2MHz OSC
Define
  // XMega USB must use the internal 32MHz OSC. So the system must use the 2MHz OSC
//   OSCtype                = int2MHz, PLLmul = 16, prescB = 1, prescC = 1;        // 32MHz                          f
  // OSCtype                = int2MHz, PLLmul = 20, prescB = 1, prescC = 1, overdrive; // 40 MHz
  // OSCtype                = int2MHz, PLLmul = 24, prescB = 1, prescC = 1, overdrive; // 48 MHz
  OSCtype                = int2MHz, PLLmul = 31, prescB = 1, prescC = 1, overdrive; // 62 MHz

  SysTick                = 10;                 // msec
  StackSize              = 1024, iData;
  FrameSize              = 512, iData;
  Scheduler              = iData;

  
  SerPortD0              = 57600, Databit8,parNone, Stop1;
  RxBufferD0             = 255, iData;
  TxBufferD0             = 255, iData;
  SerCtrlD0              = PortB, 0, negative; {control line for RS485 driver}




implementation

{$IDATA}

{------------------------------------------------------------------------------}
{ Type Declarations }
type

{--------------------------------------------------------------}
{ Const Declarations }
const

{--------------------------------------------------------------}
{ Var Declarations }
{$IDATA}
var
  st            : STRING[15];
  ww0            : word;
  ww1            : word;
  ww2            : word;
  ww3            : word;
  adPort         : byte;
  Zahl          : word;
  Zahl2          : word;
  xFor           : integer;
{--------------------------------------------------------------}


// DebugOut
procedure DebugOut( OutStr : String[100] );
var
 xc : integer;
begin
  Writeln(SerOutD0,OutStr);
end; //Ende Debug Out



{--------------------------------------------------------------}
{ Main Program }
{$IDATA}
begin

DebugOut('InitADCA...');

//  INIT ADC
  ADCACTRLB     := $00;   // Auflösung auf 12bit und rechtsbündig
  ADCAREFCTRL   := $10;   // INTVCC / 1.6
//  ADCAREFCTRL   := %00000100;   // INTVCC/2

  ADCAPRESCALER := %00000111;   // ADCAPRESCALER auf 512
  ADCACTRLA.0   := true;  // Enable ADCA
  ADCAEVCTRL    := %00000000;   // no events input
  
// INIT CH0
DebugOut('InitPortpin...');
 // PIN0CTRLA:= %01011000;  // pullup und INVERT
  DDRA.0:= 0;  // 0=EINGANG  1=Ausgang
  DDRA.1:= 0;  // 0=EINGANG  1=Ausgang
  DDRA.2:= 0;  // 0=EINGANG  1=Ausgang
  DDRA.3:= 0;  // 0=EINGANG  1=Ausgang

DebugOut('InitADCCH0...');
  ADCACH0CTRL    := $01; // singleended
  ADCACH0MUXCTRL := $0; // MUX CTRL MAXPOS ADC0
  ADCACH0CTRL    := ADCACH0CTRL OR $01; // singleended
  ADCACH0INTCTRL := %00000000;
  
  ADCACH0CTRL.7  := true;    // Starte Messung

  EnableInts($87);


mDelay(50);
DebugOut('Start loop...');
  loop
  
//Messung abgeschlossen?
if ADCACH0INTFLAG.0 then
    ADCACH0INTFLAG.0:=false;  // Flag reset

    // PORTPIN ADC0
     if    adPort = 0  then
       LO(ww0):= ADCACH0RESL;    // Ziehe Werte
        HI(ww0):= ADCACH0RESH;
        inc(xFor);
         if xFor >=50 then
            ADCACTRLA.1   := true;  // flush
             inc(adPort);
              ADCACH0MUXCTRL := %00001000; // MUX CTRL MAXPOS ADC1 nächster Port
          xFor:=0;
         endif;

    // PORTPIN ADC1
     elsif adPort = 1  then
       LO(ww1):= ADCACH0RESL;    // Ziehe Werte
        HI(ww1):= ADCACH0RESH;
        inc(xFor);
         if xFor >=50 then

            ADCACTRLA.1   := true;  // flush

         inc(adPort);
          ADCACH0MUXCTRL := %00010000; // MUX CTRL MAXPOS ADC2 nächster Port

          xFor:=0;
         endif;

    // PORTPIN ADC2
     elsif adPort = 2  then
       LO(ww2):= ADCACH0RESL;    // Ziehe Werte
        HI(ww2):= ADCACH0RESH;
        inc(xFor);
         if xFor >=50 then

            ADCACTRLA.1   := true;  // flush

         inc(adPort);
          ADCACH0MUXCTRL := %00011000; // MUX CTRL MAXPOS ADC3 nächster Port

          xFor:=0;
         endif;

    // PORTPIN ADC3
     elsif adPort >= 3  then
       LO(ww3):= ADCACH0RESL;    // Ziehe Werte
        HI(ww3):= ADCACH0RESH;
        inc(xFor);
         if xFor >=50 then

            ADCACTRLA.1   := true;  // flush

         inc(adPort);
          ADCACH0MUXCTRL := %00000000; // MUX CTRL MAXPOS ADC0 nächster Port

          xFor:=0;
         endif;

     endif;
       // mDelay(50);
        //mDelay(200);
          ADCACH0CTRL.7  := true;    // Starte neue Messung

endif;

// TEST ADC Zeitverzögerung für Ausgabe ohne freilauf zu blockieren
if Zahl <= 65500 then
  Zahl:= Zahl +1;
else
  Zahl2:= Zahl2 +1;
endif;

if (Zahl >= 65500) AND (Zahl2 = 0) then
 Zahl2:=1;



endif;


if (Zahl2 >= 65500) AND (Zahl2 <> 0) then
      DebugOut('  ');
      DebugOut('-------------');
      st:= 'B0: ' + IntToStr(ww0 : 6);
      DebugOut(st);
      st:= 'B1: ' + IntToStr(ww1 : 6);
      DebugOut(st);
      st:= 'B2: ' + IntToStr(ww2 : 6);
      DebugOut(st);
      st:= 'B3: ' + IntToStr(ww3 : 6);
      DebugOut(st);

 Zahl:=0;
 Zahl2:=0;

endif;



  endloop;

end X384_Test.


Anbei mein Testprojekt, vielleicht kannst Du es mal mit Deinen Treiber abgleichen, so das wenigstens die ADCs 0 bis 2 mit Deinem Treiber laufen. Vielleicht fällt Dir auch noch was dabei auf.

Im Moment befürchte ich einen BUG im Chip für das lesen des ADC3, ich hab es an 3 Boards getestet, bei allen das selbe, der ADC0 wird auf den ADC3 gespiegelt.

Thorsten
Attachments
Filename: 20191009_X384_Test.zip
Filesize: 83.02 KB
Title: XMega384C3_ADC
Information: XMega384C3_ADC
Download counter: 51
Torsten
Benutzer
Avatar
Gender:
Location: Bad Doberan
Age: 59
Posts: 62
Registered: 11 / 2005
Subject:

Re: ADC Treiber mit ATXMega 384C3

 · 
Posted: 09.10.2019 - 18:42  ·  #27
Hallo Thorsten,

wenn ich nichts übersehen habe, so müsste in deinem Code ein Fehler stecken.
Die Variable adPort muss doch bestimmt auf 0 gesetzt werden, in dem Bereich siehe Codebox. Es wird somit Port 0 vom ADC gelesen, das Programm speichert ihn dann in ww3.

Torsten

Code
// PORTPIN ADC3
     elsif adPort >= 3  then
       LO(ww3):= ADCACH0RESL;    // Ziehe Werte
        HI(ww3):= ADCACH0RESH;
        inc(xFor);
         if xFor >=50 then

            ADCACTRLA.1   := true;  // flush

         inc(adPort);    !!! hier könnte der Fehler stecken !!!
          ADCACH0MUXCTRL := %00000000; // MUX CTRL MAXPOS ADC0 nächster Port

          xFor:=0;
         endif;

     endif;
       // mDelay(50);
        //mDelay(200);
          ADCACH0CTRL.7  := true;    // Starte neue Messung
endif;
pvs-deck
PowerUser
Avatar
Gender:
Age: 53
Homepage: pvs-deck.de
Posts: 1341
Registered: 02 / 2009
Subject:

Re: ADC Treiber mit ATXMega 384C3

 · 
Posted: 10.10.2019 - 10:52  ·  #28
Hallo Torsten,

ja, die folgende Zeile ist wohl beim bereinigen des Codes verlorengegangen :-D Danke

Code
  if adPort >=4 then adPort:=0;endif;



Jetzt gehen alle 4 PortPins, das war jetzt noch der letzte Schliff, hier nochmal der komplette TestCode

Code
program X384_Test;
{ $NOSHADOW}
{ $WG}                     {global Warnings off}

Device = xmega384C3, VCC = 3.3;

Define_Fuses
  Override_Fuses;
  NoteBook               = D;
  COMport                = USB;
//   LockBits0 = [BLBB0, BLBB1, LB0, LB1];   // Sichere Boot und MainApp gegen das auslesen
  LockBits0     = [];                        // Für Debug ISP muss dies leer sein !!!
  FuseBits0     = [];
//  FuseBits1   = [ WDPER0, WDPER3 ];        // Watchdog   0:3 / 0110 512CLK 0.512s
  FuseBits1     = [];                        // Watchdog   leer nutze Hardwarewatchdog
// DEBUG   FuseBits2     = [BootRst];                    // Bootloader Einsprung, sonst springt er nicht in den Bootloader
  FuseBits2     = [];                    //
  // Brown-out is obligatory with USB !!!
  FuseBits5     = [BodLevel0,BodLevel2, BodAct0, EESAVE]; //  2.6V:

  ProgFuses     = true;
  ProgFlash     = TRUE;  // program Flash
  ProgEEprom    = false; // program EEprom sonst werden die Einstellungen überschrieben !!!
  AutoRelease   = true;  // Release Target    // Wichtig für Programmierung über UPP !!


//----------------------------

import SysTick,
       SerPortD0;

from System import Processes, longword, longint;

define
  // XMega USB must use the internal 32MHz OSC. So the system must use the 2MHz OSC
Define
  // XMega USB must use the internal 32MHz OSC. So the system must use the 2MHz OSC
//   OSCtype                = int2MHz, PLLmul = 16, prescB = 1, prescC = 1;        // 32MHz                          f
  // OSCtype                = int2MHz, PLLmul = 20, prescB = 1, prescC = 1, overdrive; // 40 MHz
  // OSCtype                = int2MHz, PLLmul = 24, prescB = 1, prescC = 1, overdrive; // 48 MHz
  OSCtype                = int2MHz, PLLmul = 31, prescB = 1, prescC = 1, overdrive; // 62 MHz

  SysTick                = 10;                 // msec
  StackSize              = 1024, iData;
  FrameSize              = 512, iData;
  Scheduler              = iData;

  
  SerPortD0              = 57600, Databit8,parNone, Stop1;
  RxBufferD0             = 255, iData;
  TxBufferD0             = 255, iData;
  SerCtrlD0              = PortB, 0, negative; {control line for RS485 driver}




implementation

{$IDATA}

{------------------------------------------------------------------------------}
{ Type Declarations }
type

{--------------------------------------------------------------}
{ Const Declarations }
const

{--------------------------------------------------------------}
{ Var Declarations }
{$IDATA}
var
  st            : STRING[15];
  ww0            : word;
  ww1            : word;
  ww2            : word;
  ww3            : word;
  adPort         : byte;
  Zahl          : word;
  Zahl2          : word;
  xFor           : integer;
{--------------------------------------------------------------}


// DebugOut
procedure DebugOut( OutStr : String[100] );
var
 xc : integer;
begin
  Writeln(SerOutD0,OutStr);
end; //Ende Debug Out



{--------------------------------------------------------------}
{ Main Program }
{$IDATA}
begin

DebugOut('InitADCA...');

//  INIT ADC
  ADCACTRLB     := $00;   // Auflösung auf 12bit und rechtsbündig
  ADCAREFCTRL   := $10;   // INTVCC / 1.6
//  ADCAREFCTRL   := %00000100;   // INTVCC/2

  ADCAPRESCALER := %00000111;   // ADCAPRESCALER auf 512
  ADCACTRLA.0   := true;  // Enable ADCA
  ADCAEVCTRL    := %00000000;   // no events input
  
// INIT CH0
DebugOut('InitPortpin...');
 // PIN0CTRLA:= %01011000;  // pullup und INVERT
  DDRA.0:= 0;  // 0=EINGANG  1=Ausgang
  DDRA.1:= 0;  // 0=EINGANG  1=Ausgang
  DDRA.2:= 0;  // 0=EINGANG  1=Ausgang
  DDRA.3:= 0;  // 0=EINGANG  1=Ausgang

DebugOut('InitADCCH0...');
  ADCACH0CTRL    := $01; // singleended
  ADCACH0MUXCTRL := $0; // MUX CTRL MAXPOS ADC0
  ADCACH0CTRL    := ADCACH0CTRL OR $01; // singleended
  ADCACH0INTCTRL := %00000000;
  
  ADCACH0CTRL.7  := true;    // Starte Messung

  EnableInts($87);


mDelay(50);
DebugOut('Start loop...');
  loop

  if adPort >=4 then adPort:=0;endif;

  
  
//Messung abgeschlossen?
if ADCACH0INTFLAG.0 then
    ADCACH0INTFLAG.0:=false;  // Flag reset

    // PORTPIN ADC0
     if    adPort = 0  then
       LO(ww0):= ADCACH0RESL;    // Ziehe Werte
        HI(ww0):= ADCACH0RESH;
        inc(xFor);
         if xFor >=50 then
            ADCACTRLA.1   := true;  // flush
             inc(adPort);
              ADCACH0MUXCTRL := %00001000; // MUX CTRL MAXPOS ADC1 nächster Port
          xFor:=0;
         endif;

    // PORTPIN ADC1
     elsif adPort = 1  then
       LO(ww1):= ADCACH0RESL;    // Ziehe Werte
        HI(ww1):= ADCACH0RESH;
        inc(xFor);
         if xFor >=50 then

            ADCACTRLA.1   := true;  // flush

         inc(adPort);
          ADCACH0MUXCTRL := %00010000; // MUX CTRL MAXPOS ADC2 nächster Port

          xFor:=0;
         endif;

    // PORTPIN ADC2
     elsif adPort = 2  then
       LO(ww2):= ADCACH0RESL;    // Ziehe Werte
        HI(ww2):= ADCACH0RESH;
        inc(xFor);
         if xFor >=50 then

            ADCACTRLA.1   := true;  // flush

         inc(adPort);
          ADCACH0MUXCTRL := %00011000; // MUX CTRL MAXPOS ADC3 nächster Port

          xFor:=0;
         endif;

    // PORTPIN ADC3
     elsif adPort >= 3  then
       LO(ww3):= ADCACH0RESL;    // Ziehe Werte
        HI(ww3):= ADCACH0RESH;
        inc(xFor);
         if xFor >=50 then

            ADCACTRLA.1   := true;  // flush

         inc(adPort);
          ADCACH0MUXCTRL := %00000000; // MUX CTRL MAXPOS ADC0 nächster Port

          xFor:=0;
         endif;

     endif;
       // mDelay(50);
        //mDelay(200);
          ADCACH0CTRL.7  := true;    // Starte neue Messung

endif;

// TEST ADC Zeitverzögerung für Ausgabe ohne freilauf zu blockieren
if Zahl <= 65500 then
  Zahl:= Zahl +1;
else
  Zahl2:= Zahl2 +1;
endif;

if (Zahl >= 65500) AND (Zahl2 = 0) then
 Zahl2:=1;



endif;


if (Zahl2 >= 65500) AND (Zahl2 <> 0) then
      DebugOut('  ');
      DebugOut('-------------');
      st:= 'B0: ' + IntToStr(ww0 : 6);
      DebugOut(st);
      st:= 'B1: ' + IntToStr(ww1 : 6);
      DebugOut(st);
      st:= 'B2: ' + IntToStr(ww2 : 6);
      DebugOut(st);
      st:= 'B3: ' + IntToStr(ww3 : 6);
      DebugOut(st);

 Zahl:=0;
 Zahl2:=0;

endif;



  endloop;

end X384_Test.


@rolf; Kannst Du das mal mit Deinen Treiber vergleichen? Ansonsten packe diesen Code etwas abgewandelt für mein Projekt in eine extra Funktion.

Thorsten
Torsten
Benutzer
Avatar
Gender:
Location: Bad Doberan
Age: 59
Posts: 62
Registered: 11 / 2005
Subject:

Re: ADC Treiber mit ATXMega 384C3

 · 
Posted: 10.10.2019 - 12:36  ·  #29
Hallo,

bei dem Studium der Datenblätter ist mir aufgefallen, dass diese Art von ADC auch in anderen Serien der ATXMegas vorhanden ist.
Somit ist zu prüfen, ob der Treiber für diese Bausteine auch passend ist.

Torsten
pvs-deck
PowerUser
Avatar
Gender:
Age: 53
Homepage: pvs-deck.de
Posts: 1341
Registered: 02 / 2009
Subject:

Re: ADC Treiber mit ATXMega 384C3

 · 
Posted: 14.10.2019 - 15:59  ·  #30
Hallo Leute,

ich habe jetzt aus dem TestCodes eine Funktion für mich erstellt, bis der GetADC() vom AVRco funktioniert reicht das erstmal.

Hat Jemand eine Ahnung, wie ich die Kalibrierungswerte aus der Produktion auslesen und für den ADC verwenden kann?

Und gilt das pro PortPin oder nur für den ADC? Ich habe bei einem der 4 PortPins eine stärkere Abweichung.

Thorsten
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: ADC Treiber mit ATXMega 384C3

 · 
Posted: 14.10.2019 - 17:17  ·  #31
Hallo Thorsten
schicke mir bitte mal diese App.
Ich denke das würde mir sehr weiterhelfen.
rolf
Torsten
Benutzer
Avatar
Gender:
Location: Bad Doberan
Age: 59
Posts: 62
Registered: 11 / 2005
Subject:

Re: ADC Treiber mit ATXMega 384C3

 · 
Posted: 14.10.2019 - 17:24  ·  #32
Hallo Thorsten,


AVR1300: Using the AVR XMEGA ADC

auf der Seite 15 stehen zu der Kalibrierung ein paar Dinge.

Torsten
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • Page 4 of 6
Selected quotes for multi-quoting:   0

Registered users in this topic

Currently no registered users in this section

The statistic shows who was online during the last 5 minutes. Updated every 90 seconds.
MySQL Queries: 16 · Cache Hits: 15   141   156 · Page-Gen-Time: 0.029483s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI