ADC ohne Interrupt

    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!

    • ADC ohne Interrupt

      Hi zusammen,
      ich möchte den ADC direkt, so schnell wie möglich in der Hauptschleife abfragen ohne Interrupt.

      Würde das so funktionieren?

      Dort wird so lange gewartet bis eine Wandlung fertig ist.
      Bitwait Adcsra.adsc

      Dann lese ich die Register und Starte den ADC wieder.

      Bisher habe ich das mit Interrupt gemacht ADIE. Aber ich möchte mir den Sprung sparen.
      Ich kann gerne im Programm warten, ich muss nur schnell Messen.

      BASCOM-Quellcode

      1. $regfile = "m328PBdef.dat" 'ATMega 328PB
      2. Const Speed_cry = 0 '0=1,8 1=7,3 2=11,0 3=14,7
      3. Const Build = "Version 1.10.002" 'Versionsnummer
      4. $baud = 19200 '115200
      5. $hwstack = 150
      6. $swstack = 150
      7. $framesize = 150
      8. #if Speed_cry = 0 : Const _crystal = 1843200 : #endif 'Quarz: 1.8432 MHz
      9. #if Speed_cry = 1 : Const _crystal = 7372800 : #endif 'Quarz: 7.3728 MHz
      10. #if Speed_cry = 2 : Const _crystal = 11059200 : #endif 'Quarz: 11.0592 MHz
      11. #if Speed_cry = 3 : Const _crystal = 14745600 : #endif 'Quarz: 14.7456 MHz
      12. $crystal = _crystal
      13. Config Single = Scientific , Digits = 3
      14. Config Submode = New
      15. Config Base = 1 'arrays start
      16. Dim Adc_finish As Bit , Loop_count As Byte , Impuls As Word
      17. Dim Wrdadc As Word
      18. Dim Bytadclo As Byte At Wrdadc Overlay
      19. Dim Bytadchi As Byte At Wrdadc + 1 Overlay
      20. Dim Bytadmux_0 As Byte , Bytadmux_3 As Byte
      21. Dim Bytadcsra As Byte , Admux_switch As Bit , Bytadchannel As Byte , Wrdadc_vorgabe_temp As Word
      22. Dim Wrdadc_vorgabe As Eram Word At &H179
      23. Wrdadc_vorgabe_temp = Wrdadc_vorgabe
      24. If Wrdadc_vorgabe_temp >= 1025 Then
      25. Wrdadc_vorgabe = 150
      26. End If
      27. Wrdadc_vorgabe_temp = Wrdadc_vorgabe
      28. 'Wait_vorgabe = 40
      29. '--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      30. Bytadmux_0 = &B01000000
      31. '// 01000000
      32. '// ||||||||---| bit 0: MUX0 =0000: ADC0 is input =0001: ADC1 is input
      33. '// |||||||----| bit 1: MUX1 =0010: ADC2 is input =0011: ADC3 is input
      34. '// ||||||-----| bit 2: MUX2 =0100: ADC4 is input =0101: ADC5 is input
      35. '// |||||------| bit 3: MUX3 =0110: ADC6 is input =0111: ADC7 is input
      36. '// ||||
      37. '// ||||-------- bit 4: MUX4
      38. '// |||--------- bit 5: ADLAR =0: data right adjusted =1: data left adjusted
      39. '// ||
      40. '// ||---------| bit 6: REFS0 =00: Reference = AREF =01: Reference = AVCC
      41. '// |----------| bit 7: REFS1 =10: Int. 1.10V Reference =11: Int. 2.56V Reference
      42. Admux = Bytadmux_0 'ADC Multiplexer Selection Register
      43. '--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      44. '
      45. '--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      46. '1 843 200Hz / 200.000Hz(200kHz) = 9,216
      47. 'Da mit 200kHz gerechnet wurde(Maximale Frequenz), nimmt man den nächst höheren Wert Teiler, also 16.
      48. '1 843 200Hz / 16 = 115.200Hz = 115kHz So erhält man bei 1,843200 MHz einen Prescaler von 16 und eine Frequenz von 115kHz.
      49. Bytadcsra = &B10000100
      50. '// 10001100 'ADC prescaler 50 bis 200kHz
      51. '// ||||||||---| bit 0: ADPS0 =000: Div. factor 2 =001: Div. factor 2
      52. '// |||||||----| bit 1: ADPS1 =010: Div. factor 4 =011: Div. factor 8 =100: Div. factor 16
      53. '// ||||||-----| bit 2: ADPS2 =101: Div. factor 32 =110: Div. factor 64 =111: Div. factor 128
      54. '// |||||
      55. '// |||||------- bit 3: ADIE =1: Conversion completion interrupt activated
      56. '// ||||-------- bit 4: ADIF =1: when conversion completed ---------------------------------|
      57. '// |||--------- bit 5: ADFR =1: Free Running"-Modus | Auto trigger enabled |
      58. '// ||---------- bit 6: ADSC =1: Start ADC |
      59. '// |----------- bit 7: ADEN =1: Enable ADC |
      60. Adcsra = Bytadcsra ' |
      61. ' |
      62. ' |
      63. 'Wenn eine Wandlung beendet wurde wird dieses Bit auf 1 gesetzt.
      64. 'Eine eventuell aktivierte Interruptroutine des ADCs setzt dieses Bit
      65. 'wieder auf 0, sobald die entsprechende Interruptroutine aufgerufen wurde.
      66. 'Wird ohne Interrupts gearbeitet kann mittels schreiben einer 1 auf dieses Bit das Bit zurückgesetzt werden.
      67. '--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      68. '--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      69. Sreg.7 = 1 'Enable interrupts
      70. '----------------
      71. Bytadchannel = 0 'First ADC channel
      72. Admux = Bytadmux_0 Or Bytadchannel 'Set MUX channel
      73. '----------------
      74. Set Adcsra.aden 'Switch on ADC
      75. Set Adcsra.adsc 'Start ADC
      76. '--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      77. Do
      78. Bitwait Adcsra.adsc , Reset 'Wandlung fertig, dann wird Srtart ADC gelöscht
      79. Bytadclo = Adcl 'Read ADCL first...
      80. Bytadchi = Adch '... then ADCH
      81. 'Set Adcsra.adif 'erneut beschreiben damit dieses Bit gelöscht wird bei ADC Free
      82. Set Adcsra.adsc 'Start ADC weil nach der Wandlung das bit auf 0 geht
      83. If Wrdadc >= Wrdadc_vorgabe_temp Then Incr Impuls
      84. Loop
      85. End
      Alles anzeigen
      Gruß Holger
      link zu mir..
      forum.auto-steuerung.de
      ___
    • Weil das über doppelt so lange dauert bis ich einen Messwert habe, wie wenn ich es direkt mit den Registern mache.
      Dort springe ich dann auch auch noch in den interrupt vom ADC und lese dort die Werte aus.
      Das kostet aber auch Zeit durch die Sicherung der Register mit PUSH und POP.

      Auch möchte ich nach dem lesen der Werte sofort gleich die Wandlung anstoßen und bis ich im Programm wieder bei Wait ankomme läuft ja dann schon die Wandlung.
      Bei Getadc wird an dem Punkt die Wandlung erst angestoßen.
      Gruß Holger
      link zu mir..
      forum.auto-steuerung.de
      ___
    • Wenn du die maximale Wandlungsrate hast, hast du heine Zeit mehr, um mit den Daten was anzufangen.

      Kleine Rechnung:
      Angenommen der ADC bekommt die maximale Frequenz von 200kHz. Lt. Datenblatt werden 13 Takte benötigt, um Daten zu wandeln.
      Damit wären theoretisch 15384 Wandlungen möglich. Aber du benötigst noch Zeit, um die Daten auszulesen, zu verarbeiten und auch um den ADC neu zu starten.

      Je nachdem, was man mit den Daten macht, kann ich mir vorstellen etwa 10000 Wandlungen hinzubekommen. Vielleicht etwas mehr.
      Hängt stark davon ab, was du mit den Daten machen möchtest.

      Was hast du denn vor mit den Daten? Per Uart senden, auf dem Display zeigen, im EEProm ablegen?
    • Um auf deine ursprüngliche Frage zurück zu kommen:

      So wie in deinem Beispielcode kann man es machen.

      Ich persöhnlich würde aber die Configuration nicht von Hand machen, sondern Config ADC verwenden.

      In der Hauptschleife dann folgende punkte durchführen.
      1. ADC-Wandlung starten
      2. Wenn Wandlung abgeschlossen ist, Wert auslesen
      3. Etwas mit dem Ergebnis machen (Incr Variable z.B.)
      4. Dann weiter mit 1.
      Willst du da Pulslängen messen mit dem ADC?
    • Die Impulslänge möchte ich nicht messen.
      Die Impulse sind nur verdammt kurz, die könnte ich sonst verpassen zu messen.
      Die werden nur minimal verlängert, das ich noch einigermaßen die höhe messen kann.

      Die andere Variante wäre mit Interrupt und Hardware Peak Hold.
      Das wäre der zweite schritt.

      Aktuell funktioniert das aber mit dem ADC schon ganz gut.
      Gruß Holger
      link zu mir..
      forum.auto-steuerung.de
      ___
    • Wenn 8 bit Auflösung reichen könnte der Wert rechtsbündig geliefert werde was die Abfrage des Low Bytes sparen würde. Noch nicht versucht habe ich den Adc zu starten und danach die Bytes auszulesen was möglicherweise auch funktioniert und noch ein paar µS sparen würde. Wenns nur einen Prototyp geben soll könnte auch der Adc testweise Overclockt a_20_e8d7189d werden bis er "schlechte" Werte a_48_7237538e ausgibt. Die meißten Chips haben Reserven nach oben gegenüber dem Datenblatt.
    • Die Werte aus lesen bringt nix. Die sind erst aktuell wenn Bit ADIF=1 ist. Dann werden diese umkopiert, erst Lbyte dann Hbyte.
      Deswegen muss man nach dem ADIF Bit=1 erst Lbyte lesen, ansonsten hat man Hbyte vom alten Wert und L vom neuen.
      Stimmt, 8bit wäre auch noch möglich, es wird zwar 10bit gewandelt, aber das lesen würde schnelle gehen.
      Gruß Holger
      link zu mir..
      forum.auto-steuerung.de
      ___
    • After you made your ADC free running you can read high and low byte together as a word as ADCD word variable.
      avrhelp.mcselec.com/getadc.htm
      "GetADC() returns a word variable since the A/D converter data registers consist of 2 registers. The resolution depends on the chip.
      The variable ADCD can be used to access the data register directly. The compiler will handle access to the byte registers automatically."

      You can read out as often as you want, the variable will be overwritten as soon as the conversion is finished.
      The newest ADCD is typically the voltage when the sampling ended 11,5 ADC cycles ago, and this value stays there for 13 ADC cycles.
    • Pluto25 schrieb:

      Wenn 8 bit Auflösung reichen könnte der Wert rechtsbündig geliefert werde was die Abfrage des Low Bytes sparen würde.
      Du meinst Linksbündig?

      @Trexis5
      Man kann auch die wenigen Zeilen in der Hauptschleife in Assembler schreiben.
      (ADC auslesen und vergleichen und Wert inkrementieren)
      Das spart dann das Zwischenspeichern der Werte in den Variablen, die Werte sind dann für die nächste Operation bereits im Register.

      Übrigens der Compiler hat auch eine Optimierungsoption, vielleicht bringt die in deinem Fall auch etwas an Geschwindigkeit.

      Die Option heißt Optimize Code, die findest du im Menü Optionen -> Compiler -> Output
    • Ich frag' jetzt mal ganz unbedarft: ist dieses Programmkonstrukt nicht ein Analogkomparator?
      Gib Signal, wenn eine Schwelle überschritten wird.
      Kann man da nicht den AC verwenden und mit dessen interrupt? Man hätte ja mehr Zeit.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------