Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
60 jimmy 1
/*************************************************************************
149 jimmy 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.5.2.10 2005/11/15 19:49:12 peter Exp $
5
Software: AVR-GCC 3.3
6
Hardware: any AVR with built-in UART,
7
          tested on AT90S8515 at 4 Mhz and ATmega at 1Mhz
60 jimmy 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
*************************************************************************/
26
#include <avr/io.h>
27
#include <avr/interrupt.h>
28
#include <avr/pgmspace.h>
149 jimmy 29
#include "uart.h"
60 jimmy 30
 
31
 
32
/*
33
 *  constants and macros
34
 */
35
 
36
/* size of RX/TX buffers */
37
#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)
38
#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)
39
 
40
#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
41
#error RX buffer size is not a power of 2
42
#endif
43
#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
44
#error TX buffer size is not a power of 2
45
#endif
46
 
47
#if defined(__AVR_AT90S2313__) \
48
 || defined(__AVR_AT90S4414__) || defined(__AVR_AT90S4434__) \
149 jimmy 49
 || defined(__AVR_AT90S8515__) || defined(__AVR_AT90S8535__) \
50
 || defined(__AVR_ATmega103__)
51
 /* old AVR classic or ATmega103 with one UART */
60 jimmy 52
 #define AT90_UART
53
 #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
54
 #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
55
 #define UART0_STATUS   USR
56
 #define UART0_CONTROL  UCR
57
 #define UART0_DATA     UDR  
58
 #define UART0_UDRIE    UDRIE
59
#elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__)
60
 /* old AVR classic with one UART */
61
 #define AT90_UART
62
 #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
63
 #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
64
 #define UART0_STATUS   UCSRA
65
 #define UART0_CONTROL  UCSRB
66
 #define UART0_DATA     UDR 
67
 #define UART0_UDRIE    UDRIE
68
#elif  defined(__AVR_ATmega8__)  || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
69
  || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) \
149 jimmy 70
  || defined(__AVR_ATmega323__)
71
  /* ATmega with one USART */
60 jimmy 72
 #define ATMEGA_USART
73
 #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
74
 #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
75
 #define UART0_STATUS   UCSRA
76
 #define UART0_CONTROL  UCSRB
77
 #define UART0_DATA     UDR
78
 #define UART0_UDRIE    UDRIE
79
#elif defined(__AVR_ATmega163__) 
149 jimmy 80
  /* ATmega163 with one UART */
60 jimmy 81
 #define ATMEGA_UART
82
 #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
83
 #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
84
 #define UART0_STATUS   UCSRA
85
 #define UART0_CONTROL  UCSRB
86
 #define UART0_DATA     UDR
87
 #define UART0_UDRIE    UDRIE
88
#elif defined(__AVR_ATmega162__)
149 jimmy 89
 /* ATmega with two USART */
60 jimmy 90
 #define ATMEGA_USART0
91
 #define ATMEGA_USART1
92
 #define UART0_RECEIVE_INTERRUPT   SIG_USART0_RECV
93
 #define UART1_RECEIVE_INTERRUPT   SIG_USART1_RECV
94
 #define UART0_TRANSMIT_INTERRUPT  SIG_USART0_DATA
95
 #define UART1_TRANSMIT_INTERRUPT  SIG_USART1_DATA
96
 #define UART0_STATUS   UCSR0A
97
 #define UART0_CONTROL  UCSR0B
98
 #define UART0_DATA     UDR0
99
 #define UART0_UDRIE    UDRIE0
100
 #define UART1_STATUS   UCSR1A
101
 #define UART1_CONTROL  UCSR1B
102
 #define UART1_DATA     UDR1
103
 #define UART1_UDRIE    UDRIE1
104
#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) 
149 jimmy 105
 /* ATmega with two USART */
60 jimmy 106
 #define ATMEGA_USART0
107
 #define ATMEGA_USART1
108
 #define UART0_RECEIVE_INTERRUPT   SIG_UART0_RECV
109
 #define UART1_RECEIVE_INTERRUPT   SIG_UART1_RECV
110
 #define UART0_TRANSMIT_INTERRUPT  SIG_UART0_DATA
111
 #define UART1_TRANSMIT_INTERRUPT  SIG_UART1_DATA
112
 #define UART0_STATUS   UCSR0A
113
 #define UART0_CONTROL  UCSR0B
114
 #define UART0_DATA     UDR0
115
 #define UART0_UDRIE    UDRIE0
116
 #define UART1_STATUS   UCSR1A
117
 #define UART1_CONTROL  UCSR1B
118
 #define UART1_DATA     UDR1
119
 #define UART1_UDRIE    UDRIE1
120
#elif defined(__AVR_ATmega161__)
121
 /* ATmega with UART */
122
 #error "AVR ATmega161 currently not supported by this libaray !"
149 jimmy 123
#elif defined(__AVR_ATmega169__) 
124
 /* ATmega with one USART */
125
 #define ATMEGA_USART
126
 #define UART0_RECEIVE_INTERRUPT   SIG_USART_RECV
127
 #define UART0_TRANSMIT_INTERRUPT  SIG_USART_DATA
128
 #define UART0_STATUS   UCSRA
129
 #define UART0_CONTROL  UCSRB
130
 #define UART0_DATA     UDR
131
 #define UART0_UDRIE    UDRIE
132
#elif defined(__AVR_ATmega48__) ||defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__)
133
 #define ATMEGA_USART0
134
 #define UART0_RECEIVE_INTERRUPT   SIG_USART_RECV
135
 #define UART0_TRANSMIT_INTERRUPT  SIG_USART_DATA
136
 #define UART0_STATUS   UCSR0A
137
 #define UART0_CONTROL  UCSR0B
138
 #define UART0_DATA     UDR0
139
 #define UART0_UDRIE    UDRIE0
140
#elif defined(__AVR_ATtiny2313__)
141
 #define ATMEGA_USART
142
 #define UART0_RECEIVE_INTERRUPT   SIG_USART0_RX 
143
 #define UART0_TRANSMIT_INTERRUPT  SIG_USART0_UDRE
144
 #define UART0_STATUS   UCSRA
145
 #define UART0_CONTROL  UCSRB
146
 #define UART0_DATA     UDR
147
 #define UART0_UDRIE    UDRIE
148
#else
149
 #error "no UART definition for MCU available"
60 jimmy 150
#endif
151
 
152
 
153
/*
154
 *  module global variables
155
 */
156
static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
157
static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
158
static volatile unsigned char UART_TxHead;
159
static volatile unsigned char UART_TxTail;
160
static volatile unsigned char UART_RxHead;
161
static volatile unsigned char UART_RxTail;
162
static volatile unsigned char UART_LastRxError;
163
 
149 jimmy 164
#if defined( ATMEGA_USART1 )
165
static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE];
166
static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE];
167
static volatile unsigned char UART1_TxHead;
168
static volatile unsigned char UART1_TxTail;
169
static volatile unsigned char UART1_RxHead;
170
static volatile unsigned char UART1_RxTail;
171
static volatile unsigned char UART1_LastRxError;
172
#endif
60 jimmy 173
 
174
 
149 jimmy 175
 
176
SIGNAL(UART0_RECEIVE_INTERRUPT)
60 jimmy 177
/*************************************************************************
178
Function: UART Receive Complete interrupt
179
Purpose:  called when the UART has received a character
180
**************************************************************************/
181
{
182
    unsigned char tmphead;
183
    unsigned char data;
184
    unsigned char usr;
185
    unsigned char lastRxError;
186
 
187
 
188
    /* read UART status register and UART data register */
189
    usr  = UART0_STATUS;
190
    data = UART0_DATA;
191
 
192
    /* */
193
#if defined( AT90_UART )
194
    lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
195
#elif defined( ATMEGA_USART )
196
    lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
197
#elif defined( ATMEGA_USART0 )
198
    lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) );
199
#elif defined ( ATMEGA_UART )
200
    lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
201
#endif
202
 
203
    /* calculate buffer index */
204
    tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK;
205
 
206
    if ( tmphead == UART_RxTail ) {
207
        /* error: receive buffer overflow */
208
        lastRxError = UART_BUFFER_OVERFLOW >> 8;
209
    }else{
210
        /* store new index */
211
        UART_RxHead = tmphead;
212
        /* store received data in buffer */
213
        UART_RxBuf[tmphead] = data;
214
    }
149 jimmy 215
    UART_LastRxError = lastRxError;  
60 jimmy 216
}
217
 
218
 
149 jimmy 219
SIGNAL(UART0_TRANSMIT_INTERRUPT)
60 jimmy 220
/*************************************************************************
221
Function: UART Data Register Empty interrupt
222
Purpose:  called when the UART is ready to transmit the next byte
223
**************************************************************************/
224
{
225
    unsigned char tmptail;
226
 
227
 
228
    if ( UART_TxHead != UART_TxTail) {
229
        /* calculate and store new buffer index */
230
        tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
231
        UART_TxTail = tmptail;
232
        /* get one byte from buffer and write it to UART */
233
        UART0_DATA = UART_TxBuf[tmptail];  /* start transmission */
234
    }else{
235
        /* tx buffer empty, disable UDRE interrupt */
236
        UART0_CONTROL &= ~_BV(UART0_UDRIE);
237
    }
238
}
239
 
240
 
241
/*************************************************************************
242
Function: uart_init()
243
Purpose:  initialize UART and set baudrate
244
Input:    baudrate using macro UART_BAUD_SELECT()
245
Returns:  none
246
**************************************************************************/
149 jimmy 247
void uart_init(unsigned int baudrate)
60 jimmy 248
{
249
    UART_TxHead = 0;
250
    UART_TxTail = 0;
251
    UART_RxHead = 0;
252
    UART_RxTail = 0;
253
 
254
#if defined( AT90_UART )
255
    /* set baud rate */
256
    UBRR = (unsigned char)baudrate;
257
 
258
    /* enable UART receiver and transmmitter and receive complete interrupt */
149 jimmy 259
    UART0_CONTROL = _BV(RXCIE)|_BV(RXEN)|_BV(TXEN);
60 jimmy 260
 
261
#elif defined (ATMEGA_USART)
262
    /* Set baud rate */
149 jimmy 263
    if ( baudrate & 0x8000 )
264
    {
265
         UART0_STATUS = (1<<U2X);  //Enable 2x speed 
266
         baudrate &= ~0x8000;
267
    }
60 jimmy 268
    UBRRH = (unsigned char)(baudrate>>8);
269
    UBRRL = (unsigned char) baudrate;
149 jimmy 270
 
60 jimmy 271
    /* Enable USART receiver and transmitter and receive complete interrupt */
272
    UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
273
 
274
    /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
275
    #ifdef URSEL
276
    UCSRC = (1<<URSEL)|(3<<UCSZ0);
277
    #else
278
    UCSRC = (3<<UCSZ0);
279
    #endif 
280
 
281
#elif defined (ATMEGA_USART0 )
282
    /* Set baud rate */
149 jimmy 283
    if ( baudrate & 0x8000 )
284
    {
285
        UART0_STATUS = (1<<U2X0);  //Enable 2x speed 
286
        baudrate &= ~0x8000;
287
    }
60 jimmy 288
    UBRR0H = (unsigned char)(baudrate>>8);
289
    UBRR0L = (unsigned char) baudrate;
290
 
291
    /* Enable USART receiver and transmitter and receive complete interrupt */
292
    UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
293
 
294
    /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
295
    #ifdef URSEL0
296
    UCSR0C = (1<<URSEL0)|(3<<UCSZ00);
297
    #else
298
    UCSR0C = (3<<UCSZ00);
299
    #endif 
300
 
301
#elif defined ( ATMEGA_UART )
302
    /* set baud rate */
149 jimmy 303
    if ( baudrate & 0x8000 )
304
    {
305
        UART0_STATUS = (1<<U2X);  //Enable 2x speed 
306
        baudrate &= ~0x8000;
307
    }
60 jimmy 308
    UBRRHI = (unsigned char)(baudrate>>8);
309
    UBRR   = (unsigned char) baudrate;
310
 
311
    /* Enable UART receiver and transmitter and receive complete interrupt */
312
    UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
313
 
314
#endif
315
 
316
}/* uart_init */
317
 
318
 
319
/*************************************************************************
320
Function: uart_getc()
321
Purpose:  return byte from ringbuffer  
322
Returns:  lower byte:  received byte from ringbuffer
323
          higher byte: last receive error
324
**************************************************************************/
325
unsigned int uart_getc(void)
326
{    
327
    unsigned char tmptail;
328
    unsigned char data;
329
 
330
 
331
    if ( UART_RxHead == UART_RxTail ) {
332
        return UART_NO_DATA;   /* no data available */
333
    }
334
 
335
    /* calculate /store buffer index */
336
    tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
337
    UART_RxTail = tmptail;
338
 
339
    /* get data from receive buffer */
340
    data = UART_RxBuf[tmptail];
341
 
342
    return (UART_LastRxError << 8) + data;
343
 
344
}/* uart_getc */
345
 
346
 
347
/*************************************************************************
348
Function: uart_putc()
349
Purpose:  write byte to ringbuffer for transmitting via UART
350
Input:    byte to be transmitted
351
Returns:  none          
352
**************************************************************************/
353
void uart_putc(unsigned char data)
354
{
355
    unsigned char tmphead;
356
 
357
 
358
    tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
359
 
360
    while ( tmphead == UART_TxTail ){
361
        ;/* wait for free space in buffer */
362
    }
363
 
364
    UART_TxBuf[tmphead] = data;
365
    UART_TxHead = tmphead;
366
 
367
    /* enable UDRE interrupt */
368
    UART0_CONTROL    |= _BV(UART0_UDRIE);
369
 
370
}/* uart_putc */
371
 
372
 
373
/*************************************************************************
374
Function: uart_puts()
375
Purpose:  transmit string to UART
376
Input:    string to be transmitted
377
Returns:  none          
378
**************************************************************************/
379
void uart_puts(const char *s )
380
{
381
    while (*s)
382
      uart_putc(*s++);
383
 
384
}/* uart_puts */
385
 
386
 
387
/*************************************************************************
388
Function: uart_puts_p()
389
Purpose:  transmit string from program memory to UART
390
Input:    program memory string to be transmitted
391
Returns:  none
392
**************************************************************************/
393
void uart_puts_p(const char *progmem_s )
394
{
395
    register char c;
396
 
397
    while ( (c = pgm_read_byte(progmem_s++)) )
398
      uart_putc(c);
399
 
400
}/* uart_puts_p */
401
 
149 jimmy 402
 
403
/*
404
 * these functions are only for ATmegas with two USART
405
 */
406
#if defined( ATMEGA_USART1 )
407
 
408
SIGNAL(UART1_RECEIVE_INTERRUPT)
60 jimmy 409
/*************************************************************************
149 jimmy 410
Function: UART1 Receive Complete interrupt
411
Purpose:  called when the UART1 has received a character
60 jimmy 412
**************************************************************************/
413
{
149 jimmy 414
    unsigned char tmphead;
415
    unsigned char data;
416
    unsigned char usr;
417
    unsigned char lastRxError;
418
 
419
 
420
    /* read UART status register and UART data register */
421
    usr  = UART1_STATUS;
422
    data = UART1_DATA;
60 jimmy 423
 
149 jimmy 424
    /* */
425
    lastRxError = (usr & (_BV(FE1)|_BV(DOR1)) );
426
 
427
    /* calculate buffer index */
428
    tmphead = ( UART1_RxHead + 1) & UART_RX_BUFFER_MASK;
429
 
430
    if ( tmphead == UART1_RxTail ) {
431
        /* error: receive buffer overflow */
432
        lastRxError = UART_BUFFER_OVERFLOW >> 8;
433
    }else{
434
        /* store new index */
435
        UART1_RxHead = tmphead;
436
        /* store received data in buffer */
437
        UART1_RxBuf[tmphead] = data;
438
    }
439
    UART1_LastRxError = lastRxError;  
440
}
60 jimmy 441
 
442
 
149 jimmy 443
SIGNAL(UART1_TRANSMIT_INTERRUPT)
60 jimmy 444
/*************************************************************************
149 jimmy 445
Function: UART1 Data Register Empty interrupt
446
Purpose:  called when the UART1 is ready to transmit the next byte
60 jimmy 447
**************************************************************************/
448
{
149 jimmy 449
    unsigned char tmptail;
60 jimmy 450
 
149 jimmy 451
 
452
    if ( UART1_TxHead != UART1_TxTail) {
453
        /* calculate and store new buffer index */
454
        tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK;
455
        UART1_TxTail = tmptail;
456
        /* get one byte from buffer and write it to UART */
457
        UART1_DATA = UART1_TxBuf[tmptail];  /* start transmission */
458
    }else{
459
        /* tx buffer empty, disable UDRE interrupt */
460
        UART1_CONTROL &= ~_BV(UART1_UDRIE);
461
    }
462
}
463
 
464
 
60 jimmy 465
/*************************************************************************
149 jimmy 466
Function: uart1_init()
467
Purpose:  initialize UART1 and set baudrate
468
Input:    baudrate using macro UART_BAUD_SELECT()
60 jimmy 469
Returns:  none
470
**************************************************************************/
149 jimmy 471
void uart1_init(unsigned int baudrate)
60 jimmy 472
{
149 jimmy 473
    UART1_TxHead = 0;
474
    UART1_TxTail = 0;
475
    UART1_RxHead = 0;
476
    UART1_RxTail = 0;
477
 
60 jimmy 478
 
149 jimmy 479
    /* Set baud rate */
480
    if ( baudrate & 0x8000 )
481
    {
482
        UART1_STATUS = (1<<U2X1);  //Enable 2x speed 
483
      baudrate &= ~0x8000;
484
    }
485
    UBRR1H = (unsigned char)(baudrate>>8);
486
    UBRR1L = (unsigned char) baudrate;
487
 
488
    /* Enable USART receiver and transmitter and receive complete interrupt */
489
    UART1_CONTROL = _BV(RXCIE1)|(1<<RXEN1)|(1<<TXEN1);
490
 
491
    /* Set frame format: asynchronous, 8data, no parity, 1stop bit */  
492
    #ifdef URSEL1
493
    UCSR1C = (1<<URSEL1)|(3<<UCSZ10);
494
    #else
495
    UCSR1C = (3<<UCSZ10);
496
    #endif 
497
}/* uart_init */
498
 
499
 
60 jimmy 500
/*************************************************************************
149 jimmy 501
Function: uart1_getc()
502
Purpose:  return byte from ringbuffer  
503
Returns:  lower byte:  received byte from ringbuffer
504
          higher byte: last receive error
505
**************************************************************************/
506
unsigned int uart1_getc(void)
507
{    
508
    unsigned char tmptail;
509
    unsigned char data;
510
 
511
 
512
    if ( UART1_RxHead == UART1_RxTail ) {
513
        return UART_NO_DATA;   /* no data available */
514
    }
515
 
516
    /* calculate /store buffer index */
517
    tmptail = (UART1_RxTail + 1) & UART_RX_BUFFER_MASK;
518
    UART1_RxTail = tmptail;
519
 
520
    /* get data from receive buffer */
521
    data = UART1_RxBuf[tmptail];
522
 
523
    return (UART1_LastRxError << 8) + data;
524
 
525
}/* uart1_getc */
526
 
527
 
528
/*************************************************************************
529
Function: uart1_putc()
530
Purpose:  write byte to ringbuffer for transmitting via UART
531
Input:    byte to be transmitted
532
Returns:  none          
533
**************************************************************************/
534
void uart1_putc(unsigned char data)
535
{
536
    unsigned char tmphead;
537
 
538
 
539
    tmphead  = (UART1_TxHead + 1) & UART_TX_BUFFER_MASK;
540
 
541
    while ( tmphead == UART1_TxTail ){
542
        ;/* wait for free space in buffer */
543
    }
544
 
545
    UART1_TxBuf[tmphead] = data;
546
    UART1_TxHead = tmphead;
547
 
548
    /* enable UDRE interrupt */
549
    UART1_CONTROL    |= _BV(UART1_UDRIE);
550
 
551
}/* uart1_putc */
552
 
553
 
554
/*************************************************************************
555
Function: uart1_puts()
556
Purpose:  transmit string to UART1
557
Input:    string to be transmitted
558
Returns:  none          
559
**************************************************************************/
560
void uart1_puts(const char *s )
561
{
562
    while (*s)
563
      uart1_putc(*s++);
564
 
565
}/* uart1_puts */
566
 
567
 
568
/*************************************************************************
569
Function: uart1_puts_p()
570
Purpose:  transmit string from program memory to UART1
571
Input:    program memory string to be transmitted
60 jimmy 572
Returns:  none
573
**************************************************************************/
149 jimmy 574
void uart1_puts_p(const char *progmem_s )
60 jimmy 575
{
149 jimmy 576
    register char c;
60 jimmy 577
 
149 jimmy 578
    while ( (c = pgm_read_byte(progmem_s++)) )
579
      uart1_putc(c);
580
 
581
}/* uart1_puts_p */
582
 
583
 
60 jimmy 584
#endif