Difference between revisions of "AVR Embedded Tutorial - UART/de"

From Lazarus wiki
Jump to navigationJump to search
Line 1: Line 1:
 
{{Translate}}
 
{{Translate}}
 +
=UART=
 +
 +
==Polling==
  
 
===ATmega328p (Arduino uno/nano)===
 
===ATmega328p (Arduino uno/nano)===
Line 77: Line 80:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
(Der Code wurde nicht getestet)
 
(Der Code wurde nicht getestet)
 +
 +
==Interrupt==
 +
Beim Polling kann es passieren, das Zeichen verschluckt werden, dies passiert, wen ein Zeichen ankommt und man dieses nicht abholt. Aus diesem Grund empfiehlt es sich, den Zeichenempfang Interrupt gesteuert zum machen.
 +
 +
===Deklaration===
 +
Zeichenbuffer deklarieren, hier wir ein Puffer von 16 Zeichen angelegt.
 +
<syntaxhighlight lang="pascal">
 +
const
 +
  Crxlen = 16;
 +
var
 +
  RxBuf: array[0..Crxlen - 1] of byte;
 +
  rxread: byte = 0;
 +
  rxwrite: byte = 0;   
 +
</syntaxhighlight>
 +
 +
===Inzialisieren===
 +
Dies ist ähnlich des Polling verfahren, der Unterschied, man teilt mit '''RXCIE0''' mit, das beim Zeichenempfang ein Interrupt ausgelöst wird.
 +
<syntaxhighlight lang="pascal">
 +
  procedure UARTInit;
 +
  begin
 +
    UBRR0 := teiler;
 +
 +
    UCSR0A := (0 shl U2X0);
 +
    UCSR0B := (1 shl TXEN0) or (1 shl RXEN0) or (1 shl RXCIE0);
 +
    UCSR0C := %011 shl UCSZ0;
 +
  end;
 +
</syntaxhighlight>
 +
 +
===Interrupt===
 +
Bei auslösen des Interrupts, wird das Zeichen vom UART in Zeichenbuffer kopiert.
 +
 +
<syntaxhighlight lang="pascal">
 +
  procedure UART_RX_Empfang; public Name 'USART__RX_ISR'; interrupt;
 +
  var
 +
    tchr: byte;
 +
  begin
 +
    tchr := UDR0;
 +
    if tchr <> 0 then begin
 +
      RxBuf[rxwrite] := tchr;
 +
      Inc(rxwrite);
 +
      if rxwrite >= Crxlen then begin
 +
        rxwrite := 0;
 +
      end;
 +
    end;
 +
  end;
 +
</syntaxhighlight>
 +
 +
===Hauptschleife===
 +
In der Hauptschleife wird geprüft, ob sich etwas im Empfangspuffer, wen ja, wird ein Zeichen davon ausgelesen.
 +
In diesem Beispiel werden, die empfangenen Zeichen in Grossbuchstaben umgewandelt und anschiessend wieder ausgegeben.
 +
 +
<syntaxhighlight lang="pascal">
 +
begin
 +
  // UART inizialisieren, die Interrupt gesteuert.
 +
  UARTInit;
 +
 +
  // Interrupt aktivieren.
 +
  asm sei end;
 +
 +
  // Hauptschleife.
 +
  repeat
 +
    cli;
 +
    while rxwrite <> rxread do begin
 +
      ch := RxBuf[rxread];
 +
      Inc(rxread);
 +
      if rxread >= Crxlen then begin
 +
        rxread := 0;
 +
      end;
 +
      if ch in [$61..$7A] then begin
 +
        Dec(ch, 32);
 +
      end;
 +
      UARTSendChar(char(ch));
 +
    end;
 +
    sei;
 +
  until 1 = 2;
 +
end.
 +
</syntaxhighlight>
 +
 +
  
  
 
[[Category:AVR]] {{AutoCategory}}
 
[[Category:AVR]] {{AutoCategory}}

Revision as of 21:20, 18 November 2017

Template:Translate

UART

Polling

ATmega328p (Arduino uno/nano)

Für die serielle Ausgabe wird ein Terminal mit folgenden Einstellungen gebraucht:

Baud Rate 9600
Bits 8
Stopbits 1
Parity none

Beim Betätigen von [space] im Terminal-Programm, sollte ein "Hello World !" zurück kommen.

program Project1;
const
  CPU_Clock = 16000000; // Taktfrequenz Arduino, default 16MHz.
  Baud      = 9600;     // Baudrate
  Teiler    = CPU_Clock div (16 * Baud) - 1;

  procedure UARTInit;
  begin
    UBRR0 := Teiler;

    UCSR0A := (0 shl U2X0);
    UCSR0B := (1 shl TXEN0) or (1 shl RXEN0);
    UCSR0C := (%011 shl UCSZ0);
  end;

  procedure UARTSendChar(c: char);
  begin
    while UCSR0A and (1 shl UDRE0) = 0 do begin
    end;
    UDR0 := byte(c);
  end;

  function UARTReadChar: char;
  begin
    while UCSR0A and (1 shl RXC0) = 0 do begin
    end;
    Result := char(UDR0);
  end;

  procedure UARTSendString(s: ShortString);
  var
    i: integer;
  begin
    for i := 1 to length(s) do begin
      UARTSendChar(s[i]);
    end;
  end;

begin
  UARTInit;
  repeat
    if UARTReadChar = #32 then begin         // space
      UARTSendString('Hello World !'#13#10); 
    end;
  until 1 = 2;
end.

ATtiny2313

Beim ATtiny2313 haben die Register eine andere Bezeichnung als beim ATmega328p.

  • Die 0 entfällt in der Bezeichnung.
  • UBRR0 muss man in UBRRH und UBRRL zerlegen.

Das sieht dann so aus:

UBRRH := Teiler shr 8;
UBRRL := Byte(Teiler);

UCSRB := (1 shl TXEN) or (1 shl RXEN);
UCSRC := (%011 shl UCSZ);

(Der Code wurde nicht getestet)

Interrupt

Beim Polling kann es passieren, das Zeichen verschluckt werden, dies passiert, wen ein Zeichen ankommt und man dieses nicht abholt. Aus diesem Grund empfiehlt es sich, den Zeichenempfang Interrupt gesteuert zum machen.

Deklaration

Zeichenbuffer deklarieren, hier wir ein Puffer von 16 Zeichen angelegt.

const
  Crxlen = 16;
var
  RxBuf: array[0..Crxlen - 1] of byte;
  rxread: byte = 0;
  rxwrite: byte = 0;

Inzialisieren

Dies ist ähnlich des Polling verfahren, der Unterschied, man teilt mit RXCIE0 mit, das beim Zeichenempfang ein Interrupt ausgelöst wird.

  procedure UARTInit;
  begin
    UBRR0 := teiler;

    UCSR0A := (0 shl U2X0);
    UCSR0B := (1 shl TXEN0) or (1 shl RXEN0) or (1 shl RXCIE0);
    UCSR0C := %011 shl UCSZ0;
  end;

Interrupt

Bei auslösen des Interrupts, wird das Zeichen vom UART in Zeichenbuffer kopiert.

  procedure UART_RX_Empfang; public Name 'USART__RX_ISR'; interrupt;
  var
    tchr: byte;
  begin
    tchr := UDR0;
    if tchr <> 0 then begin
      RxBuf[rxwrite] := tchr;
      Inc(rxwrite);
      if rxwrite >= Crxlen then begin
        rxwrite := 0;
      end;
    end;
  end;

Hauptschleife

In der Hauptschleife wird geprüft, ob sich etwas im Empfangspuffer, wen ja, wird ein Zeichen davon ausgelesen. In diesem Beispiel werden, die empfangenen Zeichen in Grossbuchstaben umgewandelt und anschiessend wieder ausgegeben.

begin
  // UART inizialisieren, die Interrupt gesteuert.
  UARTInit;

  // Interrupt aktivieren.
  asm sei end;

  // Hauptschleife.
  repeat
    cli;
    while rxwrite <> rxread do begin
      ch := RxBuf[rxread];
      Inc(rxread);
      if rxread >= Crxlen then begin
        rxread := 0;
      end;
      if ch in [$61..$7A] then begin
        Dec(ch, 32);
      end;
      UARTSendChar(char(ch));
    end;
    sei;
  until 1 = 2;
end.