-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUSART_V1.c
388 lines (326 loc) · 11.3 KB
/
USART_V1.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
/*
* USART.c
* Copyright by Peter Fleury (C)
* Created: 22-12-2017
* Adapted By Author : Norlinux
*http://www.microelectronic.pt
*http://maquina.96.lt
*https://www.facebook.com/MundoDosMicrocontroladores/
*Released under GPLv3.
*Please refer to LICENSE file for licensing information.
*which can be found at http://www.gnu.org/licenses/gpl.txt
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/atomic.h>
#include <stdio.h> /* Include for printf */
#include <avr/sfr_defs.h> //para bit especiais
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#include "USART_V1.h"
/*-----------------------------------------------------------------------------*/
//Adapted for printf(check at the end of this file )
#define WS_UCSR0A UCSR0A
#define WS_UDR0 UDR0
static int uart_putchar(char c, FILE *stream); //Add custom putchar function
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,_FDEV_SETUP_WRITE);
/*----------------------------------------------------------------------------*/
//#define ATMEGA_USART0
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
/*************************************************************************
Function: uart0_init()
Purpose: initialize UART and set baudrate
Input: baudrate using macro UART_BAUD_SELECT()
Returns: none
**************************************************************************/
void uart0_init(uint16_t baudrate)
{
ATOMIC_BLOCK(ATOMIC_FORCEON) {
UART_TxHead = 0;
UART_TxTail = 0;
UART_RxHead = 0;
UART_RxTail = 0;
}
/* Set baud rate */
if (baudrate & 0x8000) {
UART0_STATUS = (1<<U2X0); //Enable 2x speed
baudrate &= ~0x8000;
}
UBRR0H = (uint8_t)(baudrate>>8);
UBRR0L = (uint8_t) baudrate;
/* Enable USART receiver and transmitter and receive complete interrupt */
UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
UCSR0C = (3<<UCSZ00);
stdout = &mystdout; //Must add
sei();
} /* uart0_init */
/* Another way to init Uart*/
void USART_Init_baud(uint16_t ubrr_value)
{
//Set Baud rate
UBRR0L = ubrr_value;
UBRR0H = (ubrr_value>>8);
/*Set Frame Format
>> Asynchronous mode
>> No Parity
>> 1 StopBit
>> char size 8
*/
UART0_STATUS = (1<<U2X0); //Enable 2x speed
//UCSR0A=(1<<U2X0); // dobro velocidade
/* Enable USART receiver and transmitter and receive complete interrupt */
UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
//UCSR0C=(1<<UCSZ01)|(1<<UCSZ00); // MODO ASSINCRONO, SEM PARIDADE 1 STOP BIT, 8 BITS DADOS
UCSR0C = (3<<UCSZ00);
stdout = &mystdout; //Must add
sei();
}
/***************************************************************************************************
void UART_SetBaudRate(uint32_t v_baudRate_u32)
***************************************************************************************************
* I/P Arguments: uint32_t : v_baudRate_u32 to be configured.
* Return value : none
* description :This function is used to Set/Change the baudrate on the fly.
If the requested baud rate is not within the supported range then
the default baudrate of 9600 is set.
Refer uart.h file for Supported range of baud rates.
***************************************************************************************************/
void UART_SetBaudRate(uint32_t v_baudRate_u32)
{
uint16_t RegValue;
if((v_baudRate_u32 >= C_MinBaudRate_U32) && (v_baudRate_u32<=C_MaxBaudRate_U32))
{
/* Check if the requested baudate is within range,
If yes then calculate the value to be loaded into baud rate generator. */
RegValue = M_GetBaudRateGeneratorValue(v_baudRate_u32);
}
else
{
/* Invalid baudrate requested, hence set it to default baudrate of 9600 */
RegValue = M_GetBaudRateGeneratorValue(9600);
}
UBRR0L = util_ExtractByte0to8(RegValue);
UBRR0H = util_ExtractByte8to16(RegValue);
}
/***************************************************************************************************
void UART_Init(uint32_t v_baudRate_u32)
****************************************************************************************************
* I/P Arguments: uint32_t : Baudrate to be configured.
* Return value : none
* description :This function is used to initialize the UART at specified baud rate.
If the requested baud rate is not within the supported range then
the default baud rate of 9600 is set.
Refer uart.h file for Supported(range) baud rates.
***************************************************************************************************/
void USART_Init(uint32_t v_baudRate_u32)
{
ATOMIC_BLOCK(ATOMIC_FORCEON) {
UART_TxHead = 0;
UART_TxTail = 0;
UART_RxHead = 0;
UART_RxTail = 0;
}
UART0_STATUS = (1<<U2X0); //Enable 2x speed
UCSR0B= _BV(RXCIE0)| (1<<RXEN) | (1<<TXEN); // Enable Receiver and Transmitter
UCSR0C= (1<<UCSZ1) | (1<<UCSZ0); // Async-mode
UART_SetBaudRate(v_baudRate_u32);
}
ISR(UART0_RECEIVE_INTERRUPT)
/*************************************************************************
Function: UART Receive Complete interrupt
Purpose: called when the UART has received a character
**************************************************************************/
{
uint16_t tmphead;
uint8_t data;
uint8_t usr;
uint8_t lastRxError;
/* read UART status register and UART data register */
usr = UART0_STATUS;
data = UART0_DATA;
lastRxError = (usr & (_BV(FE0)|_BV(DOR0)));
/* calculate buffer index */
tmphead = (UART_RxHead + 1) & UART_RX0_BUFFER_MASK;
if (tmphead == UART_RxTail) {
/* error: receive buffer overflow */
lastRxError = UART_BUFFER_OVERFLOW >> 8;
} else {
/* store new index */
UART_RxHead = tmphead;
/* store received data in buffer */
UART_RxBuf[tmphead] = data;
}
UART_LastRxError = lastRxError;
}
ISR(UART0_TRANSMIT_INTERRUPT)
/*************************************************************************
Function: UART Data Register Empty interrupt
Purpose: called when the UART is ready to transmit the next byte
**************************************************************************/
{
uint16_t tmptail;
if (UART_TxHead != UART_TxTail) {
/* calculate and store new buffer index */
tmptail = (UART_TxTail + 1) & UART_TX0_BUFFER_MASK;
UART_TxTail = tmptail;
/* get one byte from buffer and write it to UART */
UART0_DATA = UART_TxBuf[tmptail]; /* start transmission */
} else {
/* tx buffer empty, disable UDRE interrupt */
UART0_CONTROL &= ~_BV(UART0_UDRIE);
}
}
/*************************************************************************
Function: uart0_getc()
Purpose: return byte from ringbuffer
Returns: lower byte: received byte from ringbuffer
higher byte: last receive error
**************************************************************************/
uint16_t uart0_getc(void)
{
uint16_t tmptail;
uint8_t data;
ATOMIC_BLOCK(ATOMIC_FORCEON) {
if (UART_RxHead == UART_RxTail) {
return UART_NO_DATA; /* no data available */
}
}
/* calculate / store buffer index */
tmptail = (UART_RxTail + 1) & UART_RX0_BUFFER_MASK;
UART_RxTail = tmptail;
/* get data from receive buffer */
data = UART_RxBuf[tmptail];
return (UART_LastRxError << 8) + data;
} /* uart0_getc */
/*************************************************************************
Function: uart0_putc()
Purpose: write byte to ringbuffer for transmitting via UART
Input: byte to be transmitted
Returns: none
**************************************************************************/
void uart0_putc(uint8_t data)
{
uint16_t tmphead;
tmphead = (UART_TxHead + 1) & UART_TX0_BUFFER_MASK;
while (tmphead == UART_TxTail); /* wait for free space in buffer */
UART_TxBuf[tmphead] = data;
UART_TxHead = tmphead;
/* enable UDRE interrupt */
UART0_CONTROL |= _BV(UART0_UDRIE);
} /* uart0_putc */
/*************************************************************************
Function: uart0_puts()
Purpose: transmit string to UART
Input: string to be transmitted
Returns: none
**************************************************************************/
void uart0_puts(const char *s)
{
while (*s) {
uart0_putc(*s++);
}
} /* uart0_puts */
/*************************************************************************
Function: uart0_puts_p()
Purpose: transmit string from program memory to UART
Input: program memory string to be transmitted
Returns: none
**************************************************************************/
void uart0_puts_p(const char *progmem_s)
{
register char c;
while ((c = pgm_read_byte(progmem_s++))) {
uart0_putc(c);
}
} /* uart0_puts_p */
/*************************************************************************
Function: uart0_available()
Purpose: Determine the number of bytes waiting in the receive buffer
Input: None
Returns: Integer number of bytes in the receive buffer
**************************************************************************/
uint16_t uart0_available(void)
{
uint16_t ret;
ATOMIC_BLOCK(ATOMIC_FORCEON) {
ret = (UART_RX0_BUFFER_SIZE + UART_RxHead - UART_RxTail) & UART_RX0_BUFFER_MASK;
}
return ret;
} /* uart0_available */
/*************************************************************************
Function: uart0_flush()
Purpose: Flush bytes waiting the receive buffer. Actually ignores them.
Input: None
Returns: None
**************************************************************************/
void uart0_flush(void)
{
ATOMIC_BLOCK(ATOMIC_FORCEON) {
UART_RxHead = UART_RxTail;
}
} /* uart0_flush */
/*************************************************************************
Function: uart_putchar()
Purpose: From RS232 sends a byte
Input: None
Returns: None
**************************************************************************/
static int uart_putchar(char c, FILE *stream)
{
if (c == '\n')
uart_putchar('\r', stream);
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = c;
return 0;
}
void putUsart0(unsigned char c)
{
while(!(WS_UCSR0A & 0x20));
WS_UDR0 = c;
}
//From receiving a RS232 bytes
unsigned int getUsart0(void)
{
unsigned char status,res;
if(!(WS_UCSR0A & 0x80)) return 0xFFFF; //no data to be received
status = WS_UCSR0A;
res = WS_UDR0;
if (status & 0x1c) return 0xFFFF; // If error, return 0xFFFF
return res;
}
//Waiting for receiving a from RS232 effective bytes
unsigned char waitUsart0(void)
{
unsigned int c;
while((c=getUsart0())==0xFFFF);
return (unsigned char)c;
}
/*************************************************************************
Function: FOR ESP8266 Project by @author Norlinux
**************************************************************************/
// New Functions for ESP8266 Project
void ESP8266_Send(uint8_t* DataArray, uint16_t count) {
/* Go through entire data array */
while (count--) {
/* Wait to be ready, buffer empty */
//uart0_flush();
/* Send data */
uart0_putc(*DataArray++);
/* Wait to be ready, buffer empty */
uart0_flush();
}
}
//void ESP8266_Send(uint8_t* DataArray, uint16_t count) {
//while (count--) {
//uart0_flush();
//uart0_putc(*DataArray++);
//}
//}