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.12 2014/01/08 21:58: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
|
8 |
|
9 | DESCRIPTION:
|
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.
|
13 |
|
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
|
16 | power of 2.
|
17 |
|
18 | USAGE:
|
19 | Refere to the header file uart.h for a description of the routines.
|
20 | See also example test_uart.c.
|
21 |
|
22 | NOTES:
|
23 | Based on Atmel Application Note AVR306
|
24 |
|
25 | LICENSE:
|
26 | Copyright (C) 2006 Peter Fleury
|
27 |
|
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
|
31 | any later version.
|
32 |
|
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.
|
37 |
|
38 | *************************************************************************/
|
39 | #include <avr/io.h>
|
40 | #include <avr/interrupt.h>
|
41 | #include <avr/pgmspace.h>
|
42 | #include "uart.h"
|
43 |
|
44 |
|
45 | /*
|
46 | * constants and macros
|
47 | */
|
48 |
|
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)
|
52 |
|
53 | #if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
|
54 | #error RX buffer size is not a power of 2
|
55 | #endif
|
56 | #if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
|
57 | #error TX buffer size is not a power of 2
|
58 | #endif
|
59 |
|
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 */
|
65 | #define AT90_UART
|
66 | #define UART0_RECEIVE_INTERRUPT UART_RX_vect
|
67 | #define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
|
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 */
|
74 | #define AT90_UART
|
75 | #define UART0_RECEIVE_INTERRUPT UART_RX_vect
|
76 | #define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
|
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_ATmega323__)
|
83 | /* ATmega with one USART */
|
84 | #define ATMEGA_USART
|
85 | #define UART0_RECEIVE_INTERRUPT USART_RXC_vect
|
86 | #define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
|
87 | #define UART0_STATUS UCSRA
|
88 | #define UART0_CONTROL UCSRB
|
89 | #define UART0_DATA UDR
|
90 | #define UART0_UDRIE UDRIE
|
91 | #elif defined (__AVR_ATmega8515__) || defined(__AVR_ATmega8535__)
|
92 | #define ATMEGA_USART
|
93 | #define UART0_RECEIVE_INTERRUPT USART_RX_vect
|
94 | #define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
|
95 | #define UART0_STATUS UCSRA
|
96 | #define UART0_CONTROL UCSRB
|
97 | #define UART0_DATA UDR
|
98 | #define UART0_UDRIE UDRIE
|
99 | #elif defined(__AVR_ATmega163__)
|
100 | /* ATmega163 with one UART */
|
101 | #define ATMEGA_UART
|
102 | #define UART0_RECEIVE_INTERRUPT UART_RX_vect
|
103 | #define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
|
104 | #define UART0_STATUS UCSRA
|
105 | #define UART0_CONTROL UCSRB
|
106 | #define UART0_DATA UDR
|
107 | #define UART0_UDRIE UDRIE
|
108 | #elif defined(__AVR_ATmega162__)
|
109 | /* ATmega with two USART */
|
110 | #define ATMEGA_USART0
|
111 | #define ATMEGA_USART1
|
112 | #define UART0_RECEIVE_INTERRUPT USART0_RXC_vect
|
113 | #define UART1_RECEIVE_INTERRUPT USART1_RXC_vect
|
114 | #define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
115 | #define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
|
116 | #define UART0_STATUS UCSR0A
|
117 | #define UART0_CONTROL UCSR0B
|
118 | #define UART0_DATA UDR0
|
119 | #define UART0_UDRIE UDRIE0
|
120 | #define UART1_STATUS UCSR1A
|
121 | #define UART1_CONTROL UCSR1B
|
122 | #define UART1_DATA UDR1
|
123 | #define UART1_UDRIE UDRIE1
|
124 | #elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
|
125 | /* ATmega with two USART */
|
126 | #define ATMEGA_USART0
|
127 | #define ATMEGA_USART1
|
128 | #define UART0_RECEIVE_INTERRUPT USART0_RX_vect
|
129 | #define UART1_RECEIVE_INTERRUPT USART1_RX_vect
|
130 | #define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
131 | #define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
|
132 | #define UART0_STATUS UCSR0A
|
133 | #define UART0_CONTROL UCSR0B
|
134 | #define UART0_DATA UDR0
|
135 | #define UART0_UDRIE UDRIE0
|
136 | #define UART1_STATUS UCSR1A
|
137 | #define UART1_CONTROL UCSR1B
|
138 | #define UART1_DATA UDR1
|
139 | #define UART1_UDRIE UDRIE1
|
140 | #elif defined(__AVR_ATmega161__)
|
141 | /* ATmega with UART */
|
142 | #error "AVR ATmega161 currently not supported by this libaray !"
|
143 | #elif defined(__AVR_ATmega169__)
|
144 | /* ATmega with one USART */
|
145 | #define ATMEGA_USART
|
146 | #define UART0_RECEIVE_INTERRUPT USART0_RX_vect
|
147 | #define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
148 | #define UART0_STATUS UCSRA
|
149 | #define UART0_CONTROL UCSRB
|
150 | #define UART0_DATA UDR
|
151 | #define UART0_UDRIE UDRIE
|
152 | #elif defined(__AVR_ATmega48__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) \
|
153 | || defined(__AVR_ATmega3250__) || defined(__AVR_ATmega3290__) ||defined(__AVR_ATmega6450__) || defined(__AVR_ATmega6490__)
|
154 | /* ATmega with one USART */
|
155 | #define ATMEGA_USART0
|
156 | #define UART0_RECEIVE_INTERRUPT USART_RX_vect
|
157 | #define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
|
158 | #define UART0_STATUS UCSR0A
|
159 | #define UART0_CONTROL UCSR0B
|
160 | #define UART0_DATA UDR0
|
161 | #define UART0_UDRIE UDRIE0
|
162 | #elif defined(__AVR_ATtiny2313__)
|
163 | #define ATMEGA_USART
|
164 | #define UART0_RECEIVE_INTERRUPT USART_RX_vect
|
165 | #define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
|
166 | #define UART0_STATUS UCSRA
|
167 | #define UART0_CONTROL UCSRB
|
168 | #define UART0_DATA UDR
|
169 | #define UART0_UDRIE UDRIE
|
170 | #elif defined(__AVR_ATmega329__) || \
|
171 | defined(__AVR_ATmega649__) || \
|
172 | defined(__AVR_ATmega325__) || \
|
173 | defined(__AVR_ATmega645__)
|
174 | /* ATmega with one USART */
|
175 | #define ATMEGA_USART0
|
176 | #define UART0_RECEIVE_INTERRUPT USART0_RX_vect
|
177 | #define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
178 | #define UART0_STATUS UCSR0A
|
179 | #define UART0_CONTROL UCSR0B
|
180 | #define UART0_DATA UDR0
|
181 | #define UART0_UDRIE UDRIE0
|
182 | #elif defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega640__) || defined(__AVR_AT90CAN128__) \
|
183 | || defined(__AVR_AT90CAN64__) || defined(__AVR_AT90CAN32__)
|
184 | /* ATmega with two USART */
|
185 | #define ATMEGA_USART0
|
186 | #define ATMEGA_USART1
|
187 | #define UART0_RECEIVE_INTERRUPT USART0_RX_vect
|
188 | #define UART1_RECEIVE_INTERRUPT USART1_RX_vect
|
189 | #define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
190 | #define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
|
191 | #define UART0_STATUS UCSR0A
|
192 | #define UART0_CONTROL UCSR0B
|
193 | #define UART0_DATA UDR0
|
194 | #define UART0_UDRIE UDRIE0
|
195 | #define UART1_STATUS UCSR1A
|
196 | #define UART1_CONTROL UCSR1B
|
197 | #define UART1_DATA UDR1
|
198 | #define UART1_UDRIE UDRIE1
|
199 | #elif defined(__AVR_ATmega644__)
|
200 | /* ATmega with one USART */
|
201 | #define ATMEGA_USART0
|
202 | #define UART0_RECEIVE_INTERRUPT USART0_RX_vect
|
203 | #define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
204 | #define UART0_STATUS UCSR0A
|
205 | #define UART0_CONTROL UCSR0B
|
206 | #define UART0_DATA UDR0
|
207 | #define UART0_UDRIE UDRIE0
|
208 | #elif defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644P__)
|
209 | /* ATmega with two USART */
|
210 | #define ATMEGA_USART0
|
211 | #define ATMEGA_USART1
|
212 | #define UART0_RECEIVE_INTERRUPT USART0_RX_vect
|
213 | #define UART1_RECEIVE_INTERRUPT USART1_RX_vect
|
214 | #define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
215 | #define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
|
216 | #define UART0_STATUS UCSR0A
|
217 | #define UART0_CONTROL UCSR0B
|
218 | #define UART0_DATA UDR0
|
219 | #define UART0_UDRIE UDRIE0
|
220 | #define UART1_STATUS UCSR1A
|
221 | #define UART1_CONTROL UCSR1B
|
222 | #define UART1_DATA UDR1
|
223 | #define UART1_UDRIE UDRIE1
|
224 | #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__)
|
225 | /* AT90USBxx with one USART */
|
226 | #define AT90USB_USART
|
227 | #define UART0_RECEIVE_INTERRUPT USART1_RX_vect
|
228 | #define UART0_TRANSMIT_INTERRUPT USART1_UDRE_vect
|
229 | #define UART0_STATUS UCSR1A
|
230 | #define UART0_CONTROL UCSR1B
|
231 | #define UART0_DATA UDR1
|
232 | #define UART0_UDRIE UDRIE1
|
233 | #else
|
234 | #error "no UART definition for MCU available"
|
235 | #endif
|
236 |
|
237 |
|
238 | /*
|
239 | * module global variables
|
240 | */
|
241 | static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
|
242 | static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
|
243 | static volatile unsigned char UART_TxHead;
|
244 | static volatile unsigned char UART_TxTail;
|
245 | static volatile unsigned char UART_RxHead;
|
246 | static volatile unsigned char UART_RxTail;
|
247 | static volatile unsigned char UART_LastRxError;
|
248 |
|
249 | #if defined( ATMEGA_USART1 )
|
250 | static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE];
|
251 | static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE];
|
252 | static volatile unsigned char UART1_TxHead;
|
253 | static volatile unsigned char UART1_TxTail;
|
254 | static volatile unsigned char UART1_RxHead;
|
255 | static volatile unsigned char UART1_RxTail;
|
256 | static volatile unsigned char UART1_LastRxError;
|
257 | #endif
|
258 |
|
259 |
|
260 |
|
261 | ISR (UART0_RECEIVE_INTERRUPT)
|
262 | /*************************************************************************
|
263 | Function: UART Receive Complete interrupt
|
264 | Purpose: called when the UART has received a character
|
265 | **************************************************************************/
|
266 | {
|
267 | unsigned char tmphead;
|
268 | unsigned char data;
|
269 | unsigned char usr;
|
270 | unsigned char lastRxError;
|
271 |
|
272 |
|
273 | /* read UART status register and UART data register */
|
274 | usr = UART0_STATUS;
|
275 | data = UART0_DATA;
|
276 |
|
277 | /* */
|
278 | #if defined( AT90_UART )
|
279 | lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
|
280 | #elif defined( ATMEGA_USART )
|
281 | lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
|
282 | #elif defined( ATMEGA_USART0 )
|
283 | lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) );
|
284 | #elif defined ( ATMEGA_UART )
|
285 | lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
|
286 | #elif defined( AT90USB_USART )
|
287 | lastRxError = (usr & (_BV(FE1)|_BV(DOR1)) );
|
288 | #endif
|
289 |
|
290 | /* calculate buffer index */
|
291 | tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK;
|
292 |
|
293 | if ( tmphead == UART_RxTail ) {
|
294 | /* error: receive buffer overflow */
|
295 | lastRxError = UART_BUFFER_OVERFLOW >> 8;
|
296 | }else{
|
297 | /* store new index */
|
298 | UART_RxHead = tmphead;
|
299 | /* store received data in buffer */
|
300 | UART_RxBuf[tmphead] = data;
|
301 | }
|
302 | UART_LastRxError |= lastRxError;
|
303 | }
|
304 |
|
305 |
|
306 | ISR (UART0_TRANSMIT_INTERRUPT)
|
307 | /*************************************************************************
|
308 | Function: UART Data Register Empty interrupt
|
309 | Purpose: called when the UART is ready to transmit the next byte
|
310 | **************************************************************************/
|
311 | {
|
312 | unsigned char tmptail;
|
313 |
|
314 |
|
315 | if ( UART_TxHead != UART_TxTail) {
|
316 | /* calculate and store new buffer index */
|
317 | tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
|
318 | UART_TxTail = tmptail;
|
319 | /* get one byte from buffer and write it to UART */
|
320 | UART0_DATA = UART_TxBuf[tmptail]; /* start transmission */
|
321 | }else{
|
322 | /* tx buffer empty, disable UDRE interrupt */
|
323 | UART0_CONTROL &= ~_BV(UART0_UDRIE);
|
324 | }
|
325 | }
|
326 |
|
327 |
|
328 | /*************************************************************************
|
329 | Function: uart_init()
|
330 | Purpose: initialize UART and set baudrate
|
331 | Input: baudrate using macro UART_BAUD_SELECT()
|
332 | Returns: none
|
333 | **************************************************************************/
|
334 | void uart_init(unsigned int baudrate)
|
335 | {
|
336 | UART_TxHead = 0;
|
337 | UART_TxTail = 0;
|
338 | UART_RxHead = 0;
|
339 | UART_RxTail = 0;
|
340 |
|
341 | #if defined( AT90_UART )
|
342 | /* set baud rate */
|
343 | UBRR = (unsigned char)baudrate;
|
344 |
|
345 | /* enable UART receiver and transmmitter and receive complete interrupt */
|
346 | UART0_CONTROL = _BV(RXCIE)|_BV(RXEN)|_BV(TXEN);
|
347 |
|
348 | #elif defined (ATMEGA_USART)
|
349 | /* Set baud rate */
|
350 | if ( baudrate & 0x8000 )
|
351 | {
|
352 | UART0_STATUS = (1<<U2X); //Enable 2x speed
|
353 | baudrate &= ~0x8000;
|
354 | }
|
355 | UBRRH = (unsigned char)(baudrate>>8);
|
356 | UBRRL = (unsigned char) baudrate;
|
357 |
|
358 | /* Enable USART receiver and transmitter and receive complete interrupt */
|
359 | UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
|
360 |
|
361 | /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
|
362 | #ifdef URSEL
|
363 | UCSRC = (1<<URSEL)|(3<<UCSZ0);
|
364 | #else
|
365 | UCSRC = (3<<UCSZ0);
|
366 | #endif
|
367 |
|
368 | #elif defined (ATMEGA_USART0 )
|
369 | /* Set baud rate */
|
370 | if ( baudrate & 0x8000 )
|
371 | {
|
372 | UART0_STATUS = (1<<U2X0); //Enable 2x speed
|
373 | baudrate &= ~0x8000;
|
374 | }
|
375 | UBRR0H = (unsigned char)(baudrate>>8);
|
376 | UBRR0L = (unsigned char) baudrate;
|
377 |
|
378 | /* Enable USART receiver and transmitter and receive complete interrupt */
|
379 | UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
|
380 |
|
381 | /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
|
382 | #ifdef URSEL0
|
383 | UCSR0C = (1<<URSEL0)|(3<<UCSZ00);
|
384 | #else
|
385 | UCSR0C = (3<<UCSZ00);
|
386 | #endif
|
387 |
|
388 | #elif defined ( ATMEGA_UART )
|
389 | /* set baud rate */
|
390 | if ( baudrate & 0x8000 )
|
391 | {
|
392 | UART0_STATUS = (1<<U2X); //Enable 2x speed
|
393 | baudrate &= ~0x8000;
|
394 | }
|
395 | UBRRHI = (unsigned char)(baudrate>>8);
|
396 | UBRR = (unsigned char) baudrate;
|
397 |
|
398 | /* Enable UART receiver and transmitter and receive complete interrupt */
|
399 | UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
|
400 |
|
401 | #elif defined ( AT90USB_USART )
|
402 | /* set baud rate */
|
403 | if ( baudrate & 0x8000 )
|
404 | {
|
405 | UART0_STATUS = (1<<U2X1 ); //Enable 2x speed
|
406 | baudrate &= ~0x8000;
|
407 | }
|
408 | UBRR1H = (unsigned char)(baudrate>>8);
|
409 | UBRR1L = (unsigned char) baudrate;
|
410 |
|
411 | /* Enable UART receiver and transmitter and receive complete interrupt */
|
412 | UART0_CONTROL = _BV(RXCIE1)|(1<<RXEN1)|(1<<TXEN1);
|
413 |
|
414 | /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
|
415 | UCSR1C = (1<<UCSZ11)|(1<<UCSZ10);
|
416 | #endif
|
417 |
|
418 | }/* uart_init */
|
419 |
|
420 |
|
421 | /*************************************************************************
|
422 | Function: uart_getc()
|
423 | Purpose: return byte from ringbuffer
|
424 | Returns: lower byte: received byte from ringbuffer
|
425 | higher byte: last receive error
|
426 | **************************************************************************/
|
427 | unsigned int uart_getc(void)
|
428 | {
|
429 | unsigned char tmptail;
|
430 | unsigned char data;
|
431 |
|
432 |
|
433 | if ( UART_RxHead == UART_RxTail ) {
|
434 | return UART_NO_DATA; /* no data available */
|
435 | }
|
436 |
|
437 | /* calculate /store buffer index */
|
438 | tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
|
439 | UART_RxTail = tmptail;
|
440 |
|
441 | /* get data from receive buffer */
|
442 | data = UART_RxBuf[tmptail];
|
443 |
|
444 | data = (UART_LastRxError << 8) + data;
|
445 | UART_LastRxError = 0;
|
446 |
|
447 | return data;
|
448 |
|
449 | }/* uart_getc */
|
450 |
|
451 |
|
452 | /*************************************************************************
|
453 | Function: uart_putc()
|
454 | Purpose: write byte to ringbuffer for transmitting via UART
|
455 | Input: byte to be transmitted
|
456 | Returns: none
|
457 | **************************************************************************/
|
458 | void uart_putc(unsigned char data)
|
459 | {
|
460 | unsigned char tmphead;
|
461 |
|
462 |
|
463 | tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
|
464 |
|
465 | while ( tmphead == UART_TxTail ){
|
466 | ;/* wait for free space in buffer */
|
467 | }
|
468 |
|
469 | UART_TxBuf[tmphead] = data;
|
470 | UART_TxHead = tmphead;
|
471 |
|
472 | /* enable UDRE interrupt */
|
473 | UART0_CONTROL |= _BV(UART0_UDRIE);
|
474 |
|
475 | }/* uart_putc */
|
476 |
|
477 |
|
478 | /*************************************************************************
|
479 | Function: uart_puts()
|
480 | Purpose: transmit string to UART
|
481 | Input: string to be transmitted
|
482 | Returns: none
|
483 | **************************************************************************/
|
484 | void uart_puts(const char *s )
|
485 | {
|
486 | while (*s)
|
487 | uart_putc(*s++);
|
488 |
|
489 | }/* uart_puts */
|
490 |
|
491 |
|
492 | /*************************************************************************
|
493 | Function: uart_puts_p()
|
494 | Purpose: transmit string from program memory to UART
|
495 | Input: program memory string to be transmitted
|
496 | Returns: none
|
497 | **************************************************************************/
|
498 | void uart_puts_p(const char *progmem_s )
|
499 | {
|
500 | register char c;
|
501 |
|
502 | while ( (c = pgm_read_byte(progmem_s++)) )
|
503 | uart_putc(c);
|
504 |
|
505 | }/* uart_puts_p */
|
506 |
|
507 |
|
508 | /*
|
509 | * these functions are only for ATmegas with two USART
|
510 | */
|
511 | #if defined( ATMEGA_USART1 )
|
512 |
|
513 | ISR(UART1_RECEIVE_INTERRUPT)
|
514 | /*************************************************************************
|
515 | Function: UART1 Receive Complete interrupt
|
516 | Purpose: called when the UART1 has received a character
|
517 | **************************************************************************/
|
518 | {
|
519 | unsigned char tmphead;
|
520 | unsigned char data;
|
521 | unsigned char usr;
|
522 | unsigned char lastRxError;
|
523 |
|
524 |
|
525 | /* read UART status register and UART data register */
|
526 | usr = UART1_STATUS;
|
527 | data = UART1_DATA;
|
528 |
|
529 | /* */
|
530 | lastRxError = (usr & (_BV(FE1)|_BV(DOR1)) );
|
531 |
|
532 | /* calculate buffer index */
|
533 | tmphead = ( UART1_RxHead + 1) & UART_RX_BUFFER_MASK;
|
534 |
|
535 | if ( tmphead == UART1_RxTail ) {
|
536 | /* error: receive buffer overflow */
|
537 | lastRxError = UART_BUFFER_OVERFLOW >> 8;
|
538 | }else{
|
539 | /* store new index */
|
540 | UART1_RxHead = tmphead;
|
541 | /* store received data in buffer */
|
542 | UART1_RxBuf[tmphead] = data;
|
543 | }
|
544 | UART1_LastRxError |= lastRxError;
|
545 | }
|
546 |
|
547 |
|
548 | ISR(UART1_TRANSMIT_INTERRUPT)
|
549 | /*************************************************************************
|
550 | Function: UART1 Data Register Empty interrupt
|
551 | Purpose: called when the UART1 is ready to transmit the next byte
|
552 | **************************************************************************/
|
553 | {
|
554 | unsigned char tmptail;
|
555 |
|
556 |
|
557 | if ( UART1_TxHead != UART1_TxTail) {
|
558 | /* calculate and store new buffer index */
|
559 | tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK;
|
560 | UART1_TxTail = tmptail;
|
561 | /* get one byte from buffer and write it to UART */
|
562 | UART1_DATA = UART1_TxBuf[tmptail]; /* start transmission */
|
563 | }else{
|
564 | /* tx buffer empty, disable UDRE interrupt */
|
565 | UART1_CONTROL &= ~_BV(UART1_UDRIE);
|
566 | }
|
567 | }
|
568 |
|
569 |
|
570 | /*************************************************************************
|
571 | Function: uart1_init()
|
572 | Purpose: initialize UART1 and set baudrate
|
573 | Input: baudrate using macro UART_BAUD_SELECT()
|
574 | Returns: none
|
575 | **************************************************************************/
|
576 | void uart1_init(unsigned int baudrate)
|
577 | {
|
578 | UART1_TxHead = 0;
|
579 | UART1_TxTail = 0;
|
580 | UART1_RxHead = 0;
|
581 | UART1_RxTail = 0;
|
582 |
|
583 |
|
584 | /* Set baud rate */
|
585 | if ( baudrate & 0x8000 )
|
586 | {
|
587 | UART1_STATUS = (1<<U2X1); //Enable 2x speed
|
588 | baudrate &= ~0x8000;
|
589 | }
|
590 | UBRR1H = (unsigned char)(baudrate>>8);
|
591 | UBRR1L = (unsigned char) baudrate;
|
592 |
|
593 | /* Enable USART receiver and transmitter and receive complete interrupt */
|
594 | UART1_CONTROL = _BV(RXCIE1)|(1<<RXEN1)|(1<<TXEN1);
|
595 |
|
596 | /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
|
597 | #ifdef URSEL1
|
598 | UCSR1C = (1<<URSEL1)|(3<<UCSZ10);
|
599 | #else
|
600 | UCSR1C = (3<<UCSZ10);
|
601 | #endif
|
602 | }/* uart_init */
|
603 |
|
604 |
|
605 | /*************************************************************************
|
606 | Function: uart1_getc()
|
607 | Purpose: return byte from ringbuffer
|
608 | Returns: lower byte: received byte from ringbuffer
|
609 | higher byte: last receive error
|
610 | **************************************************************************/
|
611 | unsigned int uart1_getc(void)
|
612 | {
|
613 | unsigned char tmptail;
|
614 | unsigned char data;
|
615 |
|
616 |
|
617 | if ( UART1_RxHead == UART1_RxTail ) {
|
618 | return UART_NO_DATA; /* no data available */
|
619 | }
|
620 |
|
621 | /* calculate /store buffer index */
|
622 | tmptail = (UART1_RxTail + 1) & UART_RX_BUFFER_MASK;
|
623 | UART1_RxTail = tmptail;
|
624 |
|
625 | /* get data from receive buffer */
|
626 | data = UART1_RxBuf[tmptail];
|
627 |
|
628 | data = (UART1_LastRxError << 8) + data;
|
629 | UART1_LastRxError = 0;
|
630 | return data;
|
631 |
|
632 | }/* uart1_getc */
|
633 |
|
634 |
|
635 | /*************************************************************************
|
636 | Function: uart1_putc()
|
637 | Purpose: write byte to ringbuffer for transmitting via UART
|
638 | Input: byte to be transmitted
|
639 | Returns: none
|
640 | **************************************************************************/
|
641 | void uart1_putc(unsigned char data)
|
642 | {
|
643 | unsigned char tmphead;
|
644 |
|
645 |
|
646 | tmphead = (UART1_TxHead + 1) & UART_TX_BUFFER_MASK;
|
647 |
|
648 | while ( tmphead == UART1_TxTail ){
|
649 | ;/* wait for free space in buffer */
|
650 | }
|
651 |
|
652 | UART1_TxBuf[tmphead] = data;
|
653 | UART1_TxHead = tmphead;
|
654 |
|
655 | /* enable UDRE interrupt */
|
656 | UART1_CONTROL |= _BV(UART1_UDRIE);
|
657 |
|
658 | }/* uart1_putc */
|
659 |
|
660 |
|
661 | /*************************************************************************
|
662 | Function: uart1_puts()
|
663 | Purpose: transmit string to UART1
|
664 | Input: string to be transmitted
|
665 | Returns: none
|
666 | **************************************************************************/
|
667 | void uart1_puts(const char *s )
|
668 | {
|
669 | while (*s)
|
670 | uart1_putc(*s++);
|
671 |
|
672 | }/* uart1_puts */
|
673 |
|
674 |
|
675 | /*************************************************************************
|
676 | Function: uart1_puts_p()
|
677 | Purpose: transmit string from program memory to UART1
|
678 | Input: program memory string to be transmitted
|
679 | Returns: none
|
680 | **************************************************************************/
|
681 | void uart1_puts_p(const char *progmem_s )
|
682 | {
|
683 | register char c;
|
684 |
|
685 | while ( (c = pgm_read_byte(progmem_s++)) )
|
686 | uart1_putc(c);
|
687 |
|
688 | }/* uart1_puts_p */
|
689 |
|
690 |
|
691 | #endif
|