AVR Embedded Tutorial - Analog Read/de

From Lazarus wiki
Jump to navigationJump to search

Deutsch (de) English (en)

Analog Read

Vorwort

Dieser Code ist für einen Atmega328/Arduino mit 16MHz.

Wie man die UART ansteuert, steht hier:

  • UART UARTInit und UARTSendString(...

Der ATmega328 kann mit 10Bit Genauigkeit messen, somit wird ein Wert zwischen 0..1023 ausgegeben.

Polling-verfahren

ADC Initialisieren

Analoges Einlesen konfigurieren. Als Referenzspannung wird AVcc genommen, dies ist der einfachste Weg. Dies mus an ADMUX übergeben werden.

Folgende Referenzspannungen kann man mit ADMUX konfigurieren:

Bit 7 Bit 6 Beschreibung
0 0 Pin AREF
0 1 von AVcc
1 0 -
1 1 2.56V

Mit ADCSRA wird der Wandler gestartet.

  procedure ADC_Init;
  begin
    ADMUX  := (1 shl REFS);   // AVcc als Referenz.
    ADCSRA := (1 shl ADEN) or // Wandler einschalten.
    %111;                     // Teiler 128.
  end;

Auslesen

Der Ablauf bei Messen ist folgendermassen.

  • Port angeben.
  • Warten bis Messung ferig.
  • Messwert auslesen.

Bei ADMUX muss man die Referenzspannung nochmals angeben, weil es das Register mit Referenz teilt, man könnte auch eine or-Verknüpfung mit ADMUX machen.

  function ADC_Read(Port: byte): integer;
  begin
    ADMUX := (1 shl REFS) or (Port and $0F);      // Port angeben.
    ADCSRA := ADCSRA or (1 shl ADSC);             // Messen einleiten.
    while (ADCSRA and (1 shl ADSC)) <> 0 do begin // Warten bis gemessen.
    end;

    Result := ADC;                                // Messwert auslesen. 
  end;

Wen man immer vom gleiche Port einliest, muss man die ADMUX-Zeile nur einmal aufrufen. Auch kann man dann das Messen einleiten direkt nach der 'while-Schleife machen. Die spart ein paar Takte.

Über UART ausgeben

Variablen für Zwischenspeicher für die Messdaten.

var
  Data: integer;
  s: string[10];

In einer Endlosschelife werden dann die Messdaten ausgegeben.

begin

  // UART inizialisieren
  UARTInit;

  // ADC inizialisieren
  ADC_Init;

  // Interrupt erlauben
  asm Sei end;

  // Messwerte ausgeben.
  repeat
    Data := ADC_Read(0);
    str(Data: 6, s);
    UARTSendString(s);
  until 1 = 2;
end.

Interrupt gesteuert

Bei dem Interruptgesteuerten Verfahren, hat man den Vorteil, das man nicht warten muss, bis die Messung fertig ist, somit hat man Zeit für Anderes.

Inizialisieren

Der Unterschied:

  • Bei ADMUX gibt man am Anfang schon den Eingangs-Port an.
  • Bei ADCSRA muss man mit ADSC die erste Messung gestartet werde.
  • Mit ADIE teilt man mit das die Wandlung Interrupt gesteuert ist.
  procedure ADC_Init;
  const
    Port = 0;
  begin
    ADMUX := (1 shl REFS) or (Port and $0F);
    ADCSRA := %111 or (1 shl ADEN) or (1 shl ADSC) or (1 shl ADIE);
  end;

Messwert im Interrupt ausgeben

  procedure ADC_Ready public Name 'ADC_ISR'; interrupt;
  var
    Data: integer;
    s: string[10];
  begin
    Data := ADC;
    ADCSRA := ADCSRA or (1 shl ADSC);
    str(Data: 6, s);
    UARTSendString(s);
  end;

Hauptprogramm

Da das Messen Interruptgesteuert ist, bleibt die Hauptschleife leer. Wichtig, das man mit sei die Interrupts einschaltet.

begin

  // UART inizialisieren
  UARTInit;

  // ADC
  ADC_Init;

  // Interrupt erlauben
  asm Sei end;

  // Hauptschleife
  repeat
    // Mache Irgendwas
  until 1 = 2;
end.

Siehe auch

Autor: Mathias