www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Warum kann ich senden oder Empfangen aber nicht beides.


Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

Ich habe einzelne Beispiele bei dem ich über den UART senden oder
empfangen kann.
Aber das Programm geht nicht. Ich will das auf den AVR schicken und
dann den Wert verändert
zurückbekommen.
Einmal lief die Sache. Aber ich weiss nicht mehr warum.



include "8515def.inc"

.equ CLOCK = 6000000
.equ BAUD  = 9600
.equ UBRRVAL = CLOCK/(BAUD*16)-1
.def temp  = r16


  rjmp Reset  ;Reset vector
  reti    ;Ext Int 0
  reti    ;Ext Int 1
  reti    ;Timer 1 Capt
  reti    ;Timer 1 CompA
  reti    ;Timer 1 CompB
  reti    ;Timer 1 OVF
  reti    ;Timer 0 OVF
  reti    ;Serial Transfer Complete
  rjmp int_rxc;UART Rx Complete
  reti    ;UART Data register empty
  rjmp int_txc;UART Tx Complete
  reti    ;Analog Comparator



Reset:
  ldi temp,LOW(RAMEND)      ;LOW-Byte der obersten RAM-Adresse
  out SPL, temp
  ldi  temp,HIGH(RAMEND)       ;HIGH-Byte der obersten RAM-Adresse
  out  SPH, temp

  ldi  temp,UBRRVAL      ;Baudrate einstellen
  out  UBRR,temp

  sbi UCR, RXEN               ;Interrupt für Empfangen vom PC
  sbi UCR, RXCIE              ;Interrupt für Empfangen vom PC
        sbi UCR, TXEN               ;Interrupt für Senden zum PC
  sbi UCR, TXCIE              ;Interrupt für Senden zum PC

  ldi temp , 0b11000000       ;RXC=Aktiv, TXC=Aktiv
  out USR, temp

  ldi  temp,0xFF
  out  DDRB, temp               ;Datenrichtung von Port B einstellen, 1 
=
Ausgang
  sei


Main:
  sei
  Lupping:

rjmp  Lupping

;********************* Empfangen von PC *********************
int_rxc:
    in  temp,SREG       ;CPU-Status sichern
  push temp                ;temp auf dem Stack sichern
     in temp, UDR             ;später Wert ausgeben
  out PORTB, temp
  ;rcall int_txc
     pop temp                 ;temp aus dem Stack wieder herstellen
reti                         ;Interrupt beenden
;********************* Empfangen von PC *********************


;********************* Senden an PC *************************
int_txc:
    inc temp
  sbis UCR,UDRE           ;Warten bis UDR für das nächste
    rjmp int_txc            ;Byte bereit ist
    out UDR, temp

reti
;********************* Senden an PC *************************




MfG

Peter

Autor: Jupp van de Balken (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Möglicherweise weil 'rcall int_txc' auskommentiert ist?

Autor: Henning (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nach dem
int_rxc:
in tmp1, sreg
push tmp1
...

pop tmp1

fehlt das
out sreg, tmp1

hmm temp heist das hier, ich nenne es immer tmp1

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Es geht immer noch nicht. Wo liegt der Fehler?
Blöde Frage warum muss man das CPU-Register sichern?


.include "8515def.inc"

.equ CLOCK = 6000000
.equ BAUD  = 9600
.equ UBRRVAL = CLOCK/(BAUD*16)-1
.def temp  = r16


  rjmp Reset  ;Reset vector
  reti    ;Ext Int 0
  reti    ;Ext Int 1
  reti    ;Timer 1 Capt
  reti    ;Timer 1 CompA
  reti    ;Timer 1 CompB
  reti    ;Timer 1 OVF
  reti    ;Timer 0 OVF
  reti    ;Serial Transfer Complete
  rjmp int_rxc;UART Rx Complete
  reti    ;UART Data register empty
  rjmp int_txc;UART Tx Complete
  reti    ;Analog Comparator



Reset:
  ldi temp,LOW(RAMEND)      ;LOW-Byte der obersten RAM-Adresse
  out SPL, temp
  ldi  temp,HIGH(RAMEND)       ;HIGH-Byte der obersten RAM-Adresse
  out  SPH, temp

  ldi  temp,UBRRVAL      ;Baudrate einstellen
  out  UBRR,temp

  sbi UCR, RXEN               ;Interrupt für Empfangen vom PC
  sbi UCR, RXCIE              ;Interrupt für Empfangen vom PC
    sbi UCR, TXEN               ;Interrupt für Senden zum PC
  sbi UCR, TXCIE              ;Interrupt für Senden zum PC

  ldi temp , 0b11000000       ;RXC=Aktiv, TXC=Aktiv
  out USR, temp



  ldi  temp,0xFF
  out  DDRB, temp               ;Datenrichtung von Port B einstellen, 1 
=
Ausgang
  sei


Main:
  sei
  Lupping:

rjmp  Lupping

;********************* Empfangen von PC *********************
int_rxc:
    in  temp,SREG       ;CPU-Status sichern
  push temp                ;temp auf dem Stack sichern
     in temp, UDR             ;später Wert ausgeben
  out PORTB, temp
     pop temp
  out sreg, temp           ;CPU-Status aus dem Stack wieder herstellen
  rcall int_txc
reti                         ;Interrupt beenden
;********************* Empfangen von PC *********************


;********************* Senden an PC *************************
int_txc:
    inc temp
  sbis UCR,UDRE           ;Warten bis UDR für das nächste
    rjmp int_txc            ;Byte bereit ist
    out UDR, temp
reti
;********************* Senden an PC *************

Autor: Henning (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
beim aufruf einen interrupts - dafür sind sie da- wird der normal ablauf
unterbrochen und der interrupt eingschoben.
wenn du aber im normalen programm grad in einer berechnung bist und
brauchst zB das carry flag oder sowas (die sind ja alle im SREG
versammelt) musst du das sichern, bevor es in der interrupt routine
verändert wird.

hab mir das ganze nochmal genauer angeguckt (heut is nicht so spät :)
das kann doch nicht gehen ;)

ich würd da so machen:

main:
hier den Stack initiallisieren
   rcall uart_init

loop:
rjmp loop

und hier die unterfunktionen
UART_Init:
;Baudrate einstellen
  ldi tmp1, UART_fosc / (UART_Baud * 16)-1
  out UBRR, tmp1  ;Baudrate in Register übertragen

  sbi UCR, TXEN  ;TX (Senden) aktivieren

  sbi UCR, RXEN  ;RX (Empfang) aktivieren
  sbi UCR, RXCIE  ;bei Empfang Interrupt auslösen

  ret
UART_SendByte:
;Warten, bis UDR für das nächste Byte bereit ist:
  sbis USR,UDRE
  rjmp UART_SendByte

  out UDR, prm1  ;das Byte aus prm1 Senden
ret

;interrupt zum emfangen über uart
UART_Int_rxc:
;SREG nicht gesichert, da nicht verändert
  push prm1  ;tmp1 retten

        in prm1, UDR
        rcall UART_SendByte ;hier das byte senden

  pop prm1  ;tmp1 wieder herstellen
  reti

Autor: Die Mutter aller Schnäppchen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das

rcall int_txc

muss schon an der Stelle bleiben an der es auch vorher war, also bevor
temp gepopt wird

Autor: Henning (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ach ja: hab das sei vergessen nach dem Uart_init.
und im komentar steht noch tmp1, dabei push ich prm1, aber das ja nich
so wild.

der interrupt tx ready ist dazu da, wenn du große datenmengen im ram
ablegt und schnell senden möchtes wird nach der fertigen übertragung
eines bytes der interrupt ausgelöst und du kannst sofort das nächste
senden. so kannst du die uart maximal auslasten. tut hier aber ja nicht
not...

sach, wenn´s klappt

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Danke für die Hilfe. Hier habe ich mein Beispiel so abgeändert dass
es geht.

MfG

Peter

.include "8515def.inc"

.equ CLOCK = 6000000
.equ BAUD  = 9600
.equ UBRRVAL = CLOCK/(BAUD*16)-1
.def temp  = r16


  rjmp Reset  ;Reset vector
  reti    ;Ext Int 0
  reti    ;Ext Int 1
  reti    ;Timer 1 Capt
  reti    ;Timer 1 CompA
  reti    ;Timer 1 CompB
  reti    ;Timer 1 OVF
  reti    ;Timer 0 OVF
  reti    ;Serial Transfer Complete
  rjmp int_rxc;UART Rx Complete
  reti    ;UART Data register empty
  rjmp int_txc;UART Tx Complete
  reti    ;Analog Comparator





Reset:
  ldi temp,LOW(RAMEND)      ;LOW-Byte der obersten RAM-Adresse
  out SPL, temp
  ldi  temp,HIGH(RAMEND)       ;HIGH-Byte der obersten RAM-Adresse
  out  SPH, temp

  ldi  temp,UBRRVAL      ;Baudrate einstellen
  out  UBRR,temp

  sbi UCR, RXEN          ;RX (Empfang) aktivieren
    sbi UCR, RXCIE        ;bei Empfang Interrupt auslösen
  sbi UCR, TXEN          ;TX (Senden) aktivieren


  ldi temp , 0b11000000       ;RXC=Aktiv, TXC=Aktiv
    out USR, temp

  ldi  temp,0xFF
  out  DDRB, temp               ;Datenrichtung von Port B einstellen, 1 
=
Ausgang
  sei


Main:
  sei
  loop:

rjmp  loop

;********************* Empfangen von PC *********************
int_rxc:
    in  temp,SREG       ;CPU-Status sichern
  push temp                ;temp auf dem Stack sichern
     in temp, UDR             ;später Wert ausgeben
  out PORTB, temp
  rcall int_txc
     pop temp
  out sreg, temp           ;CPU-Status aus dem Stack wieder herstellen
reti                         ;Interrupt beenden
;********************* Empfangen von PC *********************


;********************* Senden an PC *************************
int_txc:
    sbis USR,UDRE
    rjmp int_txc
  inc temp
    out UDR, temp  ;das Byte aus prm1 Senden
ret
;********************* Senden an PC *************************

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.