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


von pacer (Gast)


Lesenswert?

Hallo,

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

Gruß pacer

von Falk B. (falk)


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

von pacer (Gast)


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:
1
 .NOLIST                      ; List-Output unterdrücken
2
; .INCLUDE <m8def.inc>         ; das gibt es für jeden Controllertyp
3
 .include "C:\PROGRA~1\VMLAB\include\m8def.inc
4
5
 .def temp = R16        ; für Interrupt
6
 .def ZEICHEN = R17
7
8
9
 ;------------------------------------------------------
10
 ;    Peripherie initialisieren
11
 ;------------------------------------------------------
12
.equ F_CPU = 7372800                            ; Systemtakt in Hz
13
.equ BAUD  = 9600                               ; Baudrate
14
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; Berechnen des Teilers für die Baudrate
15
16
 .LIST                        ; List-Output wieder aufdrehen
17
 .CSEG                        ; was nun folgt, gehört in den FLASH-Speicher
18
19
20
 ;------------------------------------------------------
21
 ;     Start Adresse 0000 /Interruptvektoren
22
 ;------------------------------------------------------
23
 .org 0x000      ; Interruptvektoren überspringen
24
  rjmp Init      
25
26
  .org 0x00B    ; UART Receive Complete Interrupt
27
    rjmp serin
28
29
  .org 0x00C    ; USART Data Register Empty
30
    rjmp serout
31
32
 ;------------------------------------------------------
33
 ;     INITIALIZE
34
 ;------------------------------------------------------
35
INIT:
36
;Stack Pointer setzen
37
  ldi temp,high(RAMEND)
38
  out SPH,temp
39
  ldi temp,low(RAMEND)
40
  out SPL,temp
41
42
; Baudrate einstellen
43
  ldi temp, HIGH(UBRR_VAL)
44
  out UBRRH, temp
45
  ldi temp, LOW(UBRR_VAL)
46
  out UBRRL, temp
47
48
; Frame-Format: 1 Stop-Bits, 8 Bit
49
  ldi temp, (1<<URSEL)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)
50
  out UCSRC, temp
51
52
  sbi UCSRB,RXEN          ; Freigabe Empfangen
53
  sbi UCSRB,RXCIE          ; Interrupt für "Zeichen empfangen"
54
  sbi UCSRB,UDRIE          ; Interrupt für "Puffer leer"
55
56
57
  ldi ZEICHEN, '>'          ; erstes Zeichen in Puffer schieben damit Interrupt "Puffer leer"
58
     out UDR, ZEICHEN         ; nicht ausgelöst wird
59
60
61
  sei                 ; globale Interruptfreigabe
62
 ;------------------------------------------------------
63
 ;   HAUPTSCHLEIFE
64
 ;------------------------------------------------------
65
Hauptschleife:          
66
  
67
68
rjmp Hauptschleife
69
70
71
 ;------------------------------------------------------
72
 ;   Subroutinen / ISRs
73
 ;------------------------------------------------------
74
75
;Auslesen der Zeichen und bereitstellen in ZEICHEN
76
;Erhöhen des Z-Pointers; bei leerem Zeichen ISR verlassen
77
78
serout:                ; (ISR)
79
   lpm                ; Erstes Byte des Strings nach R0 lesen
80
81
   mov ZEICHEN,R0
82
   adiw ZL, 1                       ; Adresse des Z-Pointers um 1 erhöhen
83
   tst R0              ; Inhalt von R0 auf Null testen
84
85
   brbc 1,sprung_a          ; nächten Befehlsblock ausführen wenn String gesendet
86
    cbi UCSRB,TXEN          ; Sperren Senden
87
   ldi ZEICHEN, '>'        ; ersten Interrupt auslösen damit Zeichenversand
88
    out UDR, ZEICHEN         ; beginnen kann
89
   rjmp string_ready
90
91
   sprung_a:
92
    out     UDR, ZEICHEN      ; Zeichen auf UART ausgeben
93
94
   string_ready:
95
   reti
96
97
98
serin:                 ; (ISR)
99
    sbi UCSRB,TXEN               ; Sender aktivieren --> gespeichertes Zeichen '>' wird gesendet
100
101
    ldi ZL, LOW(Daten*2)      ; Adresse des ersten Strings in den
102
    ldi ZH, HIGH(Daten*2)      ; Z-Pointer laden
103
reti
104
105
 ;------------------------------------------------------
106
 ;   Datenbereich
107
 ;------------------------------------------------------
108
Daten:
109
           .db "Test!",10,13,0  
110
111
 ;------------------------------------------------------
112
 ;   ENDE
113
 ;------------------------------------------------------
114
 Ende:
115
        rjmp Ende

von Falk B. (falk)


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

1
    sbi UCSRB,TXEN

sondern

1
    sbi UCSRB,UDRIE

Natülich am Anfang den Sender einschalten

1
 sbi UCSRB,TXEN          ; Freigabe Sender

Siehe auch

Interrupt

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

MfG
Falk

von pacer (Gast)


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?
1
 .NOLIST                      ; List-Output unterdrücken
2
; .INCLUDE <m8def.inc>         ; das gibt es für jeden Controllertyp
3
 .include "C:\PROGRA~1\VMLAB\include\m8def.inc
4
5
 .def temp = R16        ; für Interrupt
6
 .def ZEICHEN = R17
7
8
9
 ;------------------------------------------------------
10
 ;    Peripherie initialisieren
11
 ;------------------------------------------------------
12
.equ F_CPU = 7372800                            ; Systemtakt in Hz
13
.equ BAUD  = 9600                               ; Baudrate
14
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; Berechnen des Teilers für die Baudrate
15
16
 .LIST                        ; List-Output wieder aufdrehen
17
 .CSEG                        ; was nun folgt, gehört in den FLASH-Speicher
18
19
20
 ;------------------------------------------------------
21
 ;     Start Adresse 0000 /Interruptvektoren
22
 ;------------------------------------------------------
23
 .org 0x000      ; Interruptvektoren überspringen
24
  rjmp Init      
25
26
  .org 0x00B    ; UART Receive Complete Interrupt
27
    rjmp serin
28
29
30
 ;------------------------------------------------------
31
 ;     INITIALIZE
32
 ;------------------------------------------------------
33
INIT:
34
;Stack Pointer setzen
35
  ldi temp,high(RAMEND)
36
  out SPH,temp
37
  ldi temp,low(RAMEND)
38
  out SPL,temp
39
40
; Baudrate einstellen
41
  ldi temp, HIGH(UBRR_VAL)
42
  out UBRRH, temp
43
  ldi temp, LOW(UBRR_VAL)
44
  out UBRRL, temp
45
46
; Frame-Format: 1 Stop-Bits, 8 Bit
47
  ldi temp, (1<<URSEL)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)
48
  out UCSRC, temp
49
50
  sbi UCSRB,RXEN          ; Freigabe Empfangen
51
  sbi UCSRB,RXCIE          ; Interrupt für "Zeichen empfangen"
52
  sbi UCSRB,TXEN          ; Freigabe senden
53
  sei                 ; globale Interruptfreigabe
54
55
56
 ;------------------------------------------------------
57
 ;   HAUPTSCHLEIFE
58
 ;------------------------------------------------------
59
Hauptschleife:          
60
  
61
62
rjmp Hauptschleife
63
64
65
 ;------------------------------------------------------
66
 ;   Subroutinen / ISRs
67
 ;------------------------------------------------------
68
serin:                 ; (ISR)
69
70
  ldi ZEICHEN, '>'          ; diese Zeichen als Antwort der ISR ausgeben
71
   out UDR, ZEICHEN
72
73
reti              
74
75
 ;------------------------------------------------------
76
 ;   ENDE
77
 ;------------------------------------------------------
78
 Ende:
79
        rjmp Ende

von Falk B. (falk)


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.

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

AVR-Tutorial: UART

Einfach mal das Tutorial und Datenblatt in Ruhe durchlesen.

MfG
Falk

von pacer (Gast)


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...
1
 .NOLIST                      ; List-Output unterdrücken
2
 .INCLUDE <m8def.inc>         ; das gibt es für jeden Controllertyp
3
; .include "C:\PROGRA~1\VMLAB\include\m8def.inc
4
5
 .def temp = R16        ; für Interrupt
6
 .def ZEICHEN = R17
7
8
9
 ;------------------------------------------------------
10
 ;    Peripherie initialisieren
11
 ;------------------------------------------------------
12
.equ F_CPU = 7372800                            ; Systemtakt in Hz
13
.equ BAUD  = 9600                               ; Baudrate
14
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; Berechnen des Teilers für die Baudrate
15
16
 .LIST                        ; List-Output wieder aufdrehen
17
 .CSEG                        ; was nun folgt, gehört in den FLASH-Speicher
18
19
20
 ;------------------------------------------------------
21
 ;     Start Adresse 0000 /Interruptvektoren
22
 ;------------------------------------------------------
23
 .org 0x000      ; Interruptvektoren überspringen
24
  rjmp Init      
25
26
  .org 0x00B    ; UART Receive Complete Interrupt
27
    rjmp serin
28
29
  .org 0x00C    ; USART Data Register Empty
30
    rjmp serout
31
32
 ;------------------------------------------------------
33
 ;     INITIALIZE
34
 ;------------------------------------------------------
35
INIT:
36
;Stack Pointer setzen
37
  ldi temp,high(RAMEND)
38
  out SPH,temp
39
  ldi temp,low(RAMEND)
40
  out SPL,temp
41
42
; Baudrate einstellen
43
  ldi temp, HIGH(UBRR_VAL)
44
  out UBRRH, temp
45
  ldi temp, LOW(UBRR_VAL)
46
  out UBRRL, temp
47
48
; Frame-Format: 1 Stop-Bits, 8 Bit
49
  ldi temp, (1<<URSEL)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)
50
  out UCSRC, temp
51
52
  sbi UCSRB,RXEN          ; Freigabe Empfangen
53
  sbi UCSRB,RXCIE          ; Interrupt für "Zeichen empfangen"
54
  sbi UCSRB,TXEN                 ; Sender aktivieren
55
56
  sei                 ; globale Interruptfreigabe
57
58
59
 ;------------------------------------------------------
60
 ;   HAUPTSCHLEIFE
61
 ;------------------------------------------------------
62
Hauptschleife:          
63
  
64
65
rjmp Hauptschleife
66
67
68
 ;------------------------------------------------------
69
 ;   Subroutinen / ISRs
70
 ;------------------------------------------------------
71
72
;Auslesen der Zeichen und bereitstellen in ZEICHEN
73
;Erhöhen des Z-Pointers; bei leerem Zeichen --> Zurücksetzen des Z-Pointers
74
75
serout:                ; (ISR)
76
   lpm                ; Erstes Byte des Strings nach R0 lesen
77
78
   mov ZEICHEN,R0
79
   adiw ZL, 1                       ; Adresse des Z-Pointers um 1 erhöhen
80
   tst R0              ; Inhalt von R0 auf Null testen
81
82
   brbc 1,sprung_a          ; nächten Befehl ausführen wenn kompletter String gesendet
83
    cbi UCSRB,UDRIE          ; Interrupt für "Puffer leer"
84
85
   sprung_a:
86
    out UDR, ZEICHEN        ; Zeichen auf UART ausgeben
87
reti
88
89
90
serin:                 ; (ISR)
91
92
  in temp, UDR            ; Puffer leeren
93
  ldi ZEICHEN, '>'          ; diese Zeichen als Antwort der ISR ausgeben
94
   out UDR, ZEICHEN
95
96
  ldi ZL, LOW(Daten*2)        ; Adresse des ersten Strings in den
97
  ldi ZH, HIGH(Daten*2)        ; Z-Pointer laden
98
99
  sbi UCSRB,UDRIE          ; Interrupt für "Puffer leer" freigeben
100
101
reti                ; Beim Verlassen wird sofort in die ISR für Senden gewechselt, UDRE=1
102
                  ; und der Interrupt freigegeben ist
103
104
 ;------------------------------------------------------
105
 ;   Datenbereich
106
 ;------------------------------------------------------
107
Daten:
108
           .db "Test!",10,13,0  
109
110
 ;------------------------------------------------------
111
 ;   ENDE
112
 ;------------------------------------------------------
113
 Ende:
114
        rjmp Ende

danke für die Hilfe

von pacer (Gast)


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 ;-)

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.