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.Mathias hat geschrieben:Irgendwie setzt mich der AVR in das 8088er-Zeitalter zurück, da hatte man auch jedes Byte optimiert.
ATmega328p und UART
-
- Beiträge: 1224
- Registriert: So 20. Mär 2016, 22:14
- OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
- CPU-Target: Raspberry Pi 3
Re: ATmega328p und UART
-
- Beiträge: 6947
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: ATmega328p und UART
Dies war schon beim 8088er der Fall.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.
So nebenbei, beim ATtiny muss man das auch bei Multiplikationen beachten, da dieser auch dies nicht Hardwaremässig kann.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 6947
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: ATmega328p und UART
Ich wollte jetzt mal einen Text mit dem Empfangspuffer machen.
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.
Noch etwas, wen ich es richtig verstanden habe, gibt es beim AVR keinen Hardware-Empfangspuffer ?
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.
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
Zuletzt geändert von Mathias am Mo 23. Okt 2017, 19:55, insgesamt 1-mal geändert.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 1224
- Registriert: So 20. Mär 2016, 22:14
- OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
- CPU-Target: Raspberry Pi 3
Re: ATmega328p und UART
Wie sieht UartInit aus?Mathias hat geschrieben:Ich wollte jetzt mal einen Text mit dem Empfangspuffer machen.
Doch, wohl. Einen 2-Byte FIFO. Während ein Byte empfangen wird, kannst Du das vorherige auslesen.Mathias hat geschrieben:Noch etwas, wen ich es richtig verstanden habe, gibt es beim AVR keinen Hardware-Empfangspuffer ?
-
- Beiträge: 6947
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: ATmega328p und UART
Ups vergessen, habe sie oben angehängt.Wie sieht UartInit aus?
Sowas habe ich mir fast gedacht, ansonsten könnte man sich die Übung mit dem Puffer sparen.Doch, wohl. Einen 2-Byte FIFO. Während ein Byte empfangen wird, kannst Du das vorherige auslesen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 1224
- Registriert: So 20. Mär 2016, 22:14
- OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
- CPU-Target: Raspberry Pi 3
-
- Beiträge: 6947
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: ATmega328p und UART
Ich glaube ich spinne.Timm Thaler hat geschrieben:SEI

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();
}
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;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 1224
- Registriert: So 20. Mär 2016, 22:14
- OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
- CPU-Target: Raspberry Pi 3
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.
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.
-
- Beiträge: 6947
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
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.
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 grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 1224
- Registriert: So 20. Mär 2016, 22:14
- OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
- CPU-Target: Raspberry Pi 3
Re: ATmega328p und UART
Würd ich mich nicht drauf verlassen. Bei mir kommt gleich als Erstes ein cli, dann die Initialisierungen, dann ein sei.Mathias hat geschrieben:Stimmt dies das der AVR zum Start im cli-Modus läuft ?
-
- Beiträge: 6947
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
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.
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 ?
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
Könnte dies einen Zusammenhang mit UDR0 haben ?
Da ich fast gleichzeitig lese und schreibe ?
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.
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 !
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;
Da ich fast gleichzeitig lese und schreibe ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 6947
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
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.
Ist die Schnittstelle etwa doch nicht bidirektional ?
Auch wen ich nur 9600Baud nehme, bleibt der Fehler.
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
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;
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.
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq�qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqxxxxxxxxxxxx��x�xxxxxx�xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx�xxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyzzzzzzzzzzzzzzzzzzzzz�zzzzzzzzzzzzzzzz�zzzzzzzzzzz�zzzzzzzzzzzzz�zyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy�yyyyyyyyyyy�yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy�yyyyyyyyyyyyyyyyyy�yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy�zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz�zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz�zzzzzzzzzzzzz
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 1224
- Registriert: So 20. Mär 2016, 22:14
- OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
- CPU-Target: Raspberry Pi 3
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.
Datenblatt Seite 190, 115kbaud ist grenzwertig bei 16MHz, erklärt aber nicht das Problem bei 9600baud.
-
- Beiträge: 6947
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
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 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 grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 1224
- Registriert: So 20. Mär 2016, 22:14
- OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
- CPU-Target: Raspberry Pi 3
Re: ATmega328p und UART
Und? Hast Du mal ins Datenblatt geschaut?
16MHz durch 1000000 geht ohne Rest.
16MHz durch 115200 geht nicht ohne Rest.
16MHz durch 1000000 geht ohne Rest.
16MHz durch 115200 geht nicht ohne Rest.