Ну типа так, для двух UART:
typedef struct uart_fifo_t
{
uint_fast8_t count;
uint_fast8_t rptr;
uint_fast8_t wptr;
uint8_t buffer[UART_FIFO_SIZE];
uint16_t data_mask;
} uart_fifo_t;
static USART_TypeDef * const uart_pointers[UART_PORT_COUNT] = { UART4, UART5};
static const uint32_t uart_irqs[UART_PORT_COUNT] = { UART4_IRQn, UART5_IRQn};
static uart_fifo_t rx_fifo[UART_PORT_COUNT] = {0};
static uart_fifo_t tx_fifo[UART_PORT_COUNT] = {0};
static timer_t rx_timer[UART_PORT_COUNT] = {0};
void uart_open(uint8_t uart, uint16_t baud_rate, uint8_t parity)
{
USART_TypeDef * uart_ptr;
int temp;
if (uart >= UART_PORT_COUNT)
{
return;
}
uart_ptr = uart_pointers[uart];
// запретим прерывания
NVIC->ICER[uart_irqs[uart] >> 5] = 1 << (uart_irqs[uart] & 0x1F);
(void)memset(&rx_fifo[uart], 0, sizeof(uart_fifo_t));
(void)memset(&tx_fifo[uart], 0, sizeof(uart_fifo_t));
temp = USART_CR1_UE | USART_CR1_RE | USART_CR1_TE | USART_CR1_RXNEIE;
tx_fifo[uart].data_mask = 0x0000;
switch (parity)
{
case 'E':
case 'e':
// Even parity
temp |= USART_CR1_M | USART_CR1_PCE;
break;
case 'M':
case 'm':
// Mark parity (parity bit always set)
temp |= USART_CR1_M;
tx_fifo[uart].data_mask = 0x0100;
break;
case 'O':
case 'o':
// Odd parity
temp |= USART_CR1_M | USART_CR1_PCE | USART_CR1_PS;
break;
case 'S':
case 's':
// Space parity (parity bit always cleared)
temp |= USART_CR1_M;
break;
case 'N':
case 'n':
// None parity (no parity bit at all)
default:
// unknown values, just as None
break;
}
uart_ptr->CR1 = temp;
uart_ptr->CR2 = 0;
uart_ptr->CR3 = 0;
// настроим делитель частоты
if ((USART1 == uart_ptr) || (USART6 == uart_ptr))
{
// USART 1 и 6 тактируются от вдвое более высокой частоты
temp = CPU_CLOCK / 2;
}
else
{
temp = CPU_CLOCK / 4;
}
uart_ptr->BRR = temp / baud_rate;
// разрешим прерывания uart на контроллере прерываний, приоритет 3
NVIC->IP[uart_irqs[uart]] = 3 << 5;
NVIC->ISER[uart_irqs[uart] >> 5] = 1 << (uart_irqs[uart] & 0x1F);
timer_set(rx_timer+uart, CLOCK_SECOND/10);
}
// общий обработчик для всех уартов
static void uart_isr(USART_TypeDef * uart_ptr, uart_fifo_t * rx_fifo_ptr, uart_fifo_t * tx_fifo_ptr)
{
if (uart_ptr->SR & USART_SR_RXNE)
{
rx_fifo_ptr->buffer[rx_fifo_ptr->wptr] = uart_ptr->DR;
rx_fifo_ptr->wptr = (rx_fifo_ptr->wptr + 1) & UART_FIFO_MASK;
rx_fifo_ptr->count++;
}
if (uart_ptr->SR & USART_SR_TXE)
{
if (0 == tx_fifo_ptr->count)
{
// пока нечего передавать, запретим прерывание
uart_ptr->CR1 &= ~USART_CR1_TXEIE;
}
else
{
uart_ptr->DR = tx_fifo_ptr->buffer[tx_fifo_ptr->rptr] | tx_fifo_ptr->data_mask;
tx_fifo_ptr->rptr = (tx_fifo_ptr->rptr + 1) & UART_FIFO_MASK;
tx_fifo_ptr->count--;
}
}
}
void uart4_isr(void)
{
uart_isr(UART4, rx_fifo + 0, tx_fifo + 0);
}
void uart5_isr(void)
{
uart_isr(UART5, rx_fifo + 1, tx_fifo + 1);
}
uint8_t uart_get(uint8_t uart, uint8_t * buf, uint8_t len)
{
uart_fifo_t * fifo_ptr;
int i = 0;
if (uart >= UART_PORT_COUNT)
{
return 0;
}
fifo_ptr = rx_fifo + uart;
NVIC->ICER[uart_irqs[uart] >> 5] = 1 << (uart_irqs[uart] & 0x1F);
// отправляем только если накопилось больше 7 символов или давно не отправляли
if ((fifo_ptr->count > 7) || (timer_expired(rx_timer + uart)))
{
while ((fifo_ptr->count > 0) && (i < len))
{
*buf = fifo_ptr->buffer[fifo_ptr->rptr];
fifo_ptr->rptr = (fifo_ptr->rptr + 1) & UART_FIFO_MASK;
fifo_ptr->count--;
buf++;
i++;
}
timer_restart(rx_timer + uart);
}
NVIC->ISER[uart_irqs[uart] >> 5] = 1 << (uart_irqs[uart] & 0x1F);
return i;
}
uint8_t uart_put(uint8_t uart, uint8_t * buf, uint8_t len)
{
uart_fifo_t * fifo_ptr;
int i = 0;
if ((uart >= UART_PORT_COUNT) || (len == 0))
{
return 0;
}
fifo_ptr = tx_fifo + uart;
NVIC->ICER[uart_irqs[uart] >> 5] = 1 << (uart_irqs[uart] & 0x1F);
while ((fifo_ptr->count < UART_FIFO_SIZE) && (i < len))
{
fifo_ptr->buffer[fifo_ptr->wptr] = *buf;
fifo_ptr->wptr = (fifo_ptr->wptr + 1) & UART_FIFO_MASK;
fifo_ptr->count++;
buf++;
i++;
}
// разрешим прерывание по пустому передатчику
uart_pointers[uart]->CR1 |= USART_CR1_TXEIE;
NVIC->ISER[uart_irqs[uart] >> 5] = 1 << (uart_irqs[uart] & 0x1F);
return i;
}
Не надо делать мне как лучше, оставьте мне как хорошо