Difference between revisions of "AVR Embedded Tutorial - Analog Read/de"

From Lazarus wiki
Jump to navigationJump to search
(Created page with "{{Translate}} {{Warning| In Arbeit}} =Analog Read= ==Vorwort== Wie man die UART ansteuert, steht hier: * UART ''UARTInit'' und ''UARTSend...")
 
m (Fixed template loop; added language category)
 
(13 intermediate revisions by one other user not shown)
Line 1: Line 1:
{{Translate}}
+
{{LanguageBar}}
  
{{Warning| In Arbeit}}
 
 
=Analog Read=
 
=Analog Read=
  
 
==Vorwort==
 
==Vorwort==
 +
 +
Dieser Code ist für einen Atmega328/Arduino mit 16MHz.
 +
 
Wie man die UART ansteuert, steht hier:
 
Wie man die UART ansteuert, steht hier:
 +
 
* [[AVR Embedded Tutorial - UART/de|UART]] ''UARTInit'' und ''UARTSendString(...''
 
* [[AVR Embedded Tutorial - UART/de|UART]] ''UARTInit'' und ''UARTSendString(...''
  
==code==
+
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.
  
<syntaxhighlight lang="pascal">
+
Folgende Referenzspannungen kann man mit ADMUX konfigurieren:
const
 
  REFS0 = 6;
 
  ADPS0 = 0;
 
  ADPS1 = 1;
 
  ADPS2 = 2;
 
  
 +
{| class="wikitable"
 +
|-
 +
! 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.
  
 +
<syntaxhighlight lang="pascal">
 
   procedure ADC_Init;
 
   procedure ADC_Init;
 
   begin
 
   begin
     ADMUX := (1 shl REFS0);
+
     ADMUX := (1 shl REFS);   // AVcc als Referenz.
     ADCSRA := %111 or (1 shl ADEN);
+
     ADCSRA := (1 shl ADEN) or // Wandler einschalten.
 +
    %111;                     // Teiler 128.
 
   end;
 
   end;
 +
</syntaxhighlight>
 +
 +
===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.
  
 +
<syntaxhighlight lang="pascal">
 
   function ADC_Read(Port: byte): integer;
 
   function ADC_Read(Port: byte): integer;
 
   begin
 
   begin
     ADMUX := (1 shl REFS0) or (Port and $0F);
+
     ADMUX := (1 shl REFS) or (Port and $0F);     // Port angeben.
     ADCSRA := ADCSRA or (1 shl ADSC);
+
     ADCSRA := ADCSRA or (1 shl ADSC);             // Messen einleiten.
     while (ADCSRA and (1 shl ADSC)) <> 0 do begin
+
     while (ADCSRA and (1 shl ADSC)) <> 0 do begin // Warten bis gemessen.
 
     end;
 
     end;
  
     Result := ADC;
+
     Result := ADC;                               // Messwert auslesen.
 
   end;
 
   end;
 +
</syntaxhighlight>
  
 +
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.
 +
 +
<syntaxhighlight lang="pascal">
 
var
 
var
 
   Data: integer;
 
   Data: integer;
 
   s: string[10];
 
   s: string[10];
 +
</syntaxhighlight>
 +
 +
In einer Endlosschelife werden dann die Messdaten ausgegeben.
  
 +
<syntaxhighlight lang="pascal">
 
begin
 
begin
  
Line 43: Line 88:
 
   UARTInit;
 
   UARTInit;
  
   // ADC
+
   // ADC inizialisieren
 
   ADC_Init;
 
   ADC_Init;
  
   asm
+
  // Interrupt erlauben
          Sei end;
+
   asm Sei end;
 +
 
 +
  // Messwerte ausgeben.
 
   repeat
 
   repeat
 
     Data := ADC_Read(0);
 
     Data := ADC_Read(0);
Line 54: Line 101:
 
   until 1 = 2;
 
   until 1 = 2;
 
end.
 
end.
 +
</syntaxhighlight>
 +
 +
==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.
 +
 +
<syntaxhighlight lang="pascal">
 +
  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;
 +
</syntaxhighlight>
 +
 +
===Messwert im Interrupt ausgeben===
  
 +
<syntaxhighlight lang="pascal">
 +
  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;
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
===Hauptprogramm===
 +
 +
Da das Messen Interruptgesteuert ist, bleibt die Hauptschleife leer.
 +
Wichtig, das man mit '''sei''' die Interrupts einschaltet.
 +
 +
<syntaxhighlight lang="pascal">
 +
begin
 +
 +
  // UART inizialisieren
 +
  UARTInit;
 +
 +
  // ADC
 +
  ADC_Init;
 +
 +
  // Interrupt erlauben
 +
  asm Sei end;
 +
 +
  // Hauptschleife
 +
  repeat
 +
    // Mache Irgendwas
 +
  until 1 = 2;
 +
end. 
 +
</syntaxhighlight>
 +
 +
== Siehe auch ==
 +
 +
* Übersichtseite [[AVR Embedded Tutorial/de|AVR Embedded Tutorial]]
 +
 +
Autor: [[User:Mathias|Mathias]]
  
[[Category:AVR]] {{AutoCategory}}
+
[[Category:Embedded]]
 +
[[Category:AVR]]
 +
[[Category:Arduino]]
 +
{{AutoCategory}}

Latest revision as of 11:43, 22 January 2020

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