-
Notifications
You must be signed in to change notification settings - Fork 1
/
usart.c
88 lines (77 loc) · 2.55 KB
/
usart.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/***************************************************************************
* Atmel AVR USART Library for GCC
* Version: 1.0
*
* Works with AVR MCUs equiped with USART hardware (ATmega series).
* Does not work with older UART's or USI of ATtiny series.
* Tested with ATmega8.
*
* Uses USART Receive Complete Interrupt. Disabling Global Interrupts
* after usart initialization disables data receive.
*
* Jaakko Ala-Paavola 2003/06/28
* http://www.iki.fi/jap email:[email protected]
*/
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <string.h>
#include "usart.h"
char usart_buffer[USART_BUFFER_SIZE];
unsigned char usart_buffer_pos_first = 0, usart_buffer_pos_last = 0;
volatile unsigned char usart_buffer_overflow = 0;
void usart_init(unsigned char baud_divider) {
// Baud rate selection
UBRRH = 0x00;
UBRRL = baud_divider;
// USART setup
UCSRA = 0x02; // 0000 0010
// U2X enabled
UCSRC = 0x86; // 1000 0110
// Access UCSRC, Asyncronous 8N1
UCSRB = 0x98; // 1001 1000
// Receiver enabled, Transmitter enabled
// RX Complete interrupt enabled
sei(); // Enable interrupts globally
}
void usart_putc(char data) {
while (!(UCSRA & 0x20)); // Wait untill USART data register is empty
// Transmit data
UDR = data;
}
void usart_puts(char *data) {
int len, count;
len = strlen(data);
for (count = 0; count < len; count++)
usart_putc(*(data+count));
}
char usart_getc(void) {
// Wait untill unread data in ring buffer
if (!usart_buffer_overflow)
while(usart_buffer_pos_first == usart_buffer_pos_last);
usart_buffer_overflow = 0;
// Increase first pointer
if (++usart_buffer_pos_first >= USART_BUFFER_SIZE)
usart_buffer_pos_first = 0;
// Get data from the buffer
return usart_buffer[usart_buffer_pos_first];
}
unsigned char usart_unread_data(void) {
if (usart_buffer_overflow)
return USART_BUFFER_SIZE;
if (usart_buffer_pos_last > usart_buffer_pos_first)
return usart_buffer_pos_last - usart_buffer_pos_first;
if (usart_buffer_pos_last < usart_buffer_pos_first)
return USART_BUFFER_SIZE-usart_buffer_pos_first
+ usart_buffer_pos_last;
return 0;
}
SIGNAL(SIG_UART_RECV) {
// Increase last buffer
if (++usart_buffer_pos_last >= USART_BUFFER_SIZE)
usart_buffer_pos_last = 0;
if (usart_buffer_pos_first == usart_buffer_pos_last)
usart_buffer_overflow++;
// Put data to the buffer
usart_buffer[usart_buffer_pos_last] = UDR;
}