mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR (ATMega8) USART --> Puffer beschreiben ohne zu senden


Autor: pacer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wollte mal fragen ob es möglich ist, Sendepuffer des USART zu laden, 
ohne jedoch das Zeichen zu versenden?

Gruß pacer

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ pacer (Gast)

>wollte mal fragen ob es möglich ist, Sendepuffer des USART zu laden,
>ohne jedoch das Zeichen zu versenden?

Wenn der Sender aus ist. Aber dann verschwinden deine Daten auch. Wozu 
soll das gut sein?

MFG
Falk

Autor: pacer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
es ist so gedacht, dass der Interrupt für das Empfangen von Zeichen 
aktiv ist. Wenn nun ein Zeichen empfangen wird, soll der AVR eine 
Zeichenkette ausgeben, die ebenfalls interrupt-gesteuert ist.

Hier mal der Code, vielleicht wird meine Absicht ja deutlicher:
 .NOLIST                      ; List-Output unterdrücken
; .INCLUDE <m8def.inc>         ; das gibt es für jeden Controllertyp
 .include "C:\PROGRA~1\VMLAB\include\m8def.inc

 .def temp = R16        ; für Interrupt
 .def ZEICHEN = R17


 ;------------------------------------------------------
 ;    Peripherie initialisieren
 ;------------------------------------------------------
.equ F_CPU = 7372800                            ; Systemtakt in Hz
.equ BAUD  = 9600                               ; Baudrate
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; Berechnen des Teilers für die Baudrate

 .LIST                        ; List-Output wieder aufdrehen
 .CSEG                        ; was nun folgt, gehört in den FLASH-Speicher


 ;------------------------------------------------------
 ;     Start Adresse 0000 /Interruptvektoren
 ;------------------------------------------------------
 .org 0x000      ; Interruptvektoren überspringen
  rjmp Init      

  .org 0x00B    ; UART Receive Complete Interrupt
    rjmp serin

  .org 0x00C    ; USART Data Register Empty
    rjmp serout

 ;------------------------------------------------------
 ;     INITIALIZE
 ;------------------------------------------------------
INIT:
;Stack Pointer setzen
  ldi temp,high(RAMEND)
  out SPH,temp
  ldi temp,low(RAMEND)
  out SPL,temp

; Baudrate einstellen
  ldi temp, HIGH(UBRR_VAL)
  out UBRRH, temp
  ldi temp, LOW(UBRR_VAL)
  out UBRRL, temp

; Frame-Format: 1 Stop-Bits, 8 Bit
  ldi temp, (1<<URSEL)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)
  out UCSRC, temp

  sbi UCSRB,RXEN          ; Freigabe Empfangen
  sbi UCSRB,RXCIE          ; Interrupt für "Zeichen empfangen"
  sbi UCSRB,UDRIE          ; Interrupt für "Puffer leer"


  ldi ZEICHEN, '>'          ; erstes Zeichen in Puffer schieben damit Interrupt "Puffer leer"
     out UDR, ZEICHEN         ; nicht ausgelöst wird


  sei                 ; globale Interruptfreigabe
 ;------------------------------------------------------
 ;   HAUPTSCHLEIFE
 ;------------------------------------------------------
Hauptschleife:          
  

rjmp Hauptschleife


 ;------------------------------------------------------
 ;   Subroutinen / ISRs
 ;------------------------------------------------------

;Auslesen der Zeichen und bereitstellen in ZEICHEN
;Erhöhen des Z-Pointers; bei leerem Zeichen ISR verlassen

serout:                ; (ISR)
   lpm                ; Erstes Byte des Strings nach R0 lesen

   mov ZEICHEN,R0
   adiw ZL, 1                       ; Adresse des Z-Pointers um 1 erhöhen
   tst R0              ; Inhalt von R0 auf Null testen

   brbc 1,sprung_a          ; nächten Befehlsblock ausführen wenn String gesendet
    cbi UCSRB,TXEN          ; Sperren Senden
   ldi ZEICHEN, '>'        ; ersten Interrupt auslösen damit Zeichenversand
    out UDR, ZEICHEN         ; beginnen kann
   rjmp string_ready

   sprung_a:
    out     UDR, ZEICHEN      ; Zeichen auf UART ausgeben

   string_ready:
   reti


serin:                 ; (ISR)
    sbi UCSRB,TXEN               ; Sender aktivieren --> gespeichertes Zeichen '>' wird gesendet

    ldi ZL, LOW(Daten*2)      ; Adresse des ersten Strings in den
    ldi ZH, HIGH(Daten*2)      ; Z-Pointer laden
reti

 ;------------------------------------------------------
 ;   Datenbereich
 ;------------------------------------------------------
Daten:
           .db "Test!",10,13,0  

 ;------------------------------------------------------
 ;   ENDE
 ;------------------------------------------------------
 Ende:
        rjmp Ende

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ pacer (Gast)

>Hier mal der Code, vielleicht wird meine Absicht ja deutlicher:

Schreib doch DIREKT, was du willst.

>  ldi ZEICHEN, '>'          ; erstes Zeichen in Puffer schieben damit
>Interrupt "Puffer leer"
>     out UDR, ZEICHEN         ; nicht ausgelöst wird

Das hier, nicht wahr?

Nun, das löst man anders. Der UDRE Interrupt bleibt solange 
ausgeschaltet, bis er gebraucht wird.
Also NICHT

    sbi UCSRB,TXEN

sondern

    sbi UCSRB,UDRIE

Natülich am Anfang den Sender einschalten

 sbi UCSRB,TXEN          ; Freigabe Sender

Siehe auch

Interrupt

Ist zwar C, sollte aber für dich lesbar sein.

MfG
Falk

Autor: pacer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich muss wohl nochmal etwas zurück gehen:
Ich habe noch das Problem, dass meine ISR schon verlassen wird und der 
receive-buffer aber noch nicht leer ist. Deswegen ist nach dem Verlassen 
der ISR das RXC-Flag noch immer gesetzt.
Nun kann ich aber innerhalb der ISR das Flag nicht abfragen weil es erst 
beim Verlassen der ISR zurückgesetzt wird, wenn der receive-buffer leer 
ist.

Wie kann man das Problem innerhalb der ISR lösen ohne eine Zählschleife 
einzubauen?
 .NOLIST                      ; List-Output unterdrücken
; .INCLUDE <m8def.inc>         ; das gibt es für jeden Controllertyp
 .include "C:\PROGRA~1\VMLAB\include\m8def.inc

 .def temp = R16        ; für Interrupt
 .def ZEICHEN = R17


 ;------------------------------------------------------
 ;    Peripherie initialisieren
 ;------------------------------------------------------
.equ F_CPU = 7372800                            ; Systemtakt in Hz
.equ BAUD  = 9600                               ; Baudrate
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; Berechnen des Teilers für die Baudrate

 .LIST                        ; List-Output wieder aufdrehen
 .CSEG                        ; was nun folgt, gehört in den FLASH-Speicher


 ;------------------------------------------------------
 ;     Start Adresse 0000 /Interruptvektoren
 ;------------------------------------------------------
 .org 0x000      ; Interruptvektoren überspringen
  rjmp Init      

  .org 0x00B    ; UART Receive Complete Interrupt
    rjmp serin


 ;------------------------------------------------------
 ;     INITIALIZE
 ;------------------------------------------------------
INIT:
;Stack Pointer setzen
  ldi temp,high(RAMEND)
  out SPH,temp
  ldi temp,low(RAMEND)
  out SPL,temp

; Baudrate einstellen
  ldi temp, HIGH(UBRR_VAL)
  out UBRRH, temp
  ldi temp, LOW(UBRR_VAL)
  out UBRRL, temp

; Frame-Format: 1 Stop-Bits, 8 Bit
  ldi temp, (1<<URSEL)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)
  out UCSRC, temp

  sbi UCSRB,RXEN          ; Freigabe Empfangen
  sbi UCSRB,RXCIE          ; Interrupt für "Zeichen empfangen"
  sbi UCSRB,TXEN          ; Freigabe senden
  sei                 ; globale Interruptfreigabe


 ;------------------------------------------------------
 ;   HAUPTSCHLEIFE
 ;------------------------------------------------------
Hauptschleife:          
  

rjmp Hauptschleife


 ;------------------------------------------------------
 ;   Subroutinen / ISRs
 ;------------------------------------------------------
serin:                 ; (ISR)

  ldi ZEICHEN, '>'          ; diese Zeichen als Antwort der ISR ausgeben
   out UDR, ZEICHEN

reti              

 ;------------------------------------------------------
 ;   ENDE
 ;------------------------------------------------------
 Ende:
        rjmp Ende

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ pacer (Gast)

>Ich habe noch das Problem, dass meine ISR schon verlassen wird und der
>receive-buffer aber noch nicht leer ist. Deswegen ist nach dem Verlassen
>der ISR das RXC-Flag noch immer gesetzt.

Klar, du MUSST in der ISR UDR lesen, um das Flag zu löschen.

serin:                 ; (ISR)
  in zeichen,udr            ; empfangenes Zeichen lesen und dadurch RXC löschen
  ldi ZEICHEN, '>'          ; diese Zeichen als Antwort der ISR ausgeben
  out UDR, ZEICHEN

reti              


AVR-Tutorial: UART

Einfach mal das Tutorial und Datenblatt in Ruhe durchlesen.

MfG
Falk

Autor: pacer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habs jetzt doch geschafft, sendet man ein Zeichen per UART an den 
Controller, so sendet dieser eine Zeichenkette zurück. Senden und 
Empfangen geschieht Interruptgesteuert.
Eigentlich ganz einfach, aber als Anfänger macht man halt 
Anfängerfehler...
 .NOLIST                      ; List-Output unterdrücken
 .INCLUDE <m8def.inc>         ; das gibt es für jeden Controllertyp
; .include "C:\PROGRA~1\VMLAB\include\m8def.inc

 .def temp = R16        ; für Interrupt
 .def ZEICHEN = R17


 ;------------------------------------------------------
 ;    Peripherie initialisieren
 ;------------------------------------------------------
.equ F_CPU = 7372800                            ; Systemtakt in Hz
.equ BAUD  = 9600                               ; Baudrate
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; Berechnen des Teilers für die Baudrate

 .LIST                        ; List-Output wieder aufdrehen
 .CSEG                        ; was nun folgt, gehört in den FLASH-Speicher


 ;------------------------------------------------------
 ;     Start Adresse 0000 /Interruptvektoren
 ;------------------------------------------------------
 .org 0x000      ; Interruptvektoren überspringen
  rjmp Init      

  .org 0x00B    ; UART Receive Complete Interrupt
    rjmp serin

  .org 0x00C    ; USART Data Register Empty
    rjmp serout

 ;------------------------------------------------------
 ;     INITIALIZE
 ;------------------------------------------------------
INIT:
;Stack Pointer setzen
  ldi temp,high(RAMEND)
  out SPH,temp
  ldi temp,low(RAMEND)
  out SPL,temp

; Baudrate einstellen
  ldi temp, HIGH(UBRR_VAL)
  out UBRRH, temp
  ldi temp, LOW(UBRR_VAL)
  out UBRRL, temp

; Frame-Format: 1 Stop-Bits, 8 Bit
  ldi temp, (1<<URSEL)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)
  out UCSRC, temp

  sbi UCSRB,RXEN          ; Freigabe Empfangen
  sbi UCSRB,RXCIE          ; Interrupt für "Zeichen empfangen"
  sbi UCSRB,TXEN                 ; Sender aktivieren

  sei                 ; globale Interruptfreigabe


 ;------------------------------------------------------
 ;   HAUPTSCHLEIFE
 ;------------------------------------------------------
Hauptschleife:          
  

rjmp Hauptschleife


 ;------------------------------------------------------
 ;   Subroutinen / ISRs
 ;------------------------------------------------------

;Auslesen der Zeichen und bereitstellen in ZEICHEN
;Erhöhen des Z-Pointers; bei leerem Zeichen --> Zurücksetzen des Z-Pointers

serout:                ; (ISR)
   lpm                ; Erstes Byte des Strings nach R0 lesen

   mov ZEICHEN,R0
   adiw ZL, 1                       ; Adresse des Z-Pointers um 1 erhöhen
   tst R0              ; Inhalt von R0 auf Null testen

   brbc 1,sprung_a          ; nächten Befehl ausführen wenn kompletter String gesendet
    cbi UCSRB,UDRIE          ; Interrupt für "Puffer leer"

   sprung_a:
    out UDR, ZEICHEN        ; Zeichen auf UART ausgeben
reti


serin:                 ; (ISR)

  in temp, UDR            ; Puffer leeren
  ldi ZEICHEN, '>'          ; diese Zeichen als Antwort der ISR ausgeben
   out UDR, ZEICHEN

  ldi ZL, LOW(Daten*2)        ; Adresse des ersten Strings in den
  ldi ZH, HIGH(Daten*2)        ; Z-Pointer laden

  sbi UCSRB,UDRIE          ; Interrupt für "Puffer leer" freigeben

reti                ; Beim Verlassen wird sofort in die ISR für Senden gewechselt, UDRE=1
                  ; und der Interrupt freigegeben ist

 ;------------------------------------------------------
 ;   Datenbereich
 ;------------------------------------------------------
Daten:
           .db "Test!",10,13,0  

 ;------------------------------------------------------
 ;   ENDE
 ;------------------------------------------------------
 Ende:
        rjmp Ende

danke für die Hilfe

Autor: pacer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
keine Sorge, ich habe mich schon seit einigen Tagen mit dem Tutorial 
beschäftigt, aber nicht alles ist immer erklärt und manchmal verliere 
ich schon mal den Überblick ;-)

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.