von
pacer (Gast)
25.01.2008 19:58
Hallo,
wollte mal fragen ob es möglich ist, Sendepuffer des USART zu laden,
ohne jedoch das Zeichen zu versenden?
Gruß pacer
@ 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)
25.01.2008 20:13
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
@ 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
sondern
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)
25.01.2008 23:10
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
@ 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)
26.01.2008 10:18
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)
26.01.2008 10:22
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.