mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik USART+RX_SR für ATmega168


Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
Ich habe mir den Code vom Tutorial übernommen und hab ihn nur für den 
Atmega168 angepasst.  Beim ersten Versuch, ohne den RX-ISR (also 
Polling) und habe auch Daten empfangen und dann mit RX-ISR, leider ohne 
erfolg. Ich weiss nicht mehr weiter, kann mir Jemand Helfen.

Chip:Atmega 168 (über STK500)
CLK:16MHz
Baud:9600

PS. Der angepasste Code
 
.include "m168def.inc"
 
.def temp_1 = R16
 
.equ F_CPU = 16000000                            ; Systemtakt in Hz
.equ BAUD  = 9600                               ; Baudrate
 
; Berechnungen
.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>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
.endif
 
.org 0x00
        rjmp main
 
.org 0x0024                ; Interruptvektor für UART-Empfang
        rjmp int_rxc
 
; Hauptprogramm
 
main:
 
    ; Stackpointer initialisieren
 
    ldi     temp_1, LOW(ramend)
    out     SPL, temp_1
    ldi     temp_1, HIGH(ramend)
    out     SPH, temp_1
 
    ; Port D = Ausgang
 
    ldi     temp_1, 0xFF
    out     DDRD, temp_1
 
    ; Baudrate einstellen
 
    ldi     temp_1, HIGH(UBRR_VAL)
    ldi     XH, HIGH(UBRR0H)
    ldi     XH, LOW(UBRR0H)
    st      X,temp_1                   ; UBRR0H (0xC5)
    ldi     temp_1, LOW(UBRR_VAL)
    st      -X,temp_1                  ; UBRR0L (0xC4)
 
    ; Frame-Format: 8 Bit
 
    ldi     temp_1,(1<<UMSEL00)|(3<<UCSZ00)
    ldi     XH, HIGH(UCSR0C)
    ldi     XH, LOW(UCSR0C)
    st      X,temp_1
 
    ldi     temp_1, (1<<RXCIE0)|(1<<RXEN0)
    ldi     XH, HIGH(UCSR0B)
    ldi     XH, LOW(UCSR0B)
    st      X,temp_1

    sei                          ; Interrupts global aktivieren
    
loop:
    
    rjmp loop                    ; Endlosschleife
 
; Interruptroutine: wird ausgeführt sobald ein Byte 
; über das UART empfangen wurde
 
int_rxc:
    push    temp_1                            

    ldi     XH, HIGH(UDR0)
    ldi     XH, LOW(UDR0)
    ld      temp_1, X

    com     temp_1               ;beim STK500 gehen die LED bei Low an
    out     PORTD, temp_1                     

    pop     temp_1                            
reti 

Autor: ecslowhand (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Einige Fehler:

>> rjmp int_rxc
nehme den JMP-Befehl: jmp int_rxc


UBRR_VAL ist ein 16-bit Wert, Du benutzt nur 8-Bit!!!
Zudem lädst Du nur das XH-Register und nicht das XL-Register!!!

>>    ; Baudrate einstellen
>>    ldi     temp_1, HIGH(UBRR_VAL)
>>   ldi     XH, HIGH(UBRR0H)
>>    ldi     XH, LOW(UBRR0H)
>>    st      X,temp_1                   ; UBRR0H (0xC5)
>>   ldi     temp_1, LOW(UBRR_VAL)
>>    st      -X,temp_1                  ; UBRR0L (0xC4)

Warum benutzt Du das X-Register? Geht doch viel einfacher:
[asm]
  ldi  r16, LOW(UBRR_VAL)  ; Baudrate berechnen..
  ldi  r17, HIGH(UBRR_VAL)
  sts  UBRR0L, r16    ; ...und setzen
  sts  UBRR0H, r17
[/asm]

Autor: ecslowhand (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine komplette Beispielroutine für den MEGA168:
; ---------------------
; UART0 initialisieren (MEGA168)
; ---------------------
USART_init:
  ldi  r16, LOW((clock/(16*baudrate))-1)  ; Baudrate berechnen..
  ldi  r17, HIGH((clock/(16*baudrate))-1)
  sts  UBRR0L, r16        ; ...und setzen
  sts  UBRR0H, r17

  lds  r16, UCSR0B
  sbr  r16, (1<<RXCIE0)|(1<<RXEN0)    ; RX-Interrupt disable, RX disable
  sbr  r16, (1<<TXEN0)        ; TX enable
  cbr  r16, (1<<UCSZ02)      ; 8 datenbits
  sts  UCSR0B, r16
  lds  r16, UCSR0C
  cbr  r16, (1<<UCPOL0)      ; asyncron
  cbr  r16, (1<<UMSEL01)|(1<<UMSEL00)    
  cbr  r16, (1<<UPM01)|(1<<UPM00)    ; no parity
  cbr  r16, (1<<USBS0)        ; 1 stopp-bit
  cbr  r16, (1<<UCSZ02)      ; 8 datenbits
  sbr  r16, (1<<UCSZ01)|(1<<UCSZ00)
  sts  UCSR0C, r16
  ret


LG EC

Autor: ecslowhand (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mist, immer wenn`s schnell gehen soll......

<>>   sbr  r16, (1<<RXCIE0)|(1<<RXEN0)    ; RX-Interrupt disable, RX 
disable

Muss natürlich heissen:
  sbr  r16, (1<<RXCIE0)|(1<<RXEN0)    ; RX-Interrupt enable, RX enable

Autor: Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
es klapt :) und "sts" ist wirlich einfacher,
danke dir.

habe den Code mit rauf gepackt, wenn auch Andere mall ein änliches 
Problem haben sollten.
.include "m168def.inc"
 
.def temp_1 = R16
 
.equ F_CPU = 16000000                            ; Systemtakt in Hz
.equ BAUD  = 9600                               ; Baudrate
 
; Berechnungen
.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>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
.endif
 
.org 0x00
        rjmp main
 
.org 0x0024                       ; Interruptvektor für UART-Empfang
        jmp int_rxc
 
; Hauptprogramm
 
main:
 
    ; Stackpointer initialisieren
 
    ldi     temp_1, LOW(ramend)
    out     SPL, temp_1
    ldi     temp_1, HIGH(ramend)
    out     SPH, temp_1
 
    ; Port C = Ausgang
 
    ldi     temp_1, 0xFF
    out     DDRC, temp_1
    out     PORTC, temp_1  
 
    rcall   USART_init
    sei                                     ; Interrupts global aktivieren
    
loop:
    
    rjmp loop                               ; Endlosschleife
 
; Interruptroutine: wird ausgeführt sobald ein Byte über das UART empfangen wurde
USART_init:
  ldi  r16, LOW(UBRR_VAL )  ; Baudrate berechnen..
  ldi  r17, HIGH(UBRR_VAL)
  sts  UBRR0L, r16        ; ...und setzen
  sts  UBRR0H, r17

  lds  r16, UCSR0B
  sbr  r16, (1<<RXCIE0)|(1<<RXEN0)    ; RX-Interrupt enable, RX enable
  sbr  r16, (1<<TXEN0)        ; TX enable
  cbr  r16, (1<<UCSZ02)      ; 8 datenbits
  sts  UCSR0B, r16

  lds  r16, UCSR0C
  cbr  r16, (1<<UCPOL0)      ; asyncron
  cbr  r16, (1<<UMSEL01)|(1<<UMSEL00)    
  cbr  r16, (1<<UPM01)|(1<<UPM00)    ; no parity
  cbr  r16, (1<<USBS0)        ; 1 stopp-bit
  sbr  r16, (1<<UCSZ01)|(1<<UCSZ00)
  sts  UCSR0C, r16
 ret
   
int_rxc:
    push    temp_1                            

    lds      temp_1, UDR0

    com     temp_1                            ;beim STK500 gehen die LED bei Low an
    out     PORTC, temp_1                     

    pop     temp_1                            
reti

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.