Hy,
Ich habe hier einen Atmega8L ohne Quarz mit FTDI232 Kabel an meinem
Laptop.
Ich sende Strings an die USART des m8 welche er im EEPROM speichert
und mir über Int0 dann wieder am USART ausgeben soll. Das funktioniert
auch, bis ich mit der BaudRate hochgehe bis (die erforderlichen) 57600!
Je höher die BaudRate wird umso weniger Zeichen bekomme ich zurück, oder
vertauschte Zeichen.
So sieht die Ausgabe im Terminal (Termite3.1) aus :
1Gesendet: 1200=Baudrate/Test:1234567890123456789012345678901234567890
1Bekommen: 1200=Baudrate/Test:1234567890123456789012345678901234567890
Soweit OK
2Gesendet: 2400=Baudrate/Test:1234567890123456789012345678901234567890
2Bekommen: 2400=Bart/et13579135791357913579
Schlecht
3Gesendet: 4800=Baudrate/Test:1234567890123456789012345678901234567890
3Bekommen: 4800=r/t3715937159
Schlechter
4Gesendet: 57600=Baudrate/Test:1234567890123456789012345678901234567890
4Bekommen: 57600
Depremierendes Ergebniss! Im HTerm siehts genauso aus!
Hab schon einiges probiert, aber immer mit dem gleichen Ergebniss!
*1 Am fehlenden Quarz oder der Baudratenabweichung von 3,6% sollte es
nicht liegen weil ich grössere ZeichenStrings ohne Probleme schicken
kann, nur nicht im EEPROM speichern.
*2 Die Interrupts kommen sich auch nicht in die quere. "Glaubichhaltso"
*3 Kann es sein das "usartrxc"-ISR zu langsam ist und sich nach ein paar
Zeichen verhaschpelt?
Hier der Quellcode:
[avrasm]
.include "m8def.inc"
;
.equ f_cpu = 8000000 ;Prozessortakt
.equ baud = 57600 ;Gewünschte Baudrate
;
.equ ubrr_val = ((f_cpu+baud*8)/(baud*16)-1);Clever runden
.equ baud_real = (f_cpu/(16*(ubrr_val+1)));Reale Baudrate
.equ baud_error =((baud_real*1000)/baud-1000) ;Fehler in Promille
;
.if ((baud_error>36) || (baud_error<-36))
.error "Baudrate Error"
.endif
;
intx0:;;;;;;;;;;;;;;;Insert Interrupt Routine bei Tastendruck
;
eeprom_read:
sbic eecr, eewe
rjmp eeprom_read
out eearh, zh ;EEPROM Adresse bekantgeben
out eearl, zl
sbi eecr, eere
in zeichen, eedr
;
serout:
sbis ucsra, udre
rjmp serout
out udr, zeichen ;Zeichen senden
;
adiw Zl, 1 ; Zeiger erhöhen
cpi zeichen, '\r' ; auf CR warten
brne eeprom_read ;ungleich, springen
ldi ZL, low(Daten)
ldi ZH, high(Daten)
lange_pause
reti
usartrxc:;;;;;;;;;;;Insert Interrupt Routine
;
in zeichen, udr ;Zeichen holen
;
eeprom_write:
sbic eecr, eewe
rjmp eeprom_write
out eearh, zh ;EEPROM Adresse bekantgeben
out eearl, zl
out eedr, zeichen ;Zeichen laden
sbi eecr, eemwe
sbi eecr, eewe ;Zeichen absenden an EEPROM
;
adiw Zl, 1 ; Zeiger erhöhen
cpi zeichen, '\r' ; auf CR warten
brne eeprom_write1 ; wenn ungleich, springen
ldi ZL, low(Daten) ; zurücksetzen
ldi ZH, high(Daten)
eeprom_write1:
reti
;;;;;;;;;;;;;;PROGRAMM START;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
reset:
ldi ssr, high(RAMEND) ;Stack
out sph, ssr
ldi ssr, low(RAMEND)
out spl, ssr
;
ldi ZL, low(daten)
ldi ZH, high(daten)
;
sbi ucsrb, txen ;USART senden aktiviert
sbi ucsrb, rxen ;USART empfangen aktiviert
sbi ucsrb, rxcie ;Interrupt bei USART Empfang
ldi ssr, (1<<ursel | 1<<ucsz1 | 1<<ucsz0)
out ucsrc, ssr ;8 Datenbits, kein Parity, 1 Stop
ldi ssr, HIGH(ubrr_val)
out ubrrh, ssr
ldi ssr, LOW(ubrr_val)
out ubrrl, ssr
;
sei
loop:
rjmp loop
.ESEG
Daten:
.db 0
[avrasm]
Serout() ist ja blockierend. Das geht so natuerlich nicht. Mach das per interrupt.
Schau mal im Datenblatt nach, wie lange das Schreiben eines EEPROM Bytes dauert. Das darf bei Dir nur eine Byte-Zeit beim UART lang sein, was vermutlich nur für 1200 Baud zutrifft. Abhilfe für schnellere Baudraten: String puffern und erst am Ende der Übertragung ins EEPROM schreiben.
Jim Meba schrieb: > Schau mal im Datenblatt nach, wie lange das Schreiben eines EEPROM Bytes > dauert. Das darf bei Dir nur eine Byte-Zeit beim UART lang sein, was > vermutlich nur für 1200 Baud zutrifft. Im Datenblatt steht 8,5ms/Byte abhängig von der Genauigkeit des internen RC-Oscillators (1MHz und unabhängig von der tatsächlichen CPU clock). Das ergibt 117,6 Bytes pro Sekunde und ist für 1200 Baud eigentlich schon zu knapp.
Jim Meba schrieb: > Schau mal im Datenblatt nach, wie lange das Schreiben eines EEPROM Bytes > dauert. Das darf bei Dir nur eine Byte-Zeit beim UART lang sein, was > vermutlich nur für 1200 Baud zutrifft. > > Abhilfe für schnellere Baudraten: String puffern und erst am Ende der > Übertragung ins EEPROM schreiben. Klaus 2m5 schrieb: > Im Datenblatt steht 8,5ms/Byte abhängig von der Genauigkeit des internen > RC-Oscillators (1MHz und unabhängig von der tatsächlichen CPU clock). > > Das ergibt 117,6 Bytes pro Sekunde und ist für 1200 Baud eigentlich > schon zu knapp. Genau das habe ich auch gerade gelesen. Das wird wohl der Fehler sein! :-) Wenn ich fertig bin mit lesen und programmieren werd ich mal posten wies ausgegangen ist. Vielen Dank erstmal.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.