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


von Anfänger (Gast)


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
1
 
2
.include "m168def.inc"
3
 
4
.def temp_1 = R16
5
 
6
.equ F_CPU = 16000000                            ; Systemtakt in Hz
7
.equ BAUD  = 9600                               ; Baudrate
8
 
9
; Berechnungen
10
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
11
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
12
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille
13
 
14
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
15
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
16
.endif
17
 
18
.org 0x00
19
        rjmp main
20
 
21
.org 0x0024                ; Interruptvektor für UART-Empfang
22
        rjmp int_rxc
23
 
24
; Hauptprogramm
25
 
26
main:
27
 
28
    ; Stackpointer initialisieren
29
 
30
    ldi     temp_1, LOW(ramend)
31
    out     SPL, temp_1
32
    ldi     temp_1, HIGH(ramend)
33
    out     SPH, temp_1
34
 
35
    ; Port D = Ausgang
36
 
37
    ldi     temp_1, 0xFF
38
    out     DDRD, temp_1
39
 
40
    ; Baudrate einstellen
41
 
42
    ldi     temp_1, HIGH(UBRR_VAL)
43
    ldi     XH, HIGH(UBRR0H)
44
    ldi     XH, LOW(UBRR0H)
45
    st      X,temp_1                   ; UBRR0H (0xC5)
46
    ldi     temp_1, LOW(UBRR_VAL)
47
    st      -X,temp_1                  ; UBRR0L (0xC4)
48
 
49
    ; Frame-Format: 8 Bit
50
 
51
    ldi     temp_1,(1<<UMSEL00)|(3<<UCSZ00)
52
    ldi     XH, HIGH(UCSR0C)
53
    ldi     XH, LOW(UCSR0C)
54
    st      X,temp_1
55
 
56
    ldi     temp_1, (1<<RXCIE0)|(1<<RXEN0)
57
    ldi     XH, HIGH(UCSR0B)
58
    ldi     XH, LOW(UCSR0B)
59
    st      X,temp_1
60
61
    sei                          ; Interrupts global aktivieren
62
    
63
loop:
64
    
65
    rjmp loop                    ; Endlosschleife
66
 
67
; Interruptroutine: wird ausgeführt sobald ein Byte 
68
; über das UART empfangen wurde
69
 
70
int_rxc:
71
    push    temp_1                            
72
73
    ldi     XH, HIGH(UDR0)
74
    ldi     XH, LOW(UDR0)
75
    ld      temp_1, X
76
77
    com     temp_1               ;beim STK500 gehen die LED bei Low an
78
    out     PORTD, temp_1                     
79
80
    pop     temp_1                            
81
reti

von ecslowhand (Gast)


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]

von ecslowhand (Gast)


Lesenswert?

Eine komplette Beispielroutine für den MEGA168:
1
; ---------------------
2
; UART0 initialisieren (MEGA168)
3
; ---------------------
4
USART_init:
5
  ldi  r16, LOW((clock/(16*baudrate))-1)  ; Baudrate berechnen..
6
  ldi  r17, HIGH((clock/(16*baudrate))-1)
7
  sts  UBRR0L, r16        ; ...und setzen
8
  sts  UBRR0H, r17
9
10
  lds  r16, UCSR0B
11
  sbr  r16, (1<<RXCIE0)|(1<<RXEN0)    ; RX-Interrupt disable, RX disable
12
  sbr  r16, (1<<TXEN0)        ; TX enable
13
  cbr  r16, (1<<UCSZ02)      ; 8 datenbits
14
  sts  UCSR0B, r16
15
  lds  r16, UCSR0C
16
  cbr  r16, (1<<UCPOL0)      ; asyncron
17
  cbr  r16, (1<<UMSEL01)|(1<<UMSEL00)    
18
  cbr  r16, (1<<UPM01)|(1<<UPM00)    ; no parity
19
  cbr  r16, (1<<USBS0)        ; 1 stopp-bit
20
  cbr  r16, (1<<UCSZ02)      ; 8 datenbits
21
  sbr  r16, (1<<UCSZ01)|(1<<UCSZ00)
22
  sts  UCSR0C, r16
23
  ret


LG EC

von ecslowhand (Gast)


Lesenswert?

Mist, immer wenn`s schnell gehen soll......

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

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

von Anfänger (Gast)


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.
1
.include "m168def.inc"
2
 
3
.def temp_1 = R16
4
 
5
.equ F_CPU = 16000000                            ; Systemtakt in Hz
6
.equ BAUD  = 9600                               ; Baudrate
7
 
8
; Berechnungen
9
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
10
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
11
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille
12
 
13
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
14
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
15
.endif
16
 
17
.org 0x00
18
        rjmp main
19
 
20
.org 0x0024                       ; Interruptvektor für UART-Empfang
21
        jmp int_rxc
22
 
23
; Hauptprogramm
24
 
25
main:
26
 
27
    ; Stackpointer initialisieren
28
 
29
    ldi     temp_1, LOW(ramend)
30
    out     SPL, temp_1
31
    ldi     temp_1, HIGH(ramend)
32
    out     SPH, temp_1
33
 
34
    ; Port C = Ausgang
35
 
36
    ldi     temp_1, 0xFF
37
    out     DDRC, temp_1
38
    out     PORTC, temp_1  
39
 
40
    rcall   USART_init
41
    sei                                     ; Interrupts global aktivieren
42
    
43
loop:
44
    
45
    rjmp loop                               ; Endlosschleife
46
 
47
; Interruptroutine: wird ausgeführt sobald ein Byte über das UART empfangen wurde
48
USART_init:
49
  ldi  r16, LOW(UBRR_VAL )  ; Baudrate berechnen..
50
  ldi  r17, HIGH(UBRR_VAL)
51
  sts  UBRR0L, r16        ; ...und setzen
52
  sts  UBRR0H, r17
53
54
  lds  r16, UCSR0B
55
  sbr  r16, (1<<RXCIE0)|(1<<RXEN0)    ; RX-Interrupt enable, RX enable
56
  sbr  r16, (1<<TXEN0)        ; TX enable
57
  cbr  r16, (1<<UCSZ02)      ; 8 datenbits
58
  sts  UCSR0B, r16
59
60
  lds  r16, UCSR0C
61
  cbr  r16, (1<<UCPOL0)      ; asyncron
62
  cbr  r16, (1<<UMSEL01)|(1<<UMSEL00)    
63
  cbr  r16, (1<<UPM01)|(1<<UPM00)    ; no parity
64
  cbr  r16, (1<<USBS0)        ; 1 stopp-bit
65
  sbr  r16, (1<<UCSZ01)|(1<<UCSZ00)
66
  sts  UCSR0C, r16
67
 ret
68
   
69
int_rxc:
70
    push    temp_1                            
71
72
    lds      temp_1, UDR0
73
74
    com     temp_1                            ;beim STK500 gehen die LED bei Low an
75
    out     PORTC, temp_1                     
76
77
    pop     temp_1                            
78
reti

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.