1 | /**************************************************************
|
2 | * *
|
3 | * UART.c *
|
4 | * *
|
5 | ***************************************************************/
|
6 |
|
7 | /* Include-Dateien
|
8 | -----------------*/
|
9 |
|
10 |
|
11 | #include <avr/io.h>
|
12 | #include <avr/interrupt.h>
|
13 |
|
14 | /* UCR - UART Control Register: Bit Definitionen
|
15 | -----------------------------------------------------------*/
|
16 | #define RXCIE 0x80 // Bit 7
|
17 | #define TXCIE 0x40 // Bit 6
|
18 | #define UDRIE 0x20 // Bit 5
|
19 | #define RXEN 0x10 // Bit 4
|
20 | #define TXEN 0x08 // Bit 3
|
21 | #define CHR9 0x04 // Bit 2
|
22 | #define RXB8 0x02 // Bit 1
|
23 | #define TXB8 0x01 // Bit 0
|
24 |
|
25 | /* USR - UART Status Register: Bit Definitionen
|
26 | ---------------------------------------------------------*/
|
27 | #define RXC 0x80 // Bit 7
|
28 | #define TXC 0x40 // Bit 6
|
29 | #define UDRE 0x20 // Bit 5
|
30 | #define FE 0x10 // Bit 4
|
31 | #define OVR 0x08 // Bit 3
|
32 |
|
33 | /* UBRR - UART Baudrate Register: Baud Definitionen fuer 4MHz
|
34 | ---------------------------------------------------------*/
|
35 | #define BAUD_1200 208
|
36 | #define BAUD_2400 103
|
37 | #define BAUD_9600 25
|
38 | #define BAUD_19200 12
|
39 |
|
40 | /* UART Daten-Puffer Definitionen
|
41 | ------------------------------*/
|
42 | #define BUFFER_SIZE 8 // Modulo 2 Groesse: nur 2,4,8,16,32 Bytes
|
43 | #define BUFFER_MASK (BUFFER_SIZE-1)
|
44 |
|
45 | /* Allgemeine typ-Definitionen
|
46 | -----------------------------------------------------------*/
|
47 | typedef enum{ FALSE=0, TRUE=1} Boolean_t ;
|
48 |
|
49 | typedef struct{ unsigned char UartData[ BUFFER_SIZE ];
|
50 | unsigned char NumberOfBytes;
|
51 | unsigned char UartStatus; } Uart_t;
|
52 |
|
53 | /* Static Variables
|
54 | -------------------*/
|
55 | static unsigned char RxBuf[ BUFFER_SIZE ];
|
56 | static volatile unsigned char RxProducer; // Empfang: Int-Service ist der Producer
|
57 | static volatile unsigned char RxConsumer; // Empfang: Hauptprogramm ist Consumer
|
58 | static unsigned char TxBuf[ BUFFER_SIZE ];
|
59 | static volatile unsigned char TxProducer; // Senden: Hauptprogramm ist der Producer
|
60 | static volatile unsigned char TxConsumer; // Senden: Int-Service ist Consumer
|
61 |
|
62 | /* Funktion-Prototypen
|
63 | ----------------------------*/
|
64 | void InitUart( unsigned char baudrate );
|
65 | Boolean_t ReceiveData( Uart_t * Data );
|
66 | Boolean_t TransmitData( Uart_t * Data );
|
67 | void Delay( void );
|
68 |
|
69 | /* Input Pins, Port B: sfrb PINB = 0x16;
|
70 | Data Direction Register, Port B: sfrb DDRB = 0x17;
|
71 | Data Register, Port B: sfrb PORTB = 0x18; */
|
72 | void Delay( void ) // warte zeit
|
73 | {
|
74 | unsigned int i= 0x7FFF;
|
75 | while(--i);
|
76 | }
|
77 |
|
78 |
|
79 | /* Main - ein einfaches Anwendungsbeispiel fuer UART und Timer
|
80 | -------------------------------------------------------------*/
|
81 | void C_task main( void )
|
82 | {
|
83 | Uart_t UartData;
|
84 |
|
85 | DDRB = 0xFF ; // Konfiguriert Port B als Ausgang
|
86 | PORTB = 0xAA;
|
87 |
|
88 | InitUart( BAUD_9600 ); // Baudrate = 9600 Baud bei 4MHz Quarz
|
89 | _SEI(); // Freigabe aller Interrupts => Enable UART Interrupts
|
90 |
|
91 | for( ;; ) // Endlos-Schleife
|
92 | {
|
93 | if( ReceiveData( & UartData ) )
|
94 | {
|
95 | TransmitData( & UartData ); // Echo der empfangenen Bytes
|
96 | }
|
97 |
|
98 | PORTB++; // Nur zum Testen Led schalten
|
99 | Delay(); // damit das Programm nicht nur die UART Daten abfragt
|
100 | }
|
101 | }
|
102 |
|
103 | /* Initialisierung der UART
|
104 | ------------------------------*/
|
105 | void InitUart( unsigned char baudrate )
|
106 | {
|
107 | UBRR = baudrate; // Baudrate setzen
|
108 |
|
109 | // Freigabe der UART Interrupts
|
110 | UCR = TXEN | RXEN | RXCIE; // ==> Senden/Empfangen/Empf.INT
|
111 |
|
112 | RxConsumer = 0; // Ruecksetzen der Puffer-Index
|
113 | RxProducer = 0;
|
114 | TxConsumer = 0;
|
115 | TxProducer = 0;
|
116 | }
|
117 |
|
118 | /* Empfangs-Interrupt Handler
|
119 | --------------------------- */
|
120 | interrupt [UART_RX_vect] void UartRxIntHandler( void )
|
121 | {
|
122 | unsigned char data;
|
123 |
|
124 | data = UDR; // Lesen der Empfangsdaten
|
125 | RxBuf[RxProducer] = data; // Empfangenes Byte in Puffer ablegen
|
126 | RxProducer++; // Bufferindex setzen
|
127 | RxProducer &=BUFFER_MASK; // Index begrenzen und evtl. auf Puffer-Anfang
|
128 |
|
129 | if (RxProducer == RxConsumer )
|
130 | {
|
131 | // Fehler! Ueberlauf Empfangspuffer
|
132 | }
|
133 | if( data =='\r') Wenn return Taste gedruckt
|
134 | {
|
135 | RxProducer == RxConsumer ; // Überlauf simulieren
|
136 | // UCR=~RXCIE; //oder der interrupt disable
|
137 | }
|
138 |
|
139 | }
|
140 |
|
141 | /* Sende-Interrupt Handler
|
142 | --------------------------- */
|
143 | interrupt [UART_UDRE_vect] void UART_TX_interrupt( void )
|
144 | {
|
145 | // Test ob noch nicht fertig mit Senden
|
146 | if ( TxConsumer != TxProducer ) // Nein, weiter machen mit senden
|
147 | {
|
148 | ++TxConsumer; // Pufferindex aktualisieren
|
149 | TxConsumer &=BUFFER_MASK; // Index begrenzen und evtl. auf Puffer-Anfang
|
150 | UDR = TxBuf[TxConsumer]; // Uebergabe eines Bytes
|
151 | }
|
152 | else // fertig ,senden beenden
|
153 | {
|
154 | UCR &= ~UDRIE; // Disable UDRE interrupt
|
155 | }
|
156 | }
|
157 |
|
158 |
|
159 | /* UART Empfangsfunktion
|
160 | --------------------- */
|
161 | Boolean_t ReceiveData( Uart_t * Data )
|
162 | {
|
163 | unsigned char i=0;
|
164 |
|
165 | // Schleife zur Uebergabe der empfangenen Daten
|
166 | while (( RxConsumer != RxProducer ) && ( i < BUFFER_SIZE ) )
|
167 | {
|
168 | Data->UartData[i++] = RxBuf[RxConsumer++];
|
169 |
|
170 | RxConsumer &=BUFFER_MASK; // Consumer-Index begrenzen und evtl. auf Puffer-Anfang
|
171 | }
|
172 |
|
173 | Data->NumberOfBytes = i ;
|
174 |
|
175 | if( i ) return TRUE ;
|
176 | else return FALSE ;
|
177 | }
|
178 |
|
179 | /* Sendefunktion
|
180 | --------------------- */
|
181 | Boolean_t TransmitData( Uart_t * Data )
|
182 | {
|
183 | unsigned char i=0;
|
184 |
|
185 | while (( i < Data->NumberOfBytes ) && ( i < BUFFER_SIZE ) )// Uebergabe Sendendaten
|
186 | {
|
187 | TxBuf[TxProducer++] = Data->UartData[i++] ;
|
188 |
|
189 | TxProducer &=BUFFER_MASK; // Producer-Index begrenzen und evtl. auf Puffer-Anfang
|
190 | }
|
191 |
|
192 | UDR = TxBuf[TxConsumer]; // Senden Anstossen
|
193 | ++TxConsumer;
|
194 | TxConsumer &=BUFFER_MASK; // Consumer-Index begrenzen
|
195 |
|
196 | UCR |= UDRIE ;
|
197 | Data->NumberOfBytes = 0;
|
198 | return TRUE ;
|
199 | }
|