Files
2024-02-29 00:45:47 +08:00

529 lines
16 KiB
C

#include "uart_fifo.h"
#include "ch32v20x.h"
#include <stdlib.h>
void uart_fifo_init(uart_fifo_t *fifo, USART_TypeDef *uart,
uint32_t mode_rx, uint32_t mode_tx)
{
fifo->UART = uart;
fifo->mode_rx = mode_rx;
fifo->mode_tx = mode_tx;
fifo->buffer_rx = NULL;
fifo->buffer_tx = NULL;
fifo->buffer_rx_len = 0;
fifo->buffer_tx_len = 0;
}
void uart_fifo_config(uart_fifo_t *fifo, uint32_t baud,
uint8_t wordlen, uint8_t stopbit, uint8_t parity,
size_t buff_rx_len, size_t buff_tx_len)
{
uint16_t WordLength = USART_WordLength_8b;
uint16_t StopBit = USART_StopBits_1;
uint16_t Parity = USART_Parity_No;
GPIO_InitTypeDef GPIO_InitStructure = {0};
USART_InitTypeDef USART_InitStructure = {0};
DMA_InitTypeDef DMA_InitStructure = {0};
NVIC_InitTypeDef NVIC_InitStructure = {0};
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
if (fifo->buffer_rx)
free(fifo->buffer_rx);
if (fifo->buffer_tx)
free(fifo->buffer_tx);
fifo->buffer_rx = (uint8_t *)malloc(buff_rx_len);
fifo->buffer_tx = (uint8_t *)malloc(buff_tx_len);
fifo->buffer_rx_len = buff_rx_len;
fifo->buffer_tx_len = buff_tx_len;
fifo->buffer_tx_len_2 = buff_tx_len / 2;
USART_Cmd(fifo->UART, DISABLE);
switch (wordlen)
{
case 9:
WordLength = USART_WordLength_9b;
break;
default:
WordLength = USART_WordLength_8b;
break;
}
switch (stopbit)
{
case 2:
StopBit = USART_StopBits_2;
break;
default:
StopBit = USART_StopBits_1;
break;
}
switch (parity)
{
case 1:
Parity = USART_Parity_Odd;
break;
case 2:
Parity = USART_Parity_Even;
break;
default:
Parity = USART_Parity_No;
break;
}
USART_InitStructure.USART_BaudRate = baud;
USART_InitStructure.USART_WordLength = WordLength;
USART_InitStructure.USART_StopBits = StopBit;
USART_InitStructure.USART_Parity = Parity;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(fifo->UART, &USART_InitStructure);
if (fifo->buffer_rx_len || fifo->mode_rx == UART_FIFO_BLOCK)
{
switch (fifo->mode_rx)
{
case UART_FIFO_DMA:
{
DMA_InitTypeDef DMA_InitStructure = {0};
DMA_DeInit(fifo->dma_channelx_rx);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&fifo->UART->DATAR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)fifo->buffer_rx;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = fifo->buffer_rx_len;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(fifo->dma_channelx_rx, &DMA_InitStructure);
}
break;
default:
break;
}
}
else
{
//usart_receive_config(com, USART_RECEIVE_DISABLE);
}
if (fifo->buffer_tx_len || fifo->mode_tx == UART_FIFO_BLOCK)
{
switch (fifo->mode_tx)
{
case UART_FIFO_DMA:
{
DMA_InitTypeDef DMA_InitStructure = {0};
DMA_DeInit(fifo->dma_channelx_tx);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&fifo->UART->DATAR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)fifo->buffer_tx;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = fifo->buffer_tx_len;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(fifo->dma_channelx_tx, &DMA_InitStructure);
}
break;
default:
break;
}
}
else
{
//usart_transmit_config(com, USART_TRANSMIT_DISABLE);
}
}
void uart_fifo_open(uart_fifo_t *fifo)
{
fifo->byt_rx = 0;
fifo->byt_tx = 0;
fifo->pkg_rx = 0;
fifo->pkg_tx = 0;
fifo->last_byt_rx = 0;
fifo->last_byt_tx = 0;
fifo->last_pkg_rx = 0;
fifo->last_pkg_tx = 0;
fifo->Bps_rx = 0;
fifo->Pps_rx = 0;
fifo->Bps_tx = 0;
fifo->Pps_tx = 0;
fifo->err_rx = 0;
fifo->err_tx = 0;
fifo->buffer_rx_max = 0;
fifo->buffer_tx_max = 0;
NVIC_InitTypeDef NVIC_InitStructure = {0};
NVIC_InitStructure.NVIC_IRQChannel = fifo->nvic_irq;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=fifo->nvic_irq_pre_priority;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=fifo->nvic_irq_sub_priority;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_ITConfig(fifo->UART, USART_IT_IDLE, ENABLE);
switch (fifo->mode_rx)
{
case UART_FIFO_IT:
if (fifo->buffer_rx_len)
{
fifo->buffer_rx_head = 0;
fifo->buffer_rx_tail = 0;
USART_ITConfig(fifo->UART, USART_IT_RXNE, ENABLE);
}
break;
case UART_FIFO_DMA:
if (fifo->buffer_rx_len)
{
DMA_Cmd(fifo->dma_channelx_rx, ENABLE);
USART_DMACmd(fifo->UART, USART_DMAReq_Rx, ENABLE);
}
break;
default:
break;
}
switch (fifo->mode_tx)
{
case UART_FIFO_IT:
fifo->buffer_tx_head = 0;
fifo->buffer_tx_tail = 0;
break;
case UART_FIFO_DMA:
fifo->buffer_tx_head = 0;
fifo->buffer_tx_tail = 0; /* 0-not_sending; 1-sending */
break;
default:
break;
}
USART_Cmd(fifo->UART, ENABLE);
}
void uart_fifo_close(uart_fifo_t *fifo)
{
USART_Cmd(fifo->UART, DISABLE);
switch (fifo->mode_rx)
{
case UART_FIFO_IT:
USART_ITConfig(fifo->UART, USART_IT_RXNE, DISABLE);
break;
case UART_FIFO_DMA:
USART_DMACmd(fifo->UART, USART_DMAReq_Tx, DISABLE);
DMA_Cmd(fifo->dma_channelx_rx, DISABLE);
break;
default:
break;
}
switch (fifo->mode_tx)
{
case UART_FIFO_IT:
USART_ITConfig(fifo->UART, USART_IT_TXE, DISABLE);
break;
case UART_FIFO_DMA:
USART_DMACmd(fifo->UART, USART_DMAReq_Tx, DISABLE);
DMA_Cmd(fifo->dma_channelx_tx, DISABLE);
break;
default:
break;
}
USART_ITConfig(fifo->UART, USART_IT_IDLE, DISABLE);
NVIC_DisableIRQ(fifo->nvic_irq);
fifo->buffer_rx_len = 0;
fifo->buffer_tx_len = 0;
}
void uart_fifo_iqr(uart_fifo_t *fifo)
{
if (RESET != USART_GetITStatus(fifo->UART, USART_IT_RXNE))
{
USART_ClearITPendingBit(fifo->UART, USART_IT_RXNE);
/* Read one byte from the receive data register */
fifo->buffer_rx[fifo->buffer_rx_head++] = (uint8_t)USART_ReceiveData(fifo->UART);
fifo->byt_rx++;
if (fifo->buffer_rx_head >= fifo->buffer_rx_len)
{
fifo->buffer_rx_head = 0;
}
}
if (RESET != USART_GetITStatus(fifo->UART, USART_IT_TXE))
{
USART_ClearITPendingBit(fifo->UART, USART_IT_TXE);
/* Write one byte to the transmit data register */
USART_SendData(fifo->UART, fifo->buffer_tx[fifo->buffer_tx_tail++]);
fifo->byt_tx++;
if (fifo->buffer_tx_tail >= fifo->buffer_tx_len)
{
fifo->buffer_tx_tail = 0;
}
if (fifo->buffer_tx_tail == fifo->buffer_tx_head)
{
/* disable the USARTx transmit interrupt */
USART_ITConfig(fifo->UART, USART_IT_TXE,DISABLE);
}
}
if ((RESET != USART_GetITStatus(fifo->UART, USART_IT_IDLE)))
{
USART_ClearITPendingBit(fifo->UART, USART_IT_IDLE);
USART_ReceiveData(fifo->UART);
fifo->pkg_rx++;
}
}
void uart_fifo_write(uart_fifo_t *fifo, const uint8_t *buff, size_t len)
{
fifo->pkg_tx++;
switch (fifo->mode_tx)
{
case UART_FIFO_DMA:
if (fifo->buffer_tx_len)
{
for (size_t i = 0; i < len; ++i)
{
fifo->buffer_tx[fifo->buffer_tx_head++] = buff[i];
if (fifo->buffer_tx_head == fifo->buffer_tx_len_2)
{
fifo->buffer_tx_head = fifo->buffer_tx_len_2 - 1;
}
else if (fifo->buffer_tx_head >= fifo->buffer_tx_len)
{
fifo->buffer_tx_head = fifo->buffer_tx_len - 1;
}
}
if (SET == DMA_GetFlagStatus(DMA1_FLAG_TC1))
{
DMA_ClearFlag(DMA1_FLAG_TC1);
fifo->buffer_tx_tail = 0;
}
if (SET == DMA_GetFlagStatus(DMA1_IT_TE1))
{
DMA_ClearFlag(DMA1_IT_TE1);
fifo->err_tx++;
fifo->buffer_tx_tail = 0;
}
if (fifo->buffer_tx_tail == 0)
{
DMA_Cmd(fifo->dma_channelx_tx,DISABLE);
if (fifo->buffer_tx_head == 0 || fifo->buffer_tx_head == fifo->buffer_tx_len_2)
{
fifo->buffer_tx_tail = 0;
}
else
{
if (fifo->buffer_tx_head < fifo->buffer_tx_len_2)
{
//dma_memory_address_config(fifo->dma_periph, fifo->dma_channelx_tx, DMA_MEMORY_0, (uint32_t)fifo->buffer_tx); //设置要发送数据的内存地址
fifo->dma_channelx_tx->MADDR = (uint32_t)fifo->buffer_tx;
if (fifo->buffer_tx_head > fifo->buffer_tx_max)
{
fifo->buffer_tx_max = fifo->buffer_tx_head;
}
DMA_SetCurrDataCounter(fifo->dma_channelx_tx, fifo->buffer_tx_head); //一共发多少个数据
fifo->buffer_tx_head = fifo->buffer_tx_len_2;
}
else
{
//dma_memory_address_config(fifo->dma_periph, fifo->dma_channelx_tx, DMA_MEMORY_0, (uint32_t)&fifo->buffer_tx[fifo->buffer_tx_len_2]);
fifo->dma_channelx_tx->MADDR = (uint32_t)&fifo->buffer_tx[fifo->buffer_tx_len_2];
uint32_t blen = fifo->buffer_tx_head - fifo->buffer_tx_len_2;
if (blen > fifo->buffer_tx_max)
{
fifo->buffer_tx_max = blen;
}
DMA_SetCurrDataCounter(fifo->dma_channelx_tx, blen); //一共发多少个数据
fifo->buffer_tx_head = 0;
}
USART_DMACmd(fifo->UART, USART_DMAReq_Tx, ENABLE);
DMA_Cmd(fifo->dma_channelx_tx, ENABLE);
fifo->buffer_tx_tail = 1;
}
}
}
break;
case UART_FIFO_IT:
if (fifo->buffer_tx_len)
{
for (size_t i = 0; i < len; ++i)
{
fifo->buffer_tx[fifo->buffer_tx_head++] = buff[i];
if (fifo->buffer_tx_head >= fifo->buffer_tx_len)
{
fifo->buffer_tx_head = 0;
}
}
int blen = fifo->buffer_tx_head - fifo->buffer_tx_tail;
if (blen < 0)
{
blen += fifo->buffer_tx_len;
}
if (blen > fifo->buffer_tx_max)
{
fifo->buffer_tx_max = blen;
}
if (fifo->buffer_tx_tail != fifo->buffer_tx_head)
{
/* enable the USARTx transmit interrupt */
USART_ITConfig(fifo->UART, USART_IT_TXE, ENABLE);
}
}
break;
default:
for (size_t i = 0; i < len; ++i)
{
USART_SendData(fifo->UART, buff[i]);
while (RESET == USART_GetFlagStatus(fifo->UART, USART_IT_TXE))
;
}
break;
}
}
size_t uart_fifo_read(uart_fifo_t *fifo, uint8_t *buff, size_t len)
{
size_t i = 0;
int blen;
switch (fifo->mode_rx)
{
case UART_FIFO_DMA:
if (fifo->buffer_rx_len)
{
/*
if (SET == DMA_GetFlagStatus(fifo->dma_channelx_rx), DMA_FLAG_FEE))
{
dma_flag_clear(fifo->dma_periph, fifo->dma_channelx_rx, DMA_FLAG_FEE);
fifo->err_rx++;
}
if (SET == dma_flag_get(fifo->dma_periph, fifo->dma_channelx_rx, DMA_FLAG_TAE))
{
dma_flag_clear(fifo->dma_periph, fifo->dma_channelx_rx, DMA_FLAG_TAE);
fifo->err_rx++;
}
if (SET == dma_flag_get(fifo->dma_periph, fifo->dma_channelx_rx, DMA_FLAG_SDE))
{
dma_flag_clear(fifo->dma_periph, fifo->dma_channelx_rx, DMA_FLAG_SDE);
fifo->err_rx++;
}
*/
if (SET == DMA_GetFlagStatus(DMA1_FLAG_TC1))
{
DMA_ClearFlag(DMA1_FLAG_TC1);
}
if (SET == DMA_GetFlagStatus(DMA1_IT_TE1))
{
DMA_ClearFlag(DMA1_IT_TE1);
fifo->err_rx++;
}
fifo->buffer_rx_head = fifo->buffer_rx_len - DMA_GetCurrDataCounter(fifo->dma_channelx_rx);
blen = fifo->buffer_rx_head - fifo->buffer_rx_tail;
if (blen < 0)
{
blen += fifo->buffer_rx_len;
}
if (blen > fifo->buffer_rx_max)
{
fifo->buffer_rx_max = blen;
}
for (; i < len; ++i)
{
if (fifo->buffer_rx_tail != fifo->buffer_rx_head)
{
buff[i] = fifo->buffer_rx[fifo->buffer_rx_tail++];
fifo->byt_rx++;
if (fifo->buffer_rx_tail >= fifo->buffer_rx_len)
{
fifo->buffer_rx_tail = 0;
}
}
else
break;
}
}
break;
case UART_FIFO_IT:
if (fifo->buffer_rx_len)
{
blen = fifo->buffer_rx_head - fifo->buffer_rx_tail;
if (blen < 0)
{
blen += fifo->buffer_rx_len;
}
if (blen > fifo->buffer_rx_max)
{
fifo->buffer_rx_max = blen;
}
for (; i < len; ++i)
{
if (fifo->buffer_rx_tail != fifo->buffer_rx_head)
{
buff[i] = fifo->buffer_rx[fifo->buffer_rx_tail++];
if (fifo->buffer_rx_tail >= fifo->buffer_rx_len)
{
fifo->buffer_rx_tail = 0;
}
}
else
break;
}
}
break;
default:
for (; i < len; ++i)
{
while (RESET == USART_GetFlagStatus(fifo->UART, USART_FLAG_RXNE))
;
buff[i] = USART_ReceiveData(fifo->UART);
}
break;
}
return i;
}
void uart_fifo_stats(uart_fifo_t *fifo)
{
fifo->Bps_rx = fifo->byt_rx - fifo->last_byt_rx;
fifo->last_byt_rx = fifo->byt_rx;
fifo->Pps_rx = fifo->pkg_rx - fifo->last_pkg_rx;
fifo->last_pkg_rx = fifo->pkg_rx;
fifo->Bps_tx = fifo->byt_tx - fifo->last_byt_tx;
fifo->last_byt_tx = fifo->byt_tx;
fifo->Pps_tx = fifo->pkg_tx - fifo->last_pkg_tx;
fifo->last_pkg_tx = fifo->pkg_tx;
}