Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1470 - 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
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
 
40
#include <avr/io.h>
41
#include <avr/interrupt.h>
42
#include <avr/pgmspace.h>
43
#include "uart1.h"
44
#include "main.h"
45
 
46
//
47
//  constants and macros
48
//
49
 
50
 
51
// size of RX/TX buffers
52
#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)
53
#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)
54
 
55
#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
56
#error RX buffer size is not a power of 2
57
#endif
58
 
59
#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
60
#error TX buffer size is not a power of 2
61
#endif
62
 
63
 
64
// ATmega with two USART
65
 
66
#define ATMEGA_USART1
67
 
68
#define UART1_STATUS   UCSR1A
69
#define UART1_CONTROL  UCSR1B
70
#define UART1_DATA     UDR1
71
#define UART1_UDRIE    UDRIE1
72
 
73
 
74
 
75
//
76
//  module global variables
77
//
78
 
79
#if defined( ATMEGA_USART1 )
80
static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE];
81
static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE];
82
static volatile unsigned char UART1_TxHead;
83
static volatile unsigned char UART1_TxTail;
84
static volatile unsigned char UART1_RxHead;
85
static volatile unsigned char UART1_RxTail;
86
static volatile unsigned char UART1_LastRxError;
87
#endif
88
 
89
 
90
 
91
 
92
//
93
// these functions are only for ATmegas with two USART
94
//
95
 
96
 
97
#if defined( ATMEGA_USART1 )
98
 
99
//--------------------------------------------------------------
100
// Function: UART1 Receive Complete interrupt
101
// Purpose:  called when the UART1 has received a character
102
//--------------------------------------------------------------
103
ISR(USART1_RX_vect)
104
{
105
        unsigned char tmphead;
106
        unsigned char data;
107
        unsigned char usr;
108
        unsigned char lastRxError;
109
 
110
 
111
        // read UART status register and UART data register
112
        usr  = UART1_STATUS;
113
        data = UART1_DATA;
114
 
115
        lastRxError = (usr & (_BV(FE1)|_BV(DOR1)) );
116
 
117
        // calculate buffer index
118
        tmphead = ( UART1_RxHead + 1) & UART_RX_BUFFER_MASK;
119
 
120
        if ( tmphead == UART1_RxTail )
121
        {
122
                // error: receive buffer overflow
123
                lastRxError = UART_BUFFER_OVERFLOW >> 8;
124
        }
125
        else
126
        {
127
                // store new index
128
                UART1_RxHead = tmphead;
129
                // store received data in buffer
130
                UART1_RxBuf[tmphead] = data;
131
        }
132
        UART1_LastRxError = lastRxError;
133
}
134
 
135
 
136
//--------------------------------------------------------------
137
// Function: UART1 Data Register Empty interrupt
138
// Purpose:  called when the UART1 is ready to transmit the next byte
139
//--------------------------------------------------------------
140
ISR(USART1_UDRE_vect)
141
{
142
        unsigned char tmptail;
143
 
144
 
145
        if ( UART1_TxHead != UART1_TxTail)
146
        {
147
                // calculate and store new buffer index
148
                tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK;
149
                UART1_TxTail = tmptail;
150
                // get one byte from buffer and write it to UART
151
                UART1_DATA = UART1_TxBuf[tmptail];  // start transmission
152
        }
153
        else
154
        {
155
                // tx buffer empty, disable UDRE interrupt
156
                UART1_CONTROL &= ~_BV(UART1_UDRIE);
157
        }
158
}
159
 
160
 
161
//--------------------------------------------------------------
162
// Function: uart1_init()
163
// Purpose:  initialize UART1 and set baudrate
164
// Input:       baudrate using macro UART_BAUD_SELECT()
165
// Returns:  none
166
//--------------------------------------------------------------
167
void uart1_init(unsigned int baudrate)
168
{
169
        UART1_TxHead = 0;
170
        UART1_TxTail = 0;
171
        UART1_RxHead = 0;
172
        UART1_RxTail = 0;
173
 
174
 
175
        // Set baud rate
176
        if ( baudrate & 0x8000 )
177
        {
178
                UART1_STATUS = (1<<U2X1);  //Enable 2x speed
179
                baudrate &= ~0x8000;
180
        }
181
        UBRR1H = (unsigned char)(baudrate>>8);
182
        UBRR1L = (unsigned char) baudrate;
183
 
184
        // Enable USART receiver and transmitter and receive complete interrupt
185
        UART1_CONTROL = _BV(RXCIE1)|(1<<RXEN1)|(1<<TXEN1);
186
 
187
        // Set frame format: asynchronous, 8data, no parity, 1stop bit
188
#ifdef URSEL1
189
        UCSR1C = (1<<URSEL1)|(3<<UCSZ10);
190
#else
191
        UCSR1C = (3<<UCSZ10);
192
#endif
193
}
194
 
195
 
196
//--------------------------------------------------------------
197
// Function: uart1_getc()
198
// Purpose:  return byte from ringbuffer
199
// Returns:  lower byte:  received byte from ringbuffer
200
//           higher byte: last receive error
201
//--------------------------------------------------------------
202
unsigned int uart1_getc(void)
203
{
204
        unsigned char tmptail;
205
        unsigned char data;
206
 
207
 
208
        if ( UART1_RxHead == UART1_RxTail )
209
        {
210
                return UART_NO_DATA;   // no data available
211
        }
212
 
213
        // calculate /store buffer index
214
        tmptail = (UART1_RxTail + 1) & UART_RX_BUFFER_MASK;
215
        UART1_RxTail = tmptail;
216
 
217
        // get data from receive buffer
218
        data = UART1_RxBuf[tmptail];
219
 
220
        return (UART1_LastRxError << 8) + data;
221
 
222
}
223
 
224
 
225
//--------------------------------------------------------------
226
// Function: uart1_putc()
227
// Purpose:  write byte to ringbuffer for transmitting via UART
228
// Input:    byte to be transmitted
229
// Returns:  1 on succes, 0 if remote not ready
230
//--------------------------------------------------------------
231
int uart1_putc(unsigned char data)
232
{
233
        unsigned char tmphead;
234
 
235
 
236
        tmphead = (UART1_TxHead + 1) & UART_TX_BUFFER_MASK;
237
 
238
        while ( tmphead == UART1_TxTail )
239
        {;}  // wait for free space in buffer
240
 
241
        UART1_TxBuf[tmphead] = data;
242
        UART1_TxHead = tmphead;
243
 
244
        // enable UDRE interrupt
245
        UART1_CONTROL |= _BV(UART1_UDRIE);
246
        return (UART1_LastRxError << 8) + data;
247
}
248
 
249
 
250
//--------------------------------------------------------------
251
// Function: uart1_puts()
252
// Purpose:  transmit string to UART1
253
// Input:    string to be transmitted
254
// Returns:  none
255
//--------------------------------------------------------------
256
void uart1_puts(const char *s )
257
{
258
        while (*s)
259
                uart1_putc(*s++);
260
}
261
 
262
 
263
//--------------------------------------------------------------
264
// Function: uart1_puts_p()
265
// Purpose:  transmit string from program memory to UART1
266
// Input:    program memory string to be transmitted
267
// Returns:  none
268
//--------------------------------------------------------------
269
void uart1_puts_p(const char *progmem_s )
270
{
271
        register char c;
272
        while ( (c = pgm_read_byte(progmem_s++)) )
273
                uart1_putc(c);
274
}
275
 
276
 
277
//--------------------------------------------------------------
278
// Function: uart1_available()
279
// Purpose:  Determine the number of bytes waiting in the receive buffer
280
// Input:    None
281
// Returns:  Integer number of bytes in the receive buffer
282
//--------------------------------------------------------------
283
int uart1_available(void)
284
{
285
        return (UART_RX_BUFFER_MASK + UART1_RxHead - UART1_RxTail) % UART_RX_BUFFER_MASK;
286
}
287
 
288
 
289
 
290
//--------------------------------------------------------------
291
// Function: uart1_flush()
292
// Purpose:  Flush bytes waiting the receive buffer.  Acutally ignores them.
293
// Input:    None
294
// Returns:  None
295
//--------------------------------------------------------------
296
void uart1_flush(void)
297
{
298
        UART1_RxHead = UART1_RxTail;
299
}
300
 
301
 
302
#endif
303