mikrocontroller.net

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


Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
.include "m8def.inc"

; Define here the variables
;
.def tmp = r16    ; erstes register für temp. werte
.def tmp2 = r17   ; zweites register für temp. werte
.def srg = r20    ; SREG-sicherung
.def com_reg = r22  ; letztes kommando des pcs
.def stop = r23    ; stop = 1, wenn messung angehalten wurde

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


; Define here Reset and interrupt vectors, if any
;
.org 0x000                    ; kommt ganz an den Anfang des Speichers
         rjmp start           ; Interruptvektoren überspringen
                              ; und zum Hauptprogramm
      reti      ; IRQ0 Handler
      reti      ; IRQ1 Handler
      reti
      reti
      reti      ; Timer1 Capture Handler
      reti      ; Timer1 CompareA Handler
      reti      ; Timer1 CompareB Handler
      reti      ; Timer1 Overflow Handler
      reti      ; Timer0 Overflow Handler
      reti      ; SPI Transfer Complete Handler
      rjmp UAR     ; USART RX Complete Handler      
      reti      ; UDR Empty Handler
      reti      ; USART TX Complete Handler
      reti      ; ADC Conversion Complete Interrupt Handler
      reti      ; EEPROM Ready Handler
      reti      ; Analog Comparator Handler
      reti      ; Two-wire Serial Interface Handler
      reti      ; Store Program Memory Ready Handler
      
      
; Program starts here after Reset
;
start:
  ; stack
  ldi tmp, LOW(RAMEND)
  out SPL, tmp
  ldi tmp, HIGH(RAMEND)
  out SPH, tmp
  
  ; baudrate
  ldi tmp, LOW(UBRRVAL)
  out UBRRL, tmp
  ldi tmp, HIGH(UBRRVAL)
  out UBRRH, tmp

  ; frameformat
  ldi tmp, (1<<URSEL)|(3<<UCSZ0)
  out UCSRC, tmp
  
  ; TX aktivieren
  sbi UCSRB, TXEN
  sbi UCSRB, RXEN
  sbi UCSRB, RXCIE

  ; register initialisieren
  clr com_reg
  
  ; interrupts
  sei

f_loop:
  
  in srg, SREG
  sbrs srg, 6
  rjmp f_n_com_sw
  rcall com_sw  ; kommunikation-switch für empfangenes byte
  andi srg, 0b10111111
  out SREG, srg

f_n_com_sw:

  rjmp f_loop



serout:        ; byte über serielle schnitstelle senden
  sbis UCSRA,UDRE
  rjmp serout
  out UDR, tmp
  ret



UAR:      ; empfangenes byte sichern und t-bit setzen  
  in srg, SREG
  in com_reg, UDR
  ori srg, 0b01000000  ; t-bit im gesicherten sreg setzen
  out SREG, srg
  reti



com_sw:
  cpi com_reg, 0x61    ; erkennungs-byte
  brne n_rb               ; (un)gleich dem RecognitionByte
  mov tmp, com_reg        ; den gleichen wert
  rcall serout      ; wieder zurück senden
  rjmp by_p
    
n_rb:  
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

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: TravelRec. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: thkais (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habs jetzt so gelöst. bitte sagt mir ob das jetzt immer noch zu 
problemen führen kann:
.include "m8def.inc"

.def flags = r20  ; register für flags
.def tmp = r16    ; erstes register für temp. werte
.def tmp2 = r17   ; zweites register für temp. werte
.def srg = r14    ; SREG-sicherung
.def mwc = r21    ; messwert-count
.def com_reg = r22  ; letztes kommando des pcs

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

.equ C_CYC = 96
.equ PRESC = 8
.equ OCR = (C_CYC / PRESC) - 1


; Define here Reset and interrupt vectors, if any
;
.org 0x000                    ; kommt ganz an den Anfang des Speichers
         rjmp start           ; Interruptvektoren überspringen
                              ; und zum Hauptprogramm
      reti      ; IRQ0 Handler
      reti      ; IRQ1 Handler
      reti
      reti
      reti      ; Timer1 Capture Handler
      reti      ; Timer1 CompareA Handler
      reti      ; Timer1 CompareB Handler
      reti      ; Timer1 Overflow Handler
      reti      ; Timer0 Overflow Handler
      reti      ; SPI Transfer Complete Handler
      rjmp UAR     ; USART RX Complete Handler      
      reti      ; UDR Empty Handler
      reti      ; USART TX Complete Handler
      reti      ; ADC Conversion Complete Interrupt Handler
      reti      ; EEPROM Ready Handler
      reti      ; Analog Comparator Handler
      reti      ; Two-wire Serial Interface Handler
      reti      ; Store Program Memory Ready Handler
      
      


; Program starts here after Reset
;
start:
  ; stack
  ldi tmp, LOW(RAMEND)
  out SPL, tmp
  ldi tmp, HIGH(RAMEND)
  out SPH, tmp
  
  ; baudrate
  ldi tmp, LOW(UBRRVAL)
  out UBRRL, tmp
  ldi tmp, HIGH(UBRRVAL)
  out UBRRH, tmp

  ; frameformat
  ldi tmp, (1<<URSEL)|(3<<UCSZ0)
  out UCSRC, tmp
  
  ; TX aktivieren
  sbi UCSRB, TXEN
  sbi UCSRB, RXEN
  sbi UCSRB, RXCIE

  ; register initialisieren
  clr com_reg
  clr flags
  
  ; interrupts
  sei

f_loop:
  
  sbrs flags, 0
  rjmp f_n_com_sw
  cbr flags, 1
  rcall com_sw  ; kommunikation-switch für empfangenes byte

f_n_com_sw:

  rjmp f_loop



serout:        ; byte über serielle schnitstelle senden
  sbis UCSRA,UDRE
  rjmp serout
  out UDR, tmp
  ret


UAR:          ; empfangenes byte sichern und t-bit setzen  
  in srg, SREG  
  in com_reg, UDR
  sbr flags, 1
  out SREG, srg
  reti




com_sw:
  cpi com_reg, 0x61    ; erkennungs-byte
  brne n_rb               ; (un)gleich dem RecognitionByte
  mov tmp, com_reg        ; den gleichen wert
  rcall serout      ; wieder zurück senden
  rjmp by_p
    
n_rb:
  
by_p:  ret        ; byte processed


mfg, johannes

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.