ATmega328p und UART

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.

Re: ATmega328p und UART

Beitragvon Timm Thaler » 22. Okt 2017, 18:07 Re: ATmega328p und UART

Mathias hat geschrieben:Irgendwie setzt mich der AVR in das 8088er-Zeitalter zurück, da hatte man auch jedes Byte optimiert. :wink:


Man muss nicht jedes Byte optimieren, das muss ich mir auch abgewohnen. Aber Divisionsroutinen fressen immer richtig viel Rechenzeit, deswegen versucht man die weitgehend zu vermeiden oder durch 2^n-Divisionen (div 2, div 4, ... div 256) zu ersetzen, dann kann der Compiler mit shift-Befehlen arbeiten.
Timm Thaler
 
Beiträge: 430
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Mathias » 22. Okt 2017, 19:13 Re: ATmega328p und UART

Aber Divisionsroutinen fressen immer richtig viel Rechenzeit, deswegen versucht man die weitgehend zu vermeiden oder durch 2^n-Divisionen (div 2, div 4, ... div 256) zu ersetzen, dann kann der Compiler mit shift-Befehlen arbeiten.
Dies war schon beim 8088er der Fall.
So nebenbei, beim ATtiny muss man das auch bei Multiplikationen beachten, da dieser auch dies nicht Hardwaremässig kann.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3188
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Mathias » 23. Okt 2017, 17:09 Re: ATmega328p und UART

Ich wollte jetzt mal einen Text mit dem Empfangspuffer machen.
Code: Alles auswählen
const
  CPU_Clock = 16000000; // Taktfrequenz Arduino, default 16MHz.
  Baud = 9600;          // Baudrate
  UCSZ01 = 2;           // Gibt es nicht in der Unit Atmega328p.
  teiler = CPU_Clock div (2 * Baud) - 1;
  teilerH = teiler shr 8;
  teilerL = teiler mod $100;
 
  procedure UART_RX_Empfang; public Name 'USART__RX_ISR'; interrupt;
  begin
    PORTB := PORTB or (1 shl 5);
  end;
 
  procedure UARTInit;
  begin
    UBRR0H := teilerH;
    UBRR0L := teilerL;
 
    UCSR0A := UCSR0A or (0 shl U2X0);
    UCSR0B := UCSR0B or (1 shl TXEN0) or (1 shl RXEN0) or (1 shl RXCIE0);
    UCSR0C := UCSR0C or (1 shl UMSEL0) or (1 shl UCSZ01) or (1 shl UCSZ0);
 
    DDRD := DDRD or (1 shl 4);
  end;     
 
begin
  DDRB := DDRB or (1 shl 5); // Pin 13 Output
  UARTInit;
  repeat
  until 1 = 2;
end.

Die LED an Pin13 geht nicht an, so wie es aussieht, wir der Interrupt nicht ausgelöst.
Wieso ?
Wen ich in Terminal etwas eingebe, leuchtet die LED RX wie erwartet kurz auf.

Der Procedure-Name habe ich aus der Unit ATmega328p.
Code: Alles auswählen
procedure USART__RX_ISR; external name 'USART__RX_ISR'; // Interrupt 18 USART Rx Complete


Noch etwas, wen ich es richtig verstanden habe, gibt es beim AVR keinen Hardware-Empfangspuffer ?
Zuletzt geändert von Mathias am 23. Okt 2017, 18:55, insgesamt 1-mal geändert.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3188
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Timm Thaler » 23. Okt 2017, 18:24 Re: ATmega328p und UART

Mathias hat geschrieben:Ich wollte jetzt mal einen Text mit dem Empfangspuffer machen.


Wie sieht UartInit aus?

Mathias hat geschrieben:Noch etwas, wen ich es richtig verstanden habe, gibt es beim AVR keinen Hardware-Empfangspuffer ?


Doch, wohl. Einen 2-Byte FIFO. Während ein Byte empfangen wird, kannst Du das vorherige auslesen.
Timm Thaler
 
Beiträge: 430
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Mathias » 23. Okt 2017, 18:57 Re: ATmega328p und UART

Wie sieht UartInit aus?

Ups vergessen, habe sie oben angehängt.

Doch, wohl. Einen 2-Byte FIFO. Während ein Byte empfangen wird, kannst Du das vorherige auslesen.

Sowas habe ich mir fast gedacht, ansonsten könnte man sich die Übung mit dem Puffer sparen.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3188
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Timm Thaler » 23. Okt 2017, 19:59 Re: ATmega328p und UART

SEI
Timm Thaler
 
Beiträge: 430
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Mathias » 23. Okt 2017, 20:14 Re: ATmega328p und UART

Timm Thaler hat geschrieben:SEI

Ich glaube ich spinne. :roll:
Da es nicht ging, habe ich es mit Arduino und sei(); probiert, es funktionierte nicht.
Ich habe es hier abgeguckt: https://www.mikrocontroller.net/article ... l/Der_UART
Code: Alles auswählen
void UARTInit(){
    UBRR0 = teiler;
 
    UCSR0A |= (0 << U2X0);
    UCSR0B |= (1 << TXEN0) | (1 << RXEN0) | (1 << RXCIE0);
    UCSR0C |= (1 << UMSEL00) | (1 << UCSZ01) | (1 << UCSZ00);
 
    DDRD = DDRD or (1 << 4);
 
    sei();
 }

Irgendwie hat es im Arduino Müll.
Aber im Pascal-Code klappt es jetzt.
Code: Alles auswählen
  procedure UART_RX_Empfang; public Name 'USART__RX_ISR'; interrupt;
  begin
    PORTB := PORTB or (1 shl PB5);
  end;
 
  procedure UARTInit;
  begin
    UBRR0 := teiler;
 
    UCSR0A := UCSR0A or (0 shl U2X0);
    UCSR0B := UCSR0B or (1 shl TXEN0) or (1 shl RXEN0) or (1 shl RXCIE0);
    UCSR0C := UCSR0C or (1 shl UMSEL0) or (1 shl UCSZ01) or (1 shl UCSZ0);
 
    DDRD := DDRD or (1 shl 4);
 
    sei;
  end;

Irgendwie hat es im Arduino Müll.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3188
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Timm Thaler » 23. Okt 2017, 22:44 Re: ATmega328p und UART

Das ist das Problem beim Arduino: Du weisst nicht, was der noch im Hintergrund so treibt.

Das SEI solltest Du vor das Repeat im Hauptprogramm setzen. Es gibt alle Interrupts frei. Also auch Timerinterrupts und so. Wenn Du das in UartInit hast und danach einen Timerinterrupt initialisierst, kann das Probleme geben, ebenso wenn Du UartInit rausnimmst, gehen plötzlich alle anderen Interrupts auch nicht mehr.
Timm Thaler
 
Beiträge: 430
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Mathias » 23. Okt 2017, 22:59 Re: ATmega328p und UART

Stimmt dies das der AVR zum Start im cli-Modus läuft ?

Ich habe heute Abend, das Ganze mit einem einfachen Buffer probiert, so halbwegs funktioniert es schon. Es kommen zwischendurch fehlerhafte Zeichen an, aber dies könnte auch beim Senen passieren.
Aber das werde ich morgen nochmals genauer angucken.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3188
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Timm Thaler » 23. Okt 2017, 23:56 Re: ATmega328p und UART

Mathias hat geschrieben:Stimmt dies das der AVR zum Start im cli-Modus läuft ?


Würd ich mich nicht drauf verlassen. Bei mir kommt gleich als Erstes ein cli, dann die Initialisierungen, dann ein sei.
Timm Thaler
 
Beiträge: 430
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Mathias » 24. Okt 2017, 16:05 Re: ATmega328p und UART

Hier probiere ich es mal mit einem Empfangspuffer.
Nur kommt leider kommt im Schnitt jedes 20igste Zeichen fehlerhaft an.
Es spielt keine Rolle, ob ich es 9600 oder 115200 Baud mache.
Code: Alles auswählen
const
  PB5 = 5;
  UCSZ01 = 2;           // Gibt es nicht in der Unit Atmega328p.
  CPU_Clock = 16000000; // Taktfrequenz Arduino, default 16MHz.
  Baud = 115200;          // Baudrate
//  Baud = 9600;          // Baudrate
  teiler = CPU_Clock div (2 * Baud) - 1;
 
var
  zeiger: integer;
  buf: array[0..255] of byte;
 
 
  procedure UART_RX_Empfang; public Name 'USART__RX_ISR'; interrupt;
  begin
    buf[zeiger] := UDR0;
    Inc(zeiger);
  end;
 
  procedure UARTInit;
  begin
    UBRR0 := teiler;
 
    UCSR0A := UCSR0A or (0 shl U2X0);
    UCSR0B := UCSR0B or (1 shl TXEN0) or (1 shl RXEN0) or (1 shl RXCIE0);
    UCSR0C := UCSR0C or (1 shl UMSEL0) or (1 shl UCSZ01) or (1 shl UCSZ0);
 
    DDRD := DDRD or (1 shl 4);
  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;
 
var
  i: integer;
 
begin
  DDRB := DDRB or (1 shl UMSEL0); // Pin 13 Output
  zeiger := 0;
 
  cli;
  UARTInit;
  sei;
  repeat
    if zeiger > 3 then begin
      for i := 0 to 3 do begin
        UARTSendChar(char(buf[i]));
      end;
      UARTSendString(' Hello World !'#13#10);
      zeiger := 0;
    end;
  until 1 = 2;
end.

Wen ich konstant die 'x' drücke, bekomme ich folgende Ausgabe.
Ich kann auch ein anderes Zeichen drücken, dies spielt keine Rolle.

Was habe ich übersehen ?
Code: Alles auswählen
xxxx Hello World !
xxxx Hello World !
x�xx Hello World !
xxxx Hello World !
xxx� Hello World !
xxxx Hello World !
xxxx Hello World !
xxxx Hello World !
xx�x Hello World !
xxx� Hello World !
xxxx Hello World !
�xxx Hello World !
x�xx Hello World !
xxxx Hello World !
xxxx Hello World !
xxxx Hello World !
xxxx Hello World !
xxxx Hello World !
xxxx Hello World !
xxxx Hello World !
�xxx Hello World !


Ein zweiter Versuch, ich gebe aus was gerade rein kommt.
Hier kommt jedes Zeichen falsch raus.
Wen ich zB. die 'x' drücke, dann kommen fast alles 'y'. Zwischen durch kommt mal ein 'x' raus.
Weiter Ausgaben:
e --> u
a --> e
i --> m

Code: Alles auswählen
procedure UART_RX_Empfang; public Name 'USART__RX_ISR'; interrupt;
begin
  UARTSendChar(char( UDR0));
end;

Könnte dies einen Zusammenhang mit UDR0 haben ?
Da ich fast gleichzeitig lese und schreibe ?
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3188
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Mathias » 28. Okt 2017, 19:46 Re: ATmega328p und UART

Wieso gibt es hier Übertragungsfehler ?

Ich habe das Programm mal aufs Minimum abgespeckt.

Ich mal die in die Interruptschleife eingefügt, aber ohne Erfolg.
Code: Alles auswählen
while UCSR0A and (1 shl RXC0) = 0 do begin end;

Ist die Schnittstelle etwa doch nicht bidirektional ?
Auch wen ich nur 9600Baud nehme, bleibt der Fehler.

Code: Alles auswählen
program Project1;
{$o-}
 
  procedure sei; assembler;
  asm
           Sei
  end;
 
  procedure cli; assembler;
  asm
           Cli
  end;
 
const
  UCSZ01 = 2;           // Gibt es nicht in der Unit Atmega328p.
  CPU_Clock = 16000000; // Taktfrequenz Arduino, default 16MHz.
    Baud = 115200;          // Baudrate
//  Baud = 9600;          // Baudrate
  teiler = CPU_Clock div (2 * Baud) - 1;
 
  procedure UARTInit;
  begin
    UBRR0 := teiler;
 
    UCSR0A := (0 shl U2X0);
    UCSR0B := (1 shl TXEN0) or (1 shl RXEN0) or (1 shl RXCIE0);
    UCSR0C := (1 shl UMSEL0) or (1 shl UCSZ01) or (1 shl UCSZ0);
 
    DDRD := DDRD or (1 shl 4);
  end;
 
  procedure UARTSendChar(c: Byte);
  begin
    while UCSR0A and (1 shl UDRE0) = 0 do begin
    end;
    UDR0 := byte(c);
  end;
 
  procedure UART_RX_Empfang; public Name 'USART__RX_ISR'; interrupt;
  begin
//    while UCSR0A and (1 shl RXC0) = 0 do begin
//    end;
    UARTSendChar(UDR0);
  end;
 
begin
  cli;
  UARTInit;
  sei;
 
  repeat
  until 1 = 2;
end.


Die Ausgabe im Terminal, die Buchstabenreihe habe ich als Eingabe gedrückt.
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq�qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqxxxxxxxxxxxx��x�xxxxxx�xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx�xxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyzzzzzzzzzzzzzzzzzzzzz�zzzzzzzzzzzzzzzz�zzzzzzzzzzz�zzzzzzzzzzzzz�zyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy�yyyyyyyyyyy�yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy�yyyyyyyyyyyyyyyyyy�yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy�zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz�zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz�zzzzzzzzzzzzz
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3188
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Timm Thaler » 28. Okt 2017, 22:04 Re: ATmega328p und UART

Wenn es bei anderen funktioniert und bei Dir nicht, könnte der Fehler vielleicht nicht bei den anderen liegen. Rx und Tx geht gleichzeitig, ist so.

Datenblatt Seite 190, 115kbaud ist grenzwertig bei 16MHz, erklärt aber nicht das Problem bei 9600baud.
Timm Thaler
 
Beiträge: 430
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Mathias » 28. Okt 2017, 22:15 Re: ATmega328p und UART

[quote115kbaud ist grenzwertig bei 16MHz[/quote]
Mit dem Arduino Serial sind sogar 1000000Baud möglich.

Keine Idee, was in meinem Code falsch ist, das es bei mir nicht mal mit 9600Baud klappt ?
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3188
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Timm Thaler » 28. Okt 2017, 22:19 Re: ATmega328p und UART

Und? Hast Du mal ins Datenblatt geschaut?

16MHz durch 1000000 geht ohne Rest.
16MHz durch 115200 geht nicht ohne Rest.
Timm Thaler
 
Beiträge: 430
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

» Weitere Beiträge siehe nächste Seite »
VorherigeNächste

Zurück zu Sonstiges



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast

porpoises-institution
accuracy-worried