Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

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