Forum: Mikrocontroller und Digitale Elektronik Übertragung per USART: Nicht jedes Zeichen wird ausgewertet


von gast (Gast)


Lesenswert?

hi

was folgender code machen sollte:

ein zeichen, das per uart empfangen wird, löst den interrupt aus, der 
das t-bit im sreg setzt. in der hauptschleife wird das t-bit abgefragt, 
wenn es gestetzt ist, wird die routine zur behandlung von empfangenen 
bytes gestartet. diese überprüft, ob das empfangene byte ein 'a' ist 
(0x61) und schickt es (wenn es ein 'a' ist) zurück.
1
.include "m8def.inc"
2
3
; Define here the variables
4
;
5
.def tmp = r16    ; erstes register für temp. werte
6
.def tmp2 = r17   ; zweites register für temp. werte
7
.def srg = r20    ; SREG-sicherung
8
.def com_reg = r22  ; letztes kommando des pcs
9
.def stop = r23    ; stop = 1, wenn messung angehalten wurde
10
11
.equ CLOCK = 14745600
12
.equ BAUD = 9600
13
.equ UBRRVAL = CLOCK/(BAUD*16)-1
14
15
16
; Define here Reset and interrupt vectors, if any
17
;
18
.org 0x000                    ; kommt ganz an den Anfang des Speichers
19
         rjmp start           ; Interruptvektoren überspringen
20
                              ; und zum Hauptprogramm
21
      reti      ; IRQ0 Handler
22
      reti      ; IRQ1 Handler
23
      reti
24
      reti
25
      reti      ; Timer1 Capture Handler
26
      reti      ; Timer1 CompareA Handler
27
      reti      ; Timer1 CompareB Handler
28
      reti      ; Timer1 Overflow Handler
29
      reti      ; Timer0 Overflow Handler
30
      reti      ; SPI Transfer Complete Handler
31
      rjmp UAR     ; USART RX Complete Handler      
32
      reti      ; UDR Empty Handler
33
      reti      ; USART TX Complete Handler
34
      reti      ; ADC Conversion Complete Interrupt Handler
35
      reti      ; EEPROM Ready Handler
36
      reti      ; Analog Comparator Handler
37
      reti      ; Two-wire Serial Interface Handler
38
      reti      ; Store Program Memory Ready Handler
39
      
40
      
41
; Program starts here after Reset
42
;
43
start:
44
  ; stack
45
  ldi tmp, LOW(RAMEND)
46
  out SPL, tmp
47
  ldi tmp, HIGH(RAMEND)
48
  out SPH, tmp
49
  
50
  ; baudrate
51
  ldi tmp, LOW(UBRRVAL)
52
  out UBRRL, tmp
53
  ldi tmp, HIGH(UBRRVAL)
54
  out UBRRH, tmp
55
56
  ; frameformat
57
  ldi tmp, (1<<URSEL)|(3<<UCSZ0)
58
  out UCSRC, tmp
59
  
60
  ; TX aktivieren
61
  sbi UCSRB, TXEN
62
  sbi UCSRB, RXEN
63
  sbi UCSRB, RXCIE
64
65
  ; register initialisieren
66
  clr com_reg
67
  
68
  ; interrupts
69
  sei
70
71
f_loop:
72
  
73
  in srg, SREG
74
  sbrs srg, 6
75
  rjmp f_n_com_sw
76
  rcall com_sw  ; kommunikation-switch für empfangenes byte
77
  andi srg, 0b10111111
78
  out SREG, srg
79
80
f_n_com_sw:
81
82
  rjmp f_loop
83
84
85
86
serout:        ; byte über serielle schnitstelle senden
87
  sbis UCSRA,UDRE
88
  rjmp serout
89
  out UDR, tmp
90
  ret
91
92
93
94
UAR:      ; empfangenes byte sichern und t-bit setzen  
95
  in srg, SREG
96
  in com_reg, UDR
97
  ori srg, 0b01000000  ; t-bit im gesicherten sreg setzen
98
  out SREG, srg
99
  reti
100
101
102
103
com_sw:
104
  cpi com_reg, 0x61    ; erkennungs-byte
105
  brne n_rb               ; (un)gleich dem RecognitionByte
106
  mov tmp, com_reg        ; den gleichen wert
107
  rcall serout      ; wieder zurück senden
108
  rjmp by_p
109
    
110
n_rb:  
111
by_p:  ret        ; byte processed
das funktioniert in der praxis aber nur so halb.
es wird zwar das 'a' zurückgeschickt, aber eben nicht jedes 'a'. 
manchmal, wenn ich ein 'a' drücke, passiert einfach nichts.

was läuft falsch? benutze einen atmega8 mit 14.7456 mhz

mfg, johannes

von crazy horse (Gast)


Lesenswert?

Liegt sicher an deinem Gewurschtel mit dem SREG und Register srg. Genau 
habe ich es mir nicht angeschaut, aber das ist schon irgendwie konfus 
(kann aber auch sein, dass es logisch völlig korrekt ist!).
Besser ist es, für solche Zustandsanzeigen Bits aus dem Registerbereich 
zu nehmen.

.def bit_reg = R2
.def rx_complete=0  //Bit0

Uart_rx:
set
bld bit_reg, rx_complete     //Zeichen empfangen -> Bit gesetzt


Abfrage im Hauptprogramm dann mit sbrs/sbrc

von TravelRec. (Gast)


Lesenswert?

Erstens: in der ISR muß immer erst das SREG und alle anderen in der ISR 
verwendeten Register gesichert (auf den Stack ge"push"t) werden. Am Ende 
der ISR müssen diese in umgekehrter Reihenfolge wieder zurückge"pop"t 
werden. Sonst überschreibst Du mit jedem Interrupt die betreffenden 
Register der Main und es kommt nur noch Datenwurst heraus.

Zweitens: Nimm außerdem das t-Bit nicht dafür, weil dies nach der ISR 
durch oben genannte Vorgehensweise eh´ wieder zurückgeschrieben wird. 
Mach Dir ein separates Flagregister irgendwo im SRAM, auf welches Du von 
überall im Programm zugreifen kannst und beeinflusse dort entspechender 
Bits, die Du dann an geeigneter Stelle abfragst.

von Johannes (Gast)


Lesenswert?

> Erstens: in der ISR muß immer erst das SREG und alle anderen in der ISR
> verwendeten Register gesichert (auf den Stack ge"push"t) werden. Am Ende
> der ISR müssen diese in umgekehrter Reihenfolge wieder zurückge"pop"t
> werden. Sonst überschreibst Du mit jedem Interrupt die betreffenden
> Register der Main und es kommt nur noch Datenwurst heraus.

ich habe versucht das mit in srg, SREG am anfang und out SREG, srg am 
ende zu machen. geht das?

> Uart_rx:
> set
> bld bit_reg, rx_complete     ; Zeichen empfangen -> Bit gesetzt

versteh ich irgendwie nicht. zuerst wird mit set das t-bit auf 1 
gesetzt. dann wird das rx_complete-bit aus bit_reg ins t-bit kopiert. 
sinn?

> Zweitens: Nimm außerdem das t-Bit nicht dafür, weil dies nach der ISR
> durch oben genannte Vorgehensweise eh´ wieder zurückgeschrieben wird.
> Mach Dir ein separates Flagregister irgendwo im SRAM, auf welches Du von
> überall im Programm zugreifen kannst und beeinflusse dort entspechender
> Bits, die Du dann an geeigneter Stelle abfragst.

ok. werds mal versuchen

von thkais (Gast)


Lesenswert?

Du benutzt srg sowohl im Hauptprogramm (f_loop) als auch im Interrupt, 
um den Wert von SREG zu laden. Kommt ein Interrupt an einer ungünstigen 
Stelle, knallts.

von Johannes (Gast)


Lesenswert?

> Du benutzt srg sowohl im Hauptprogramm (f_loop) als auch im Interrupt,
> um den Wert von SREG zu laden. Kommt ein Interrupt an einer ungünstigen
> Stelle, knallts.

stimmt. danke

von Uwe (Gast)


Lesenswert?

Hi,
ich kenne da schönere Befehle zb. brts, brtc, clt

Da das Einlesen von UDR keine Flags verändert würde dein Prog bei mir so 
aussehen:
UAR:      ; empfangenes byte sichern und t-bit setzen
  in com_reg, UDR
  set
  reti

MFG Uwe

von gast (Gast)


Lesenswert?

ich habs jetzt so gelöst. bitte sagt mir ob das jetzt immer noch zu 
problemen führen kann:
1
.include "m8def.inc"
2
3
.def flags = r20  ; register für flags
4
.def tmp = r16    ; erstes register für temp. werte
5
.def tmp2 = r17   ; zweites register für temp. werte
6
.def srg = r14    ; SREG-sicherung
7
.def mwc = r21    ; messwert-count
8
.def com_reg = r22  ; letztes kommando des pcs
9
10
.equ CLOCK = 14745600
11
.equ BAUD = 9600
12
.equ UBRRVAL = CLOCK/(BAUD*16)-1
13
14
.equ C_CYC = 96
15
.equ PRESC = 8
16
.equ OCR = (C_CYC / PRESC) - 1
17
18
19
; Define here Reset and interrupt vectors, if any
20
;
21
.org 0x000                    ; kommt ganz an den Anfang des Speichers
22
         rjmp start           ; Interruptvektoren überspringen
23
                              ; und zum Hauptprogramm
24
      reti      ; IRQ0 Handler
25
      reti      ; IRQ1 Handler
26
      reti
27
      reti
28
      reti      ; Timer1 Capture Handler
29
      reti      ; Timer1 CompareA Handler
30
      reti      ; Timer1 CompareB Handler
31
      reti      ; Timer1 Overflow Handler
32
      reti      ; Timer0 Overflow Handler
33
      reti      ; SPI Transfer Complete Handler
34
      rjmp UAR     ; USART RX Complete Handler      
35
      reti      ; UDR Empty Handler
36
      reti      ; USART TX Complete Handler
37
      reti      ; ADC Conversion Complete Interrupt Handler
38
      reti      ; EEPROM Ready Handler
39
      reti      ; Analog Comparator Handler
40
      reti      ; Two-wire Serial Interface Handler
41
      reti      ; Store Program Memory Ready Handler
42
      
43
      
44
45
46
; Program starts here after Reset
47
;
48
start:
49
  ; stack
50
  ldi tmp, LOW(RAMEND)
51
  out SPL, tmp
52
  ldi tmp, HIGH(RAMEND)
53
  out SPH, tmp
54
  
55
  ; baudrate
56
  ldi tmp, LOW(UBRRVAL)
57
  out UBRRL, tmp
58
  ldi tmp, HIGH(UBRRVAL)
59
  out UBRRH, tmp
60
61
  ; frameformat
62
  ldi tmp, (1<<URSEL)|(3<<UCSZ0)
63
  out UCSRC, tmp
64
  
65
  ; TX aktivieren
66
  sbi UCSRB, TXEN
67
  sbi UCSRB, RXEN
68
  sbi UCSRB, RXCIE
69
70
  ; register initialisieren
71
  clr com_reg
72
  clr flags
73
  
74
  ; interrupts
75
  sei
76
77
f_loop:
78
  
79
  sbrs flags, 0
80
  rjmp f_n_com_sw
81
  cbr flags, 1
82
  rcall com_sw  ; kommunikation-switch für empfangenes byte
83
84
f_n_com_sw:
85
86
  rjmp f_loop
87
88
89
90
serout:        ; byte über serielle schnitstelle senden
91
  sbis UCSRA,UDRE
92
  rjmp serout
93
  out UDR, tmp
94
  ret
95
96
97
UAR:          ; empfangenes byte sichern und t-bit setzen  
98
  in srg, SREG  
99
  in com_reg, UDR
100
  sbr flags, 1
101
  out SREG, srg
102
  reti
103
104
105
106
107
com_sw:
108
  cpi com_reg, 0x61    ; erkennungs-byte
109
  brne n_rb               ; (un)gleich dem RecognitionByte
110
  mov tmp, com_reg        ; den gleichen wert
111
  rcall serout      ; wieder zurück senden
112
  rjmp by_p
113
    
114
n_rb:
115
  
116
by_p:  ret        ; byte processed

mfg, johannes

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.