AVR (ATMega8) USART --> Puffer beschreiben ohne zu senden

Gast #762352
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
#762372
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
Gast #762488
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
#762501
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
Gast #762634
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren