1 | #include <stdlib.h>
|
2 | #include <avr/io.h>
|
3 | #include <util/delay.h>
|
4 | #include <avr/interrupt.h>
|
5 | #include <inttypes.h>
|
6 | #include <string.h>
|
7 |
|
8 | #define LENGTH 15
|
9 |
|
10 | #ifndef F_CPU
|
11 | #warning "F_CPU was not defined yet, now make up with 4000000"
|
12 | #define F_CPU 4000000L // Systemtakt in Hz
|
13 | #endif
|
14 |
|
15 |
|
16 | #define BAUD 9600L
|
17 | #define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1) //clever round
|
18 | #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) //real baud rate
|
19 | #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) //Error per thousand
|
20 |
|
21 |
|
22 | #if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
|
23 | #error Systematic error in the baud rate more than 1% and thus too high!
|
24 | #endif
|
25 |
|
26 |
|
27 | // constants and macros
|
28 | /* size of RX/TX buffers */
|
29 | #define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)
|
30 | #define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)
|
31 |
|
32 | #if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
|
33 | #error RX buffer size is not a power of 2
|
34 | #endif
|
35 | #if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
|
36 | #error TX buffer size is not a power of 2
|
37 | #endif
|
38 |
|
39 | /** Size of the circular receive buffer, must be power of 2 */
|
40 | #ifndef UART_RX_BUFFER_SIZE
|
41 | #define UART_RX_BUFFER_SIZE 32
|
42 | #endif
|
43 | /** Size of the circular transmit buffer, must be power of 2 */
|
44 | #ifndef UART_TX_BUFFER_SIZE
|
45 | #define UART_TX_BUFFER_SIZE 32
|
46 | #endif
|
47 |
|
48 | /* test if the size of the circular buffers fits into SRAM */
|
49 | #if ( (UART_RX_BUFFER_SIZE+UART_TX_BUFFER_SIZE) >= (RAMEND-0x60 ) )
|
50 | #error "size of UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE larger than size of SRAM"
|
51 | #endif
|
52 |
|
53 | /*
|
54 | ** high byte error return code of uart_getc()
|
55 | */
|
56 | #define UART_FRAME_ERROR 0x0800 // Framing Error by UART
|
57 | #define UART_OVERRUN_ERROR 0x0400 // Overrun condition by UART
|
58 | #define UART_BUFFER_OVERFLOW 0x0200 // receive ringbuffer overflow
|
59 | #define UART_NO_DATA 0x0100 // no receive data available
|
60 |
|
61 |
|
62 |
|
63 | // ATmega with two USART
|
64 | #define ATMEGA_USART0
|
65 | #define ATMEGA_USART1
|
66 | #define UART0_RECEIVE_INTERRUPT SIG_UART0_RECV
|
67 | #define UART1_RECEIVE_INTERRUPT SIG_UART1_RECV
|
68 | #define UART0_TRANSMIT_INTERRUPT SIG_UART0_DATA
|
69 | #define UART1_TRANSMIT_INTERRUPT SIG_UART1_DATA
|
70 |
|
71 | #define UART0_STATUS UCSR0A
|
72 | #define UART0_CONTROL UCSR0B
|
73 | #define UART0_DATA UDR0
|
74 | #define UART0_UDRIE UDRIE0
|
75 |
|
76 | #define UART1_STATUS UCSR1A
|
77 | #define UART1_CONTROL UCSR1B
|
78 | #define UART1_DATA UDR1
|
79 | #define UART1_UDRIE UDRIE1
|
80 |
|
81 |
|
82 | //module global variables
|
83 |
|
84 | //ATMEGA_USART0
|
85 | static volatile unsigned char UART0_TxBuf[UART_TX_BUFFER_SIZE];
|
86 | static volatile unsigned char UART0_RxBuf[UART_RX_BUFFER_SIZE];
|
87 | static volatile unsigned char UART0_TxHead;
|
88 | static volatile unsigned char UART0_TxTail;
|
89 | static volatile unsigned char UART0_RxHead;
|
90 | static volatile unsigned char UART0_RxTail;
|
91 | static volatile unsigned char UART0_LastRxError;
|
92 |
|
93 | //ATMEGA_USART1
|
94 | static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE];
|
95 | static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE];
|
96 | static volatile unsigned char UART1_TxHead;
|
97 | static volatile unsigned char UART1_TxTail;
|
98 | static volatile unsigned char UART1_RxHead;
|
99 | static volatile unsigned char UART1_RxTail;
|
100 | static volatile unsigned char UART1_LastRxError;
|
101 |
|
102 |
|
103 |
|
104 | SIGNAL(UART0_RECEIVE_INTERRUPT)
|
105 | /*************************************************************************
|
106 | Function: UART Receive Complete interrupt
|
107 | Purpose: called when the UART has received a character
|
108 | **************************************************************************/
|
109 | {
|
110 | unsigned char tmphead;
|
111 | unsigned char data;
|
112 | unsigned char usr;
|
113 | unsigned char lastRxError;
|
114 |
|
115 |
|
116 | // read UART status register and UART data register
|
117 | usr = UART0_STATUS;
|
118 | data = UART0_DATA;
|
119 |
|
120 | // defined( ATMEGA_USART0 )
|
121 | lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) );
|
122 |
|
123 | // calculate buffer index
|
124 | tmphead = ( UART0_RxHead + 1) & UART_RX_BUFFER_MASK;
|
125 |
|
126 | if ( tmphead == UART0_RxTail )
|
127 | // error: receive buffer overflow
|
128 | lastRxError = UART_BUFFER_OVERFLOW >> 8;
|
129 |
|
130 | else
|
131 | {
|
132 | // store new index
|
133 | UART0_RxHead = tmphead;
|
134 | // store received data in buffer
|
135 | UART0_RxBuf[tmphead] = data;
|
136 | }
|
137 |
|
138 | UART0_LastRxError = lastRxError;
|
139 | }
|
140 |
|
141 |
|
142 | SIGNAL(UART0_TRANSMIT_INTERRUPT)
|
143 | /*************************************************************************
|
144 | Function: UART Data Register Empty interrupt
|
145 | Purpose: called when the UART is ready to transmit the next byte
|
146 | **************************************************************************/
|
147 | {
|
148 | unsigned char tmptail;
|
149 |
|
150 |
|
151 | if ( UART0_TxHead != UART0_TxTail)
|
152 | {
|
153 | // calculate and store new buffer index
|
154 | tmptail = (UART0_TxTail + 1) & UART_TX_BUFFER_MASK;
|
155 | UART0_TxTail = tmptail;
|
156 | // get one byte from buffer and write it to UART
|
157 | UART0_DATA = UART0_TxBuf[tmptail]; // start transmission
|
158 | }
|
159 | else
|
160 | // tx buffer empty, disable UDRE interrupt
|
161 | UART0_CONTROL &= ~_BV(UART0_UDRIE);
|
162 | }
|
163 |
|
164 |
|
165 | /*************************************************************************
|
166 | Function: uart0_init()
|
167 | Purpose: initialize UART and set baudrate
|
168 | Input: baudrate using macro UART_BAUD_SELECT()
|
169 | Returns: none
|
170 | **************************************************************************/
|
171 | void uart0_init(void)
|
172 | {
|
173 | UART0_TxHead = 0;
|
174 | UART0_TxTail = 0;
|
175 | UART0_RxHead = 0;
|
176 | UART0_RxTail = 0;
|
177 |
|
178 |
|
179 |
|
180 | //defined (ATMEGA_USART0 )
|
181 |
|
182 | UBRR0H = (unsigned char)(UBRR_VAL>>8);
|
183 | UBRR0L = (unsigned char) UBRR_VAL;
|
184 |
|
185 | // Enable USART receiver and transmitter and receive complete interrupt
|
186 | UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
|
187 |
|
188 | // Set frame format: asynchronous, 8data, no parity, 1stop bit
|
189 | #ifdef URSEL0
|
190 | UCSR0C = (1<<URSEL0)| (1<<UCSZ01)|(1<<UCSZ00);
|
191 | #else
|
192 | UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
|
193 | #endif
|
194 |
|
195 | }// uart_init
|
196 |
|
197 |
|
198 | /*************************************************************************
|
199 | Function: uart0_getc()
|
200 | Purpose: return byte from ringbuffer
|
201 | Returns: lower byte: received byte from ringbuffer
|
202 | higher byte: last receive error
|
203 | **************************************************************************/
|
204 | unsigned char uart0_getc(void)
|
205 | {
|
206 | unsigned char tmptail;
|
207 | unsigned char data;
|
208 |
|
209 |
|
210 | if ( UART0_RxHead == UART0_RxTail ) {
|
211 | return (unsigned char) UART_NO_DATA; // no data available
|
212 | }
|
213 |
|
214 | // calculate /store buffer index
|
215 | tmptail = (UART0_RxTail + 1) & UART_RX_BUFFER_MASK;
|
216 | UART0_RxTail = tmptail;
|
217 |
|
218 | // get data from receive buffer
|
219 | data = UART0_RxBuf[tmptail];
|
220 |
|
221 | return (UART0_LastRxError << 8) + data;
|
222 |
|
223 | }// uart_getc
|
224 |
|
225 | /*************************************************************************
|
226 | Function: uart0_gets()
|
227 | Purpose: function which receive a String Through usart
|
228 | Returns: lower byte: received byte from ringbuffer
|
229 | higher byte: last receive error
|
230 | **************************************************************************/
|
231 | void uart0_gets (char* string, unsigned int Length)
|
232 | {
|
233 | uint8_t i;
|
234 | char c;
|
235 | char* s;
|
236 |
|
237 | s=string;
|
238 | i=0;
|
239 | do
|
240 | {
|
241 | c=uart0_getc();
|
242 | if (c!='\r')
|
243 | {
|
244 | *s=c;
|
245 | s++;
|
246 | i++;
|
247 | }
|
248 | }
|
249 | while( i!=Length && c!='\r');
|
250 | *s = '\0';
|
251 |
|
252 | }//end UART_Gets
|
253 |
|
254 |
|
255 | /*************************************************************************
|
256 | Function: uart_putc()
|
257 | Purpose: write byte to ringbuffer for transmitting via UART
|
258 | Input: byte to be transmitted
|
259 | Returns: none
|
260 | **************************************************************************/
|
261 | void uart0_putc(unsigned char data)
|
262 | {
|
263 | unsigned char tmphead;
|
264 |
|
265 | // calculate /store buffer index
|
266 | tmphead = (UART0_TxHead + 1) & UART_TX_BUFFER_MASK;
|
267 |
|
268 | while ( tmphead == UART0_TxTail ){
|
269 | ;// wait for free space in buffer
|
270 | }
|
271 |
|
272 | UART0_TxBuf[tmphead] = data;
|
273 | UART0_TxHead = tmphead;
|
274 |
|
275 | // enable UDRE interrupt
|
276 | UART0_CONTROL |= _BV(UART0_UDRIE);
|
277 |
|
278 | }// uart_putc
|
279 |
|
280 | /*void USART_Putc(unsigned char c)
|
281 | {
|
282 | while (!(UCSRA & (1<<UDRE))); // Do nothing until data have been transmited
|
283 |
|
284 | UDR = c; // Put data into Buffer, sends the data
|
285 | _delay_ms(10);
|
286 | }//end USART_Putc()*/
|
287 | /*************************************************************************
|
288 | Function: uart_puts()
|
289 | Purpose: transmit string to UART
|
290 | Input: string to be transmitted
|
291 | Returns: none
|
292 | **************************************************************************/
|
293 | void uart0_puts(char *s )
|
294 | {
|
295 | while (*s != '\0' )
|
296 | uart0_putc(*s++);
|
297 |
|
298 | }// uart_puts
|
299 |
|
300 |
|
301 | /*************************************************************************
|
302 | Function: uart_puts_p()
|
303 | Purpose: transmit string from program memory to UART
|
304 | Input: program memory string to be transmitted
|
305 | Returns: none
|
306 | **************************************************************************/
|
307 | void uart0_puts_p(const char *progmem_s )
|
308 | {
|
309 | register char c;
|
310 |
|
311 | while ( (c = pgm_read_byte(progmem_s++)) )
|
312 | uart0_putc(c);
|
313 |
|
314 | }//uart_puts_p
|
315 |
|
316 |
|
317 | /*
|
318 | * these functions are only for ATMEGA_USART1
|
319 | */
|
320 |
|
321 | SIGNAL(UART1_RECEIVE_INTERRUPT)
|
322 | /*************************************************************************
|
323 | Function: UART1 Receive Complete interrupt
|
324 | Purpose: called when the UART1 has received a character
|
325 | **************************************************************************/
|
326 | {
|
327 | unsigned char tmphead;
|
328 | unsigned char data;
|
329 | unsigned char usr;
|
330 | unsigned char lastRxError;
|
331 |
|
332 |
|
333 | /* read UART status register and UART data register */
|
334 | usr = UART1_STATUS;
|
335 | data = UART1_DATA;
|
336 |
|
337 | /* */
|
338 | lastRxError = (usr & (_BV(FE1)|_BV(DOR1)) );
|
339 |
|
340 | /* calculate buffer index */
|
341 | tmphead = ( UART1_RxHead + 1) & UART_RX_BUFFER_MASK;
|
342 |
|
343 | if ( tmphead == UART1_RxTail )
|
344 | /* error: receive buffer overflow */
|
345 | lastRxError = UART_BUFFER_OVERFLOW >> 8;
|
346 |
|
347 | else
|
348 | {
|
349 | /* store new index */
|
350 | UART1_RxHead = tmphead;
|
351 | /* store received data in buffer */
|
352 | UART1_RxBuf[tmphead] = data;
|
353 | }
|
354 |
|
355 | UART1_LastRxError = lastRxError;
|
356 | }
|
357 |
|
358 |
|
359 | SIGNAL(UART1_TRANSMIT_INTERRUPT)
|
360 | /*************************************************************************
|
361 | Function: UART1 Data Register Empty interrupt
|
362 | Purpose: called when the UART1 is ready to transmit the next byte
|
363 | **************************************************************************/
|
364 | {
|
365 | unsigned char tmptail;
|
366 |
|
367 |
|
368 | if ( UART1_TxHead != UART1_TxTail)
|
369 | {
|
370 | /* calculate and store new buffer index */
|
371 | tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK;
|
372 | UART1_TxTail = tmptail;
|
373 | /* get one byte from buffer and write it to UART */
|
374 | UART1_DATA = UART1_TxBuf[tmptail]; /* start transmission */
|
375 | }
|
376 | else
|
377 | /* tx buffer empty, disable UDRE interrupt */
|
378 | UART1_CONTROL &= ~_BV(UART1_UDRIE);
|
379 | }
|
380 |
|
381 |
|
382 | /*************************************************************************
|
383 | Function: uart1_init()
|
384 | Purpose: initialize UART1 and set baudrate
|
385 | Input: baudrate using macro UART_BAUD_SELECT()
|
386 | Returns: none
|
387 | **************************************************************************/
|
388 | void uart1_init()
|
389 | {
|
390 | UART1_TxHead = 0;
|
391 | UART1_TxTail = 0;
|
392 | UART1_RxHead = 0;
|
393 | UART1_RxTail = 0;
|
394 |
|
395 |
|
396 | UBRR1H = (unsigned char)(UBRR_VAL>>8);
|
397 | UBRR1L = (unsigned char) UBRR_VAL;
|
398 |
|
399 | // Enable USART receiver and transmitter and receive complete interrupt
|
400 | UART1_CONTROL = _BV(RXCIE1)|(1<<RXEN1)|(1<<TXEN1);
|
401 |
|
402 | // Set frame format: asynchronous, 8data, no parity, 1stop bit
|
403 | #ifdef URSEL1
|
404 | UCSR1C = (1<<URSEL1)|(3<<UCSZ10);
|
405 | #else
|
406 | UCSR1C = (3<<UCSZ10);
|
407 | #endif
|
408 |
|
409 | }// uart_init
|
410 |
|
411 |
|
412 | /*************************************************************************
|
413 | Function: uart1_getc()
|
414 | Purpose: return byte from ringbuffer
|
415 | Returns: lower byte: received byte from ringbuffer
|
416 | higher byte: last receive error
|
417 | **************************************************************************/
|
418 | unsigned char uart1_getc(void)
|
419 | {
|
420 | unsigned char tmptail;
|
421 | unsigned char data;
|
422 |
|
423 |
|
424 | if ( UART1_RxHead == UART1_RxTail ) {
|
425 | return (unsigned char) UART_NO_DATA; // no data available
|
426 | }
|
427 |
|
428 | // calculate /store buffer index
|
429 | tmptail = (UART1_RxTail + 1) & UART_RX_BUFFER_MASK;
|
430 | UART1_RxTail = tmptail;
|
431 |
|
432 | // get data from receive buffer
|
433 | data = UART1_RxBuf[tmptail];
|
434 |
|
435 | return (UART1_LastRxError << 8) + data;
|
436 |
|
437 | }// uart1_getc
|
438 |
|
439 | /*************************************************************************
|
440 | Function: uart1_gets()
|
441 | Purpose: function which receive a String Through usart
|
442 | Returns: lower byte: received byte from ringbuffer
|
443 | higher byte: last receive error
|
444 | **************************************************************************/
|
445 | void uart1_gets (char* string, unsigned int Length)
|
446 | {
|
447 | uint8_t i;
|
448 | char c;
|
449 | char* s;
|
450 |
|
451 | s=string;
|
452 | i=0;
|
453 | do
|
454 | {
|
455 | c=uart1_getc();
|
456 | if (c!='\r')
|
457 | {
|
458 | *s=c;
|
459 | s++;
|
460 | i++;
|
461 | }
|
462 | }
|
463 | while( i!=Length && c!='\r');
|
464 | *s = '\0';
|
465 |
|
466 | }//end uart1_gets
|
467 |
|
468 | /*************************************************************************
|
469 | Function: uart1_putc()
|
470 | Purpose: write byte to ringbuffer for transmitting via UART
|
471 | Input: byte to be transmitted
|
472 | Returns: none
|
473 | **************************************************************************/
|
474 | void uart1_putc(unsigned char data)
|
475 | {
|
476 | unsigned char tmphead;
|
477 |
|
478 |
|
479 | tmphead = (UART1_TxHead + 1) & UART_TX_BUFFER_MASK;
|
480 |
|
481 | while ( tmphead == UART1_TxTail ){
|
482 | ;// wait for free space in buffer
|
483 | }
|
484 |
|
485 | UART1_TxBuf[tmphead] = data;
|
486 | UART1_TxHead = tmphead;
|
487 |
|
488 | // enable UDRE interrupt
|
489 | UART1_CONTROL |= _BV(UART1_UDRIE);
|
490 |
|
491 | }// uart1_putc
|
492 |
|
493 |
|
494 | /*************************************************************************
|
495 | Function: uart1_puts()
|
496 | Purpose: transmit string to UART1
|
497 | Input: string to be transmitted
|
498 | Returns: none
|
499 | **************************************************************************/
|
500 | void uart1_puts(const char *s )
|
501 | {
|
502 | while (*s)
|
503 | uart1_putc(*s++);
|
504 |
|
505 | }// uart1_puts
|
506 |
|
507 |
|
508 |
|
509 | int main(void)
|
510 | {
|
511 |
|
512 | DDRD = 0xFF; // PORTD auf Eingang
|
513 | PORTD = 0xFF; //Internal pull ups resistance for key inputs PortD2 and portD3 was activated
|
514 |
|
515 | DDRC = 0xFF; // outputs for LEDs
|
516 | PORTC = 0x00; // LEDs off
|
517 |
|
518 | // Initialize UART library, pass baudrate and AVR cpu clock with the macro
|
519 | uart0_init();
|
520 | uart1_init();
|
521 |
|
522 | // now enable interrupt, since UART library is interrupt controlled
|
523 | sei();
|
524 |
|
525 | char Command [LENGTH+1];
|
526 |
|
527 | for(;;)
|
528 | {
|
529 | PORTC = 0xAA;
|
530 |
|
531 | uart0_gets( Command, LENGTH );
|
532 | uart0_puts( Command );
|
533 | uart0_puts( "\r\n" );
|
534 |
|
535 |
|
536 | if(strcmp(Command, "start") == 0)
|
537 | {
|
538 | PORTC = 0xFA;
|
539 | for(int i=0; i<19; i++)
|
540 | uart1_puts("start");
|
541 | _delay_ms(10);
|
542 | }
|
543 | else if(strcmp(Command, "exit") == 0)
|
544 | {
|
545 | PORTC = 0xBA;
|
546 | for(int i=0; i<19; i++)
|
547 | uart1_puts("exit");
|
548 | _delay_ms(10);
|
549 | }
|
550 | }
|
551 | return 0;
|
552 | }
|