ATXmega384C3 Timer zu Event zu ADC zu DMA

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • ATXmega384C3 Timer zu Event zu ADC zu DMA

      Hallo zusammen,

      ich möchte auf dem ATXmega384C3 eine gewisse Anzahl von Messwerten alle 250µ einlesen, ohne die die CPU zu belasten.
      Die Idee ist: Timer_ovl befeuert alle 250µ ein Event -> triggert ADC, der die Messwerte per DMA in den Speicher schiebt und dann der Int vom DMA "fertig" meldet.
      Leider funktioniert das Zusammenspiel anscheinend nicht richtig.
      Der Int vom DMA kommt sofort und im Messwerte-Array stehen komische Werte.
      Ich vermute da eine fehlerhafte Konfiguration

      Hat jemand ein simples Beispiel dafür?

      Mein bisheriger Ansatz

      BASCOM-Quellcode

      1. Config Priority = Static , Vector = Application , Lo = Enabled , Hi = Enabled ', Med = Enabled
      2. Config Event_system = Dummy , Mux0 = Tcc0_ovf ' Event Channel0 wird mit Tcc0_ovf getriggert
      3. On Dma_ch0 Dma_ch0_int ' DMA Ch0 ISR
      4. Config Dma = Enabled , Doublebuf = Disabled , Cpm = Ch01rr23 ' enable DMA,
      5. Adca_evctrl = &B00000000 'kein Event start
      6. ' 250µs-Timer für Spannungsmessung
      7. Tcc0_per = 8000
      8. Config Tcc0 = Normal , Prescale = 1
      9. Config Adca = Single , Convmode = Unsigned , Resolution = 12bit , Dma = Ch01 , Event_channel = Ch0123 , Event_mode = Ch0 , Prescaler = 16 , Tempref = Disabled , Ch0_inp = Single_ended , Mux0 = &B0_0000_000
      10. Adca_refctrl = &B0_000_00_1_0 ' Interne 1V-Referenz - Bandgap ein - Tempref aus
      11. '_______________________________________________________________________________
      12. ' ADC-Messung über die CPU
      13. Sub Adcmessung(byval Channel As Byte , Byval Samples As Byte)
      14. ' Channel=0 PA.0 HV-U
      15. ' Channel=1 PA.1 HV-I
      16. ' Channel=2 PA.2 +24V-Versorgung
      17. ' Channel=3 PA.3 +3.3V-Versorgung
      18. ' Channel=4 PA.4 GND für Offsetmessung
      19. ' Channel=7 PA.7 Boardrevision
      20. ' ADCA auf richtigen Eingang setzen und DMA anpassen
      21. Select Case Channel ' auf welchem Kanal und wie messen
      22. Case Channel_hv_u ' 0...250V AC messen
      23. Adca_ch0_muxctrl = &B0_0000_000 ' auf richtigem Eingang messen
      24. If Samples = 80 Then ' bei Netztspannung 50Hz -> 80 Messungen
      25. Config Dmach0 = Enabled , Burstlen = 2 , Chanrpt = Disabled , Tci = Lo , Eil = Lo , Singleshot = Enabled , _
      26. Sar = Burst , Sam = Fixed , Dar = Transaction , Dam = Inc , Trigger = &H10 , Btc = 160 , Repeat = 0 , Sadr = Varptr(adca_ch0_res) , Dadr = Varptr(adcwert(1))
      27. Else ' bei Netztspannung 60Hz -> 67 Messungen
      28. Config Dmach0 = Enabled , Burstlen = 2 , Chanrpt = Disabled , Tci = Lo , Eil = Lo , Singleshot = Enabled , _
      29. Sar = Burst , Sam = Fixed , Dar = Transaction , Dam = Inc , Trigger = &H10 , Btc = 134 , Repeat = 0 , Sadr = Varptr(adca_ch0_res) , Dadr = Varptr(adcwert(1))
      30. End If
      31. Case Channel_gnd ' ADC Offset messen
      32. Adca_ch0_muxctrl = &B0_0100_000 ' auf richtigem Eingang messen
      33. Config Dmach0 = Enabled , Burstlen = 2 , Chanrpt = Disabled , Tci = Lo , Eil = Lo , Singleshot = Enabled , _
      34. Sar = Burst , Sam = Fixed , Dar = Transaction , Dam = Inc , Trigger = &H10 , Btc = 20 , Repeat = 0 , Sadr = Varptr(adca_ch0_res) , Dadr = Varptr(adcwert(1))
      35. Case Channel_boardrevision ' Boardrevision messen
      36. Adca_ch0_muxctrl = &B0_0111_000 ' auf richtigem Eingang messen
      37. Config Dmach0 = Enabled , Burstlen = 2 , Chanrpt = Disabled , Tci = Lo , Eil = Lo , Singleshot = Enabled , _
      38. Sar = Burst , Sam = Fixed , Dar = Transaction , Dam = Inc , Trigger = &H10 , Btc = 20 , Repeat = 0 , Sadr = Varptr(adca_ch0_res) , Dadr = Varptr(adcwert(1))
      39. End Select
      40. Zeittaktadcmessung = 1 ' Messung läuft
      41. Enable Tcc0_ovf , Lo ' Timer-IRQ freigeben
      42. Adca_evctrl = &B000_00_001 'ADC ist bereit...ADCA start über event CH.0
      43. Evsys_ch0mux = &B1100_0000 'eventsystem (CH.0) triggert bei TCC0 overflow
      44. Do
      45. Loop Until Zeittaktadcmessung = 0
      46. End Sub
      47. '___ DMA Ch0 ISR wenn Daten von MainCPU im SRAM sind ___________________________
      48. '
      49. Dma_ch0_int:
      50. Print #1 , "Dma_ch0_int"
      51. Reset Dma_channel_0_error
      52. If Dma_intflags.0 = 1 Then 'Channel 0 Transaction Interrupt Flag
      53. Set Dma_intflags.0 'Clear the Channel 0 Transaction Complete flag
      54. Zeittaktadcmessung = 0
      55. Evsys_ch0mux = 0 'eventsystem (CH.0) triggert bei TCC1 overflow = AUS
      56. Disable Tcc0_ovf ' Timer-IRQ sperren
      57. 'Reset Testpin
      58. End If
      59. If Dma_intflags.4 = 1 Then 'Channel 0 ERROR Flag
      60. Set Dma_intflags.4 'Clear the flag
      61. Set Dma_channel_0_error 'Channel 0 Error
      62. End If
      63. Return
      Alles anzeigen

      Danke und Gruß
    • Hallo zusammen,

      hier mal ein kleines update, da ich ein Bisschen weiter gekommen bin...

      Als Erstes muss das Event im ADC bei der ersten Konfiguration ausgeschaltet bleiben,
      da es ja erst gezielt aktiviert wird.

      Quellcode

      1. Config Adca = Single , Convmode = Unsigned , Resolution = 12bit , Dma = Ch01 , Event_mode = None , Prescaler = 16 , Tempref = Disabled , Ch0_inp = Single_ended , Mux0 = &B0_0000_000
      Dann war der DMA nicht richtig konfiguriert


      Quellcode

      1. '_______________________________________________________________________________
      2. ' ADC-Messung über die CPU
      3. Sub Adcmessung(byval Channel As Byte , Byval Samples As Byte)
      4. Print #1 , "Adcmessung"
      5. Print #1 , "Channel:" ; Channel
      6. Print #1 , "Samples:" ; Samples
      7. ' Channel=0 PA.0 HV-U
      8. ' Channel=1 PA.1 HV-I
      9. ' Channel=2 PA.2 +24V-Versorgung
      10. ' Channel=3 PA.3 +3.3V-Versorgung
      11. ' Channel=4 PA.4 GND für Offsetmessung
      12. ' Channel=7 PA.7 Boardrevision
      13. ' ADCA auf richtigen Eingang setzen und DMA anpassen
      14. Select Case Channel ' auf welchem Kanal und wie messen
      15. Case Channel_hv_u ' 0...250V AC messen
      16. Adca_ch0_muxctrl = &B0_0000_000 ' auf richtigem Eingang messen
      17. If Samples = 80 Then ' bei Netztspannung 50Hz -> 80 Messungen
      18. Print #1 , "Channel_hv_u 80Samples"
      19. Config Dmach0 = Enabled , Burstlen = 2 , Chanrpt = Disabled , Tci = Lo , Eil = Lo , Singleshot = Enabled , _
      20. Sar = Burst , Sam = Inc , Dar = Block , Dam = Inc , Trigger = &H10 , Btc = 160 , Repeat = 0 , Sadr = Varptr(adca_ch0_res) , Dadr = Varptr(adcwert(1))
      21. ' Config Dmach0 = Enabled , Burstlen = 2 , Chanrpt = Disabled , Tci = Lo , Eil = Lo , Singleshot = Enabled , _
      22. ' Sar = Burst , Sam = Fixed , Dar = Transaction , Dam = Inc , Trigger = &H10 , Btc = 160 , Repeat = 0 , Sadr = Varptr(adca_ch0_res) , Dadr = Varptr(adcwert(1))
      23. Else ' bei Netztspannung 60Hz -> 67 Messungen
      24. Print #1 , "Channel_hv_u 67Samples"
      25. Config Dmach0 = Enabled , Burstlen = 2 , Chanrpt = Disabled , Tci = Lo , Eil = Lo , Singleshot = Enabled , _
      26. Sar = Burst , Sam = Inc , Dar = Block , Dam = Inc , Trigger = &H10 , Btc = 134 , Repeat = 0 , Sadr = Varptr(adca_ch0_res) , Dadr = Varptr(adcwert(1))
      27. ' Config Dmach0 = Enabled , Burstlen = 2 , Chanrpt = Disabled , Tci = Lo , Eil = Lo , Singleshot = Enabled , _
      28. ' Sar = Burst , Sam = Fixed , Dar = Transaction , Dam = Inc , Trigger = &H10 , Btc = 134 , Repeat = 0 , Sadr = Varptr(adca_ch0_res) , Dadr = Varptr(adcwert(1))
      29. End If
      30. Case Channel_gnd ' ADC Offset messen
      31. Print #1 , "Channel_gnd"
      32. Adca_ch0_muxctrl = &B0_0100_000 ' auf richtigem Eingang messen
      33. Config Dmach0 = Enabled , Burstlen = 2 , Chanrpt = Disabled , Tci = Lo , Eil = Off , Singleshot = Enabled , _
      34. Sar = Burst , Sam = Inc , Dar = Block , Dam = Inc , Trigger = &H10 , Btc = 20 , Repeat = 1 , Sadr = Varptr(adca_ch0_res) , Dadr = Varptr(adcwert(1))
      35. ' Config Dmach0 = Enabled , Burstlen = 2 , Chanrpt = Disabled , Tci = Lo , Eil = Lo , Singleshot = Enabled , _
      36. ' Sar = Burst , Sam = Fixed , Dar = Transaction , Dam = Inc , Trigger = &H10 , Btc = 20 , Repeat = 0 , Sadr = Varptr(adca_ch0_res) , Dadr = Varptr(adcwert(1))
      37. Case Channel_boardrevision ' Boardrevision messen
      38. Print #1 , "Channel_boardrevision"
      39. Adca_ch0_muxctrl = &B0_0111_000 ' auf richtigem Eingang messen
      40. Config Dmach0 = Enabled , Burstlen = 2 , Chanrpt = Disabled , Tci = Lo , Eil = Lo , Singleshot = Enabled , _
      41. Sar = Burst , Sam = Inc , Dar = Block , Dam = Inc , Trigger = &H10 , Btc = 20 , Repeat = 0 , Sadr = Varptr(adca_ch0_res) , Dadr = Varptr(adcwert(1))
      42. ' Config Dmach0 = Enabled , Burstlen = 2 , Chanrpt = Disabled , Tci = Lo , Eil = Lo , Singleshot = Enabled , _
      43. ' Sar = Burst , Sam = Fixed , Dar = Transaction , Dam = Inc , Trigger = &H10 , Btc = 20 , Repeat = 0 , Sadr = Varptr(adca_ch0_res) , Dadr = Varptr(adcwert(1))
      44. End Select
      45. Print #1 , "los gehts"
      46. Zeittaktadcmessung = 1 ' Messung läuft
      47. Set Dma_intflags.0 'Clear the Channel 0 Transaction Complete flag
      48. Tcc0_ctrlfset = &B00001000
      49. Enable Tcc0_ovf , Lo ' Timer-IRQ freigeben
      50. Adca_evctrl = &B000_00_001 'ADC ist bereit...ADCA start über event CH.0
      51. Evsys_ch0mux = &B1100_0000 'eventsystem (CH.0) triggert bei TCC0 overflow
      52. Do
      53. Loop Until Zeittaktadcmessung = 0
      54. End Sub
      Alles anzeigen
      Jetzt funktioniert es prinzipiell schon mal, wie es soll... a_22_9ac28a82
      Allerdings kommt es zwischendurch zu falschen Messwerten bzw. abwechselnde Messwerte 0 und 2047 a_56_df238249
    • So läuft's bei mir wie geschmiert:
      Mit Xmega256A3BU, übertaktet zu 38MHz. Geht mit C3 genauso, nur viel langsamer weil kein ADC-Pipelining.
      Codeschnitzel:
      Ich triggere DMA-Transfer mit AC0 Comparator. Ab Zeile 14 sind zwei ineindergeschachtelte Schleifen, um etwas zeitversetzt viele Male die ADC(Zeit)-werte aufzusummieren.
      Wichtig ist das config DMA vor jedem DMA-Lauf neu aufzurufen (kostet kaum Zeit).

      Quellcode

      1. Config Adca = Free , Convmode = Signed , Resolution = 12bit , Dma = Ch01 , _
      2. Reference = Int1v , Prescaler = 32 , Sweep = Ch0 , Event_mode = None , Event_channel = Ch0123 , _
      3. Ch0_gain = 2 , Ch0_inp = Diffwgain , Mux0 = &H33 ''&B0110_011=x33 adc6,7 diff w gain
      4. Config Priority = Static , Vector = Application , Lo = Enabled
      5. Enable Interrupts
      6. Start Adca
      7. Dim Dest_adress As Word , Dest_adress_l , Dest_adress_h As Byte
      8. Dest_adress = Varptr(samples(1))
      9. Dest_adress_l = Low(dest_adress)
      10. Dest_adress_h = High(dest_adress)
      11. Bitwait Aca_status.4 , Set
      12. Config Dmach0 = Enabled , Burstlen = 2 , Chanrpt = Enabled , Tci = Lo , Eil = Lo , Singleshot = Enabled , _
      13. Sar = Burst , Sam = Inc , Dar = None , Dam = Inc , Trigger = &H10 , Btc = 512 , Repeat = 1 , Sadr = Varptr(adca_ch0_res) , Dadr = Varptr(samples(1))
      14. Do
      15. I3 = Memcopy(null , Summenarray(1) , Sample_count2 , 2)
      16. J = 0
      17. For I = 1 To Aussere_summe
      18. ' Print #1 , "I=" ; I ; "---------------------------------"
      19. I3 = Memcopy(null , Summenarray1(1) , Sample_count2 , 2)
      20. For L = 1 To Innere_summe
      21. Bitwait Aca_status.0 , Set
      22. Config Dmach0 = Enabled , Burstlen = 2 , Chanrpt = Enabled , Tci = Lo , Eil = Lo , Singleshot = Enabled , _
      23. Sar = Burst , Sam = Inc , Dar = None , Dam = Inc , Trigger = &H10 , Btc = Sample_count2 , Repeat = 1 , Sadr = Varptr(adca_ch0_res) , Dadr = Varptr(samples(1))
      24. ....
      25. next L
      26. ....
      27. Loop
      Alles anzeigen
    • Wow. Die Likes explodieren ja gerade....
      Ach, noch 'nen Tip:
      Alternativ zum Taktreduzieren sollte man die ADC-Beschaltung so niederohmig machen wie möglich.
      Ich habe 1 oder 2k Widerstand parallel zum ADC-Pin gelegt (bzw. zwischen differentielle Eingänge, die sollte man eh benutzen).
      Noch besser wären 100 Ohm....

      Übrigens: Mir wurde der Xmeg256A3 zu eng.
      Gehe jetzt fremd.
      Fand einen wunderschönen schnellen Osci mit 256Ms/s Real.time FFT (!!) für die STM32 Bluepill
      (mein Datenaufsummieren wirkt wie Tiefpass, und den könnte man natürlich auch mit FFT realisieren).
      Die Bluepill läuft normal mit 72MHz und hat 20kB Ram Speicher.

      Aber wenn man den wohlbehüteten Bereich der AVRs und Bascom verlässt, wird's sofort gruselig.
      Die allerwenigsten Sachen funktionieren direkt. Alles ist im Fluss... Immerhin lässt sich die Bluepill (aber auch andere) in Arduino programmieren.
      Wenn's interessiert, kann ich's mal posten.
    • elektron schrieb:

      Übrigens: Mir wurde der Xmeg256A3 zu eng.
      Gehe jetzt fremd.
      Fand einen wunderschönen schnellen Osci mit 256Ms/s Real.time FFT (!!) für die STM32 Bluepill
      (mein Datenaufsummieren wirkt wie Tiefpass, und den könnte man natürlich auch mit FFT realisieren).
      Die Bluepill läuft normal mit 72MHz und hat 20kB Ram Speicher.

      Aber wenn man den wohlbehüteten Bereich der AVRs und Bascom verlässt, wird's sofort gruselig.
      Die allerwenigsten Sachen funktionieren direkt. Alles ist im Fluss... Immerhin lässt sich die Bluepill (aber auch andere) in Arduino programmieren.
      Wenn's interessiert, kann ich's mal posten.
      Ich bin in einer ähnlichen Situation.
      Der Xmega384C3 ist für meine Anwendung auch zu klein.
      Da Microchip mir auf der vorletzten Embedded ganz klar mitgeteilt hat, dass es keine neuen, größeren AVRs geben wird,
      habe ich hier ein STM32F469-Disco Board hier liegen.
      Der gute Mann war so begeistert von seinen Tinys, dass er überhaupt nicht verstand,
      das ich was großes brauche, was mehr wie im ARM hat.
      Das ist, wie Du schon sagtest, eine andere Hausnummer. =O
      Zudem ist mein "C" durch jahrelange Bascom-Nutzung ein wenig eingerostet.
      Über Deine Erfahrungen würde ich mich sehr freuen, auch wenn es nicht gerade in ein Bascom Forum passen mag ;)
    • ich werde mal beim admin beantragen, ein unterforum "fremdgehen" einzurichten.
      Bis dahin hier.
      Die bluepill ist schon mal etwas "größer" als jeder xmega und kostet 2-3 €.
      Schau mal google.com/url?q=https://githu…Vaw3uevgikzhTKyG8KdFoTDGK
      Ich hab ein f429 disco board. Dafür hat jemand auf Mikrocontroller.net eine ganze Menge schöne Beispiele eingestellt. U.a auch einen schönen oszi und packman...
      mikrocontroller.bplaced.net/wordpress/?page_id=752
      Gibt's ähnliches (oszi) auch für den 469er (suchen).
    • elektron schrieb:

      ich werde mal beim admin beantragen, ein unterforum "fremdgehen" einzurichten.
      Wozu? Dafür gibts doch mikrocontroller.net. Zusätzliche Unterforen machen aus diesem speziellen Forum nur genauso einen "Gemischtwarenladen" wie andere Foren schon sind. Und dazu brauchs nicht auch noch das bascomforum.

      Also Admins bitte das Forum nicht weiter aufblähen.
      Wem ich nicht ausdrücklich widerspreche, der darf das bis auf Widerruf als "Gefällt mir" verstehen.