Forum: Mikrocontroller und Digitale Elektronik usart - ich empfange immernoch schrott


von TS (Gast)


Lesenswert?

Ich versuche einen skytraq venus 5 mit einem atmega 162 zu verbinden.

Der tx ligt am usart0 an und ich empfange auch etwas. und genau da is 
das problem. Ich empfange schrott!

Laut dem Venus Datenblatt baudrate 9600
Quarz @ 8mhz
und fuses auf 1111

folgender code...


; http://www.mikrocontroller.net/tutorial/uart.htm



; Daten empfangen mit Interrupt

; und zur?cksenden

.include "m162def.inc"

.def temp      = r16
.def sreg_save = r17

.equ CLOCK = 8000000

.equ BAUD = 9600
.equ UBRRVAL = CLOCK/(BAUD*16)-1

; hier geht das Programmsegment los

.CSEG
.org 0x00
    rjmp    main

.org URXC0addr
    rjmp    int_rxc

; Hauptprogramm
main:
    ldi     temp, LOW(RAMEND)           ; Stackpointer initialisieren
    out     SPL, temp
    ldi     temp, HIGH(RAMEND)
    out     SPH, temp

    ldi     temp, LOW(UBRRVAL)          ; Baudrate einstellen
    out     UBRR0L, temp
    ldi     temp, HIGH(UBRRVAL)
    out     UBRR0H, temp


    ldi     temp, (1<<URSEL0)|(3<<UCSZ00) ; Frame-Format: 8 Bit
    out     UCSR0C, temp

    sbi     UCSR0B, RXCIE                ; Interrupt bei Empfang
    sbi     UCSR0B, RXEN                 ; RX (Empfang) aktivieren

    ldi     ZL,low(daten)               ; der Z-Zeiger wird hier 
exclusiv
    ldi     ZH,high(daten)              ; für die Datenadressierung 
verwendet

    sei                                 ; Interrupts global aktivieren

loop:
    rjmp    loop                        ; Endlosschleife (ABER 
Interrupts!)

; Interruptroutine wird ausgeführt,
; sobald ein Byte über den UART empfangen wurde

int_rxc:
    push    temp                        ; temp auf dem Stack sichern
    in      temp,sreg                   ; SREG sicher, muss praktisch in 
jeder
                                        ; Interruptroutine gemacht 
werden
    push    temp

    in      temp, UDR                   ; empfangenes Byte lesen
    rcall   EEPROM_write                ; Byte im EEPROM speichern
    adiw    ZL,1                        ; Zeiger erhöhen
    cpi     ZL,low(EEPROMEND+1)         ; Vergleiche den Z Zeiger
    ldi     temp,high(EEPROMEND+1)      ; mit der maximalen EEPROM 
Adresse +1
    cpc     ZH,temp
    brne    int_rxc_1                   ; wenn ungleich, springen
    ldi     ZL,low(Daten)               ; wenn gleich, Zeiger 
zurücksetzen
    ldi     ZH,high(Daten)
int_rxc_1:

    pop     temp
    out     sreg,temp
    pop     temp                        ; temp wiederherstellen
    reti

; der eigentliche EEPROM Schreibzugriff
; Adresse in ZL/ZH
; Daten in temp

EEPROM_write:
    sbic    EECR, EEWE                  ; prüfe ob der letzte 
Schreibvorgang beendet ist
    rjmp    EEPROM_write                ; wenn nein, nochmal prüfen

    out     EEARH, ZH                   ; Adresse schreiben
    out     EEARL, ZL                   ;
    out     EEDR,temp                   ; Daten  schreiben
    in      sreg_save,sreg              ; SREG sichern
    cli                                 ; Interrupts sperren, die 
nächsten
                                        ; zwei Befehle dürfen NICHT
                                        ; unterbrochen werden
    sbi     EECR,EEMWE                  ; Schreiben vorbereiten
    sbi     EECR,EEWE                   ; Und los !
    out     sreg, sreg_save             ; SREG wieder herstellen
    ret

; hier wird der EEPROM-Inhalt definiert
.ESEG

Daten:
    .db     0


jemand ne idee??

von oha (Gast)


Lesenswert?

Ja. Vergiss das EEPROM, speziell in der Rx-interruptroutine. Ein Byte 
EEPROM schreiben dauert 4ms, waehrend 1byte empfangen 1ms dauert.

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
Noch kein Account? Hier anmelden.