📄 uart.c
字号:
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avrx/avrx.h>
#include "hardware.h"
#include "uart.h"
// USART Receiver buffer
uint8_t rx_buffer[RX_BUFFER_SIZE];
uint8_t volatile rx_wr, rx_count;
uint8_t rx_rd;
Mutex rx_rdy;
// This flag is set on USART Receiver buffer overflow
uint8_t rx_buffer_overflow;
// USART Transmitter buffer
uint8_t tx_buffer[TX_BUFFER_SIZE];
uint8_t tx_wr;
uint8_t volatile tx_rd, tx_count;
Mutex tx_rdy;
// USART Receiver interrupt service routine
AVRX_SIGINT(SIG_UART_RECV)
{
uint8_t status, data;
IntProlog();
status = UCSRA;
data = UDR;
if ((status & (_BV(FE) | _BV(PE) | _BV(DOR))) == 0)
{
rx_buffer[rx_wr] = data;
if (++rx_wr == RX_BUFFER_SIZE)
{
rx_wr = 0;
}
if (++rx_count == RX_BUFFER_SIZE)
{
rx_count = 0;
rx_buffer_overflow = 1;
}
else
{
AvrXIntSetSemaphore(&rx_rdy);
}
}
Epilog();
}
// USART Transmitter interrupt service routine
AVRX_SIGINT(SIG_UART_TRANS)
{
IntProlog();
if (tx_count)
{
UDR = tx_buffer[tx_rd];
if (++tx_rd == TX_BUFFER_SIZE) tx_rd = 0;
--tx_count;
AvrXIntSetSemaphore(&tx_rdy);
}
Epilog();
}
int
UartGetc(void)
{
uint8_t data;
if (0 == rx_count)
{
AvrXWaitSemaphore(&rx_rdy);
}
data = rx_buffer[rx_rd];
if (++rx_rd == RX_BUFFER_SIZE)
{
rx_rd = 0;
}
BeginCritical();
if (0 == --rx_count)
{
AvrXResetSemaphore(&rx_rdy);
}
EndCritical();
return data;
}
int
UartPutc(char c)
{
if (tx_count == TX_BUFFER_SIZE)
{
AvrXWaitSemaphore(&tx_rdy);
}
BeginCritical();
if (tx_count || bit_is_clear(UCSRA, UDRE))
{
tx_buffer[tx_wr] = c;
if (++tx_wr == TX_BUFFER_SIZE)
{
tx_wr = 0;
}
if (++tx_count == TX_BUFFER_SIZE)
{
AvrXResetSemaphore(&tx_rdy);
}
}
else
{
UDR = c;
}
EndCritical();
return 0;
}
void
UartInit(void)
{
uint32_t uart_param;
AvrXResetSemaphore(&rx_rdy);
AvrXResetSemaphore(&tx_rdy);
uart_param = UART_DEFAULT_DATABITS;
UartIOCtl(UART_SETDATABITS, &uart_param);
uart_param = UART_DEFAULT_PARITY;
UartIOCtl(UART_SETPARITY, &uart_param);
uart_param = UART__DEFAULT_STOPBITS;
UartIOCtl(UART_SETSTOPBITS, &uart_param);
uart_param = UART_DEFAULT_BAUD;
UartIOCtl(UART_SETSPEED, &uart_param);
UCSRB = BV(RXCIE) | BV(TXCIE) | BV(RXEN) | BV(TXEN);
fdevopen(UartPutc, UartGetc, 0);
}
void
UartIOCtl(uint16_t req, void *conf)
{
uint32_t *lvp = (uint32_t *)conf;
uint32_t lv = *lvp;
uint8_t bv = (uint8_t)lv;
uint16_t sv;
switch (req)
{
case UART_SETSPEED:
{
sv = (uint16_t) ((((2UL * CPUCLK) / (lv * 16UL)) + 1UL) / 2UL) - 1;
UBRRL = (uint8_t) sv;
UBRRH = (uint8_t) (sv >> 8);
}
break;
case UART_GETSPEED:
{
sv = ((uint16_t)UBRRH << 8) || UBRRL;
*lvp = CPUCLK / (16UL * (uint32_t)(sv + 1));
}
break;
case UART_SETDATABITS:
{
if (bv >= 5 && bv <= 8)
{
bv = (bv - 5) << 1;
UCSRC = (UCSRC & 0xF9) | bv;
UCSRB &= 0xFB;
}
}
break;
case UART_GETDATABITS:
{
*lvp = ((UCSRC & 0x06) >> 1) + 5;
}
break;
case UART_SETPARITY:
{
if (bv <= 2)
{
if (bv == 1) bv = 3;
bv <<= 4;
UCSRC = (UCSRC & 0xCF) | bv;
}
}
break;
case UART_GETPARITY:
{
bv = (UCSRC & 0x30) >> 4;
if (bv == 3) bv = 1;
}
break;
case UART_SETSTOPBITS:
{
if (bv == 1 || bv == 2)
{
bv = (bv - 1) << 3;
UCSRC = (UCSRC & 0xF7) | bv;
}
}
break;
case UART_GETSTOPBITS:
{
*lvp = ((UCSRC & 0x08) >> 3) + 1;
}
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -