ATMega128, rx\tx\cts\rts\gnd, WinAVR, прерывания, FIFO:
CODE
#ifndef _USART0_H_
#define _USART0_H_
#include "main.h"
void USART0_Initialize(void);
uint8_t USART0_ReceiveByte(void);
void USART0_TransmitByte(uint8_t data);
uint8_t USART0_IsDataReceived(void);
void USART0_Flush(void);
#endif
CODE
#include "usart0.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////
#define UART_RX_BUFFER_SIZE 128
#define UART_RX_BUFFER_MASK (UART_RX_BUFFER_SIZE - 1)
static uint8_t UART_RxBuf[UART_RX_BUFFER_SIZE];
static volatile uint8_t UART_RxHead;
static volatile uint8_t UART_RxTail;
////////////////////////////////////////////////////////////////////////////////////////////////////////
#define UART_TX_BUFFER_SIZE 128
#define UART_TX_BUFFER_MASK (UART_TX_BUFFER_SIZE - 1)
static uint8_t UART_TxBuf[UART_TX_BUFFER_SIZE];
static volatile uint8_t UART_TxHead;
static volatile uint8_t UART_TxTail;
////////////////////////////////////////////////////////////////////////////////////////////////////////
#define UART_RX_BUFFER_SIZE_4 32 // (16 + 1) bytes min
////////////////////////////////////////////////////////////////////////////////////////////////////////
#define CTSS 2 // This is CTSS# really (not CTSS)
#define RTSS 3 // This is RTSS# really (not RTSS)
////////////////////////////////////////////////////////////////////////////////////////////////////////
static uint8_t USART0_GetRxBufFreeSz(void)
{
return (UART_RxHead >= UART_RxTail? (UART_RX_BUFFER_SIZE - UART_RxHead + UART_RxTail) : (UART_RX_BUFFER_SIZE - UART_RxTail + UART_RxHead));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
static void RTS_SetHigh(void)
{
// This is RTS#, so we MUST invert signals
PORTE &= ~_BV(RTSS);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
static void RTS_SetLow(void)
{
// This is RTS#, so we MUST invert signals
PORTE |= _BV(RTSS);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
static uint8_t CTS_GetState(void)
{
// This is CTS#, so we MUST invert signals
if(PINE & _BV(CTSS)) return FALSE;
else return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//UART0 initialize
// desired baud rate: 500000
// actual: baud rate:500000 (0,0%)
// char size: 8 bit
// parity: Disabled
void USART0_Initialize(void) // initialization
{
UART_RxTail = 0; // reset buffer counters
UART_RxHead = 0;
UART_TxTail = 0;
UART_TxHead = 0;
UCSR0B = 0x00; //disable while setting baud rate
UCSR0A = 0x00;
UCSR0C = (_BV(UCSZ01) | _BV(UCSZ00));
UBRR0L = 0x01; //set baud rate lo
UBRR0H = 0x00; //set baud rate hi
UCSR0B = (_BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0));
RTS_SetHigh();
DDRE &= ~_BV(CTSS); // Configure CTS pin as input
DDRE |= _BV(RTSS); // Configure RTS pin as output
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
ISR(USART0_RX_vect) // interrupt on RXC0
{
uint8_t data;
uint8_t tmphead;
if(UCSR0A & (_BV(FE0) | _BV(DOR0))) // if any error is detected
{
data = UDR0; // just read UDR0
}
else // no errors, receive data
{
data = UDR0;
tmphead = (UART_RxHead + 1) & UART_RX_BUFFER_MASK;
UART_RxHead = tmphead;
if(USART0_GetRxBufFreeSz() < UART_RX_BUFFER_SIZE_4) // ERROR! Receive buffer could be overflown, pause dataflow
{
RTS_SetLow();
}
UART_RxBuf[tmphead] = data;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
ISR(USART0_UDRE_vect) // interrupt on UDRE0
{
if(CTS_GetState())
{
uint8_t tmptail;
if(UART_TxHead != UART_TxTail)
{
tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
UART_TxTail = tmptail;
UDR0 = UART_TxBuf[tmptail];
}
else
{
UCSR0B &= ~_BV(UDRIE0);
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
uint8_t USART0_ReceiveByte(void)
{
uint8_t data;
uint8_t tmptail;
while (UART_RxHead == UART_RxTail);
tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
UART_RxTail = tmptail;
data = UART_RxBuf[tmptail];
if(UART_RxHead == UART_RxTail) RTS_SetHigh(); // Buffer is empty now, so we can receive data again
return data;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
void USART0_TransmitByte(uint8_t data)
{
uint8_t tmphead;
tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
while (tmphead == UART_TxTail);
UART_TxBuf[tmphead] = data;
UART_TxHead = tmphead;
UCSR0B |= _BV(UDRIE0);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
uint8_t USART0_IsDataReceived(void)
{
if(UART_RxHead == UART_RxTail) return FALSE;
else return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
void USART0_Flush(void)
{
while(USART0_IsDataReceived()) USART0_ReceiveByte();
}