1 /*************************************************************************
2 Title: Interrupt UART library with receive/transmit circular buffers
3 Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
4 File: $Id: uart.c,v 1.6.2.2 2009/11/29 08:56:12 Peter Exp $
5 Software: AVR-GCC 4.1, AVR Libc 1.4.6 or higher
6 Hardware: any AVR with built-in UART,
7 License: GNU General Public License
10 An interrupt is generated when the UART has finished transmitting or
11 receiving a byte. The interrupt handling routines use circular buffers
12 for buffering received and transmitted data.
14 The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define
15 the buffer size in bytes. Note that these variables must be a
19 Refere to the header file uart.h for a description of the routines.
20 See also example test_uart.c.
23 Based on Atmel Application Note AVR306
26 Copyright (C) 2006 Peter Fleury
28 This program is free software; you can redistribute it and/or modify
29 it under the terms of the GNU General Public License as published by
30 the Free Software Foundation; either version 2 of the License, or
33 This program is distributed in the hope that it will be useful,
34 but WITHOUT ANY WARRANTY; without even the implied warranty of
35 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 GNU General Public License for more details.
38 *************************************************************************/
40 #include <avr/interrupt.h>
41 #include <avr/pgmspace.h>
46 * constants and macros
49 /* size of RX/TX buffers */
50 #define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)
51 #define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)
53 #if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
54 #error RX buffer size is not a power of 2
56 #if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
57 #error TX buffer size is not a power of 2
60 #if defined(__AVR_AT90S2313__) \
61 || defined(__AVR_AT90S4414__) || defined(__AVR_AT90S4434__) \
62 || defined(__AVR_AT90S8515__) || defined(__AVR_AT90S8535__) \
63 || defined(__AVR_ATmega103__)
64 /* old AVR classic or ATmega103 with one UART */
66 #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV
67 #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA
68 #define UART0_STATUS USR
69 #define UART0_CONTROL UCR
70 #define UART0_DATA UDR
71 #define UART0_UDRIE UDRIE
72 #elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__)
73 /* old AVR classic with one UART */
75 #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV
76 #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA
77 #define UART0_STATUS UCSRA
78 #define UART0_CONTROL UCSRB
79 #define UART0_DATA UDR
80 #define UART0_UDRIE UDRIE
81 #elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
82 || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) \
83 || defined(__AVR_ATmega323__)
84 /* ATmega with one USART */
86 #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV
87 #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA
88 #define UART0_STATUS UCSRA
89 #define UART0_CONTROL UCSRB
90 #define UART0_DATA UDR
91 #define UART0_UDRIE UDRIE
92 #elif defined(__AVR_ATmega163__)
93 /* ATmega163 with one UART */
95 #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV
96 #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA
97 #define UART0_STATUS UCSRA
98 #define UART0_CONTROL UCSRB
99 #define UART0_DATA UDR
100 #define UART0_UDRIE UDRIE
101 #elif defined(__AVR_ATmega162__)
102 /* ATmega with two USART */
103 #define ATMEGA_USART0
104 #define ATMEGA_USART1
105 #define UART0_RECEIVE_INTERRUPT SIG_USART0_RECV
106 #define UART1_RECEIVE_INTERRUPT SIG_USART1_RECV
107 #define UART0_TRANSMIT_INTERRUPT SIG_USART0_DATA
108 #define UART1_TRANSMIT_INTERRUPT SIG_USART1_DATA
109 #define UART0_STATUS UCSR0A
110 #define UART0_CONTROL UCSR0B
111 #define UART0_DATA UDR0
112 #define UART0_UDRIE UDRIE0
113 #define UART1_STATUS UCSR1A
114 #define UART1_CONTROL UCSR1B
115 #define UART1_DATA UDR1
116 #define UART1_UDRIE UDRIE1
117 #elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
118 /* ATmega with two USART */
119 #define ATMEGA_USART0
120 #define ATMEGA_USART1
121 #define UART0_RECEIVE_INTERRUPT SIG_UART0_RECV
122 #define UART1_RECEIVE_INTERRUPT SIG_UART1_RECV
123 #define UART0_TRANSMIT_INTERRUPT SIG_UART0_DATA
124 #define UART1_TRANSMIT_INTERRUPT SIG_UART1_DATA
125 #define UART0_STATUS UCSR0A
126 #define UART0_CONTROL UCSR0B
127 #define UART0_DATA UDR0
128 #define UART0_UDRIE UDRIE0
129 #define UART1_STATUS UCSR1A
130 #define UART1_CONTROL UCSR1B
131 #define UART1_DATA UDR1
132 #define UART1_UDRIE UDRIE1
133 #elif defined(__AVR_ATmega161__)
134 /* ATmega with UART */
135 #error "AVR ATmega161 currently not supported by this libaray !"
136 #elif defined(__AVR_ATmega169__)
137 /* ATmega with one USART */
139 #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV
140 #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA
141 #define UART0_STATUS UCSRA
142 #define UART0_CONTROL UCSRB
143 #define UART0_DATA UDR
144 #define UART0_UDRIE UDRIE
145 #elif defined(__AVR_ATmega48__) ||defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
146 /* ATmega with one USART */
147 #define ATMEGA_USART0
148 #define UART0_RECEIVE_INTERRUPT USART_RX_vect
149 #define UART0_TRANSMIT_INTERRUPT USART_TX_vect
150 #define UART0_STATUS UCSR0A
151 #define UART0_CONTROL UCSR0B
152 #define UART0_DATA UDR0
153 #define UART0_UDRIE UDRIE0
154 #elif defined(__AVR_ATtiny2313__)
156 #define UART0_RECEIVE_INTERRUPT SIG_USART0_RX
157 #define UART0_TRANSMIT_INTERRUPT SIG_USART0_UDRE
158 #define UART0_STATUS UCSRA
159 #define UART0_CONTROL UCSRB
160 #define UART0_DATA UDR
161 #define UART0_UDRIE UDRIE
162 #elif defined(__AVR_ATmega329__) ||defined(__AVR_ATmega3290__) ||\
163 defined(__AVR_ATmega649__) ||defined(__AVR_ATmega6490__) ||\
164 defined(__AVR_ATmega325__) ||defined(__AVR_ATmega3250__) ||\
165 defined(__AVR_ATmega645__) ||defined(__AVR_ATmega6450__)
166 /* ATmega with one USART */
167 #define ATMEGA_USART0
168 #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV
169 #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA
170 #define UART0_STATUS UCSR0A
171 #define UART0_CONTROL UCSR0B
172 #define UART0_DATA UDR0
173 #define UART0_UDRIE UDRIE0
174 #elif defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega640__)
175 /* ATmega with two USART */
176 #define ATMEGA_USART0
177 #define ATMEGA_USART1
178 #define UART0_RECEIVE_INTERRUPT SIG_USART0_RECV
179 #define UART1_RECEIVE_INTERRUPT SIG_USART1_RECV
180 #define UART0_TRANSMIT_INTERRUPT SIG_USART0_DATA
181 #define UART1_TRANSMIT_INTERRUPT SIG_USART1_DATA
182 #define UART0_STATUS UCSR0A
183 #define UART0_CONTROL UCSR0B
184 #define UART0_DATA UDR0
185 #define UART0_UDRIE UDRIE0
186 #define UART1_STATUS UCSR1A
187 #define UART1_CONTROL UCSR1B
188 #define UART1_DATA UDR1
189 #define UART1_UDRIE UDRIE1
190 #elif defined(__AVR_ATmega644__)
191 /* ATmega with one USART */
192 #define ATMEGA_USART0
193 #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV
194 #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA
195 #define UART0_STATUS UCSR0A
196 #define UART0_CONTROL UCSR0B
197 #define UART0_DATA UDR0
198 #define UART0_UDRIE UDRIE0
199 #elif defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644P__)
200 /* ATmega with two USART */
201 #define ATMEGA_USART0
202 #define ATMEGA_USART1
203 #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV
204 #define UART1_RECEIVE_INTERRUPT SIG_USART1_RECV
205 #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA
206 #define UART1_TRANSMIT_INTERRUPT SIG_USART1_DATA
207 #define UART0_STATUS UCSR0A
208 #define UART0_CONTROL UCSR0B
209 #define UART0_DATA UDR0
210 #define UART0_UDRIE UDRIE0
211 #define UART1_STATUS UCSR1A
212 #define UART1_CONTROL UCSR1B
213 #define UART1_DATA UDR1
214 #define UART1_UDRIE UDRIE1
216 #error "no UART definition for MCU available"
221 * module global variables
223 static volatile unsigned char UART_TxBuf
[UART_TX_BUFFER_SIZE
];
224 static volatile unsigned char UART_RxBuf
[UART_RX_BUFFER_SIZE
];
225 static volatile unsigned char UART_TxHead
;
226 static volatile unsigned char UART_TxTail
;
227 static volatile unsigned char UART_RxHead
;
228 static volatile unsigned char UART_RxTail
;
229 static volatile unsigned char UART_LastRxError
;
231 #if defined( ATMEGA_USART1 )
232 static volatile unsigned char UART1_TxBuf
[UART_TX_BUFFER_SIZE
];
233 static volatile unsigned char UART1_RxBuf
[UART_RX_BUFFER_SIZE
];
234 static volatile unsigned char UART1_TxHead
;
235 static volatile unsigned char UART1_TxTail
;
236 static volatile unsigned char UART1_RxHead
;
237 static volatile unsigned char UART1_RxTail
;
238 static volatile unsigned char UART1_LastRxError
;
243 ISR(UART0_RECEIVE_INTERRUPT
)
244 /*************************************************************************
245 Function: UART Receive Complete interrupt
246 Purpose: called when the UART has received a character
247 **************************************************************************/
249 unsigned char tmphead
;
252 unsigned char lastRxError
;
255 /* read UART status register and UART data register */
260 #if defined( AT90_UART )
261 lastRxError
= (usr
& (_BV(FE
)|_BV(DOR
)) );
262 #elif defined( ATMEGA_USART )
263 lastRxError
= (usr
& (_BV(FE
)|_BV(DOR
)) );
264 #elif defined( ATMEGA_USART0 )
265 lastRxError
= (usr
& (_BV(FE0
)|_BV(DOR0
)) );
266 #elif defined ( ATMEGA_UART )
267 lastRxError
= (usr
& (_BV(FE
)|_BV(DOR
)) );
270 /* calculate buffer index */
271 tmphead
= ( UART_RxHead
+ 1) & UART_RX_BUFFER_MASK
;
273 if ( tmphead
== UART_RxTail
) {
274 /* error: receive buffer overflow */
275 lastRxError
= UART_BUFFER_OVERFLOW
>> 8;
277 /* store new index */
278 UART_RxHead
= tmphead
;
279 /* store received data in buffer */
280 UART_RxBuf
[tmphead
] = data
;
282 UART_LastRxError
= lastRxError
;
286 ISR(UART0_TRANSMIT_INTERRUPT
)
287 /*************************************************************************
288 Function: UART Data Register Empty interrupt
289 Purpose: called when the UART is ready to transmit the next byte
290 **************************************************************************/
292 unsigned char tmptail
;
295 if ( UART_TxHead
!= UART_TxTail
) {
296 /* calculate and store new buffer index */
297 tmptail
= (UART_TxTail
+ 1) & UART_TX_BUFFER_MASK
;
298 UART_TxTail
= tmptail
;
299 /* get one byte from buffer and write it to UART */
300 UART0_DATA
= UART_TxBuf
[tmptail
]; /* start transmission */
302 /* tx buffer empty, disable UDRE interrupt */
303 UART0_CONTROL
&= ~_BV(UART0_UDRIE
);
308 /*************************************************************************
309 Function: uart_init()
310 Purpose: initialize UART and set baudrate
311 Input: baudrate using macro UART_BAUD_SELECT()
313 **************************************************************************/
314 void uart_init(unsigned int baudrate
)
321 #if defined( AT90_UART )
323 UBRR
= (unsigned char)baudrate
;
325 /* enable UART receiver and transmmitter and receive complete interrupt */
326 UART0_CONTROL
= _BV(RXCIE
)|_BV(RXEN
)|_BV(TXEN
);
328 #elif defined (ATMEGA_USART)
330 if ( baudrate
& 0x8000 )
332 UART0_STATUS
= (1<<U2X
); //Enable 2x speed
335 UBRRH
= (unsigned char)(baudrate
>>8);
336 UBRRL
= (unsigned char) baudrate
;
338 /* Enable USART receiver and transmitter and receive complete interrupt */
339 UART0_CONTROL
= _BV(RXCIE
)|(1<<RXEN
)|(1<<TXEN
);
341 /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
343 UCSRC
= (1<<URSEL
)|(3<<UCSZ0
);
348 #elif defined (ATMEGA_USART0 )
350 if ( baudrate
& 0x8000 )
352 UART0_STATUS
= (1<<U2X0
); //Enable 2x speed
355 UBRR0H
= (unsigned char)(baudrate
>>8);
356 UBRR0L
= (unsigned char) baudrate
;
358 /* Enable USART receiver and transmitter and receive complete interrupt */
359 UART0_CONTROL
= _BV(RXCIE0
)|(1<<RXEN0
)|(1<<TXEN0
);
361 /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
363 UCSR0C
= (1<<URSEL0
)|(3<<UCSZ00
);
365 UCSR0C
= (3<<UCSZ00
);
368 #elif defined ( ATMEGA_UART )
370 if ( baudrate
& 0x8000 )
372 UART0_STATUS
= (1<<U2X
); //Enable 2x speed
375 UBRRHI
= (unsigned char)(baudrate
>>8);
376 UBRR
= (unsigned char) baudrate
;
378 /* Enable UART receiver and transmitter and receive complete interrupt */
379 UART0_CONTROL
= _BV(RXCIE
)|(1<<RXEN
)|(1<<TXEN
);
386 /*************************************************************************
387 Function: uart_getc()
388 Purpose: return byte from ringbuffer
389 Returns: lower byte: received byte from ringbuffer
390 higher byte: last receive error
391 **************************************************************************/
392 unsigned int uart_getc(void)
394 unsigned char tmptail
;
398 if ( UART_RxHead
== UART_RxTail
) {
399 return UART_NO_DATA
; /* no data available */
402 /* calculate /store buffer index */
403 tmptail
= (UART_RxTail
+ 1) & UART_RX_BUFFER_MASK
;
404 UART_RxTail
= tmptail
;
406 /* get data from receive buffer */
407 data
= UART_RxBuf
[tmptail
];
409 return (UART_LastRxError
<< 8) + data
;
414 /*************************************************************************
415 Function: uart_putc()
416 Purpose: write byte to ringbuffer for transmitting via UART
417 Input: byte to be transmitted
419 **************************************************************************/
420 void uart_putc(unsigned char data
)
422 unsigned char tmphead
;
425 tmphead
= (UART_TxHead
+ 1) & UART_TX_BUFFER_MASK
;
427 while ( tmphead
== UART_TxTail
){
428 ;/* wait for free space in buffer */
431 UART_TxBuf
[tmphead
] = data
;
432 UART_TxHead
= tmphead
;
434 /* enable UDRE interrupt */
435 UART0_CONTROL
|= _BV(UART0_UDRIE
);
440 /*************************************************************************
441 Function: uart_puts()
442 Purpose: transmit string to UART
443 Input: string to be transmitted
445 **************************************************************************/
446 void uart_puts(const char *s
)
454 /*************************************************************************
455 Function: uart_puts_p()
456 Purpose: transmit string from program memory to UART
457 Input: program memory string to be transmitted
459 **************************************************************************/
460 void uart_puts_p(const char *progmem_s
)
464 while ( (c
= pgm_read_byte(progmem_s
++)) )
471 * these functions are only for ATmegas with two USART
473 #if defined( ATMEGA_USART1 )
475 ISR(UART1_RECEIVE_INTERRUPT
)
476 /*************************************************************************
477 Function: UART1 Receive Complete interrupt
478 Purpose: called when the UART1 has received a character
479 **************************************************************************/
481 unsigned char tmphead
;
484 unsigned char lastRxError
;
487 /* read UART status register and UART data register */
492 lastRxError
= (usr
& (_BV(FE1
)|_BV(DOR1
)) );
494 /* calculate buffer index */
495 tmphead
= ( UART1_RxHead
+ 1) & UART_RX_BUFFER_MASK
;
497 if ( tmphead
== UART1_RxTail
) {
498 /* error: receive buffer overflow */
499 lastRxError
= UART_BUFFER_OVERFLOW
>> 8;
501 /* store new index */
502 UART1_RxHead
= tmphead
;
503 /* store received data in buffer */
504 UART1_RxBuf
[tmphead
] = data
;
506 UART1_LastRxError
= lastRxError
;
510 ISR(UART1_TRANSMIT_INTERRUPT
)
511 /*************************************************************************
512 Function: UART1 Data Register Empty interrupt
513 Purpose: called when the UART1 is ready to transmit the next byte
514 **************************************************************************/
516 unsigned char tmptail
;
519 if ( UART1_TxHead
!= UART1_TxTail
) {
520 /* calculate and store new buffer index */
521 tmptail
= (UART1_TxTail
+ 1) & UART_TX_BUFFER_MASK
;
522 UART1_TxTail
= tmptail
;
523 /* get one byte from buffer and write it to UART */
524 UART1_DATA
= UART1_TxBuf
[tmptail
]; /* start transmission */
526 /* tx buffer empty, disable UDRE interrupt */
527 UART1_CONTROL
&= ~_BV(UART1_UDRIE
);
532 /*************************************************************************
533 Function: uart1_init()
534 Purpose: initialize UART1 and set baudrate
535 Input: baudrate using macro UART_BAUD_SELECT()
537 **************************************************************************/
538 void uart1_init(unsigned int baudrate
)
547 if ( baudrate
& 0x8000 )
549 UART1_STATUS
= (1<<U2X1
); //Enable 2x speed
552 UBRR1H
= (unsigned char)(baudrate
>>8);
553 UBRR1L
= (unsigned char) baudrate
;
555 /* Enable USART receiver and transmitter and receive complete interrupt */
556 UART1_CONTROL
= _BV(RXCIE1
)|(1<<RXEN1
)|(1<<TXEN1
);
558 /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
560 UCSR1C
= (1<<URSEL1
)|(3<<UCSZ10
);
562 UCSR1C
= (3<<UCSZ10
);
567 /*************************************************************************
568 Function: uart1_getc()
569 Purpose: return byte from ringbuffer
570 Returns: lower byte: received byte from ringbuffer
571 higher byte: last receive error
572 **************************************************************************/
573 unsigned int uart1_getc(void)
575 unsigned char tmptail
;
579 if ( UART1_RxHead
== UART1_RxTail
) {
580 return UART_NO_DATA
; /* no data available */
583 /* calculate /store buffer index */
584 tmptail
= (UART1_RxTail
+ 1) & UART_RX_BUFFER_MASK
;
585 UART1_RxTail
= tmptail
;
587 /* get data from receive buffer */
588 data
= UART1_RxBuf
[tmptail
];
590 return (UART1_LastRxError
<< 8) + data
;
595 /*************************************************************************
596 Function: uart1_putc()
597 Purpose: write byte to ringbuffer for transmitting via UART
598 Input: byte to be transmitted
600 **************************************************************************/
601 void uart1_putc(unsigned char data
)
603 unsigned char tmphead
;
606 tmphead
= (UART1_TxHead
+ 1) & UART_TX_BUFFER_MASK
;
608 while ( tmphead
== UART1_TxTail
){
609 ;/* wait for free space in buffer */
612 UART1_TxBuf
[tmphead
] = data
;
613 UART1_TxHead
= tmphead
;
615 /* enable UDRE interrupt */
616 UART1_CONTROL
|= _BV(UART1_UDRIE
);
621 /*************************************************************************
622 Function: uart1_puts()
623 Purpose: transmit string to UART1
624 Input: string to be transmitted
626 **************************************************************************/
627 void uart1_puts(const char *s
)
635 /*************************************************************************
636 Function: uart1_puts_p()
637 Purpose: transmit string from program memory to UART1
638 Input: program memory string to be transmitted
640 **************************************************************************/
641 void uart1_puts_p(const char *progmem_s
)
645 while ( (c
= pgm_read_byte(progmem_s
++)) )