之前分享了一个关于gd32的fifo框架,这次就用stm32仿照写一个,其实几乎一样,这次说的更详细点,我全文都写上了注释,大家直接cv模仿我的调用方式即可
uasrt.c
cs
#include "stm32f10x.h" // Device header
#include "queue.h"
void myDMA_init(void);
void myNVIC_Config(void);
queue_t uart1_queue_in,uart1_queue_out ; //定义2个结构体变量,分别是入、出栈
uint8_t recv_buf[256] = {0}; //接收缓冲区大小256 byte
static uint8_t send_buf[256] = {0}; //发送缓冲区大小256 byte
static uint8_t usart1_tx_buf[64];
static uint8_t uart1_send_ready = 1;
void uart1_queue_init(void)
{
queue_init(&uart1_queue_in,recv_buf,sizeof(recv_buf));//初始化压栈的缓冲区
queue_init(&uart1_queue_out,send_buf,256); //初始化出栈的缓冲区
}
/* **************************************************************************************
* 函 数 名: uart_get_queue_data
* 功能说明: 拿取uart in队列的数据
* 形 参: p_buf : 数据存储地址
* size : 拿取个数
* 返 回 值: 无
* 备 注: 无
*****************************************************************************************/
uint16_t uart1_get_queue_data(uint8_t * p_buf,uint16_t size)
{
return queue_out_data(&uart1_queue_in,p_buf,size);
}
/* **************************************************************************************
* 函 数 名: uart_get_data_len
* 功能说明: 返回uart in 队列的储存数据长度
* 形 参: 无
*
* 返 回 值: 数据长度
* 备 注: 无
*****************************************************************************************/
uint16_t uart1_get_data_len(void)
{
return queue_get_num(&uart1_queue_in);
}
/* **************************************************************************************
* 函 数 名: uart_put_queue_data
* 功能说明: 把数据压进uart out队列
* 形 参: p_buf : 数据存储地址
* size : 压的个数
* 返 回 值: 无
* 备 注: 无
*****************************************************************************************/
uint16_t uart1_put_queue_data(uint8_t * p_buf,uint16_t size)
{
return queue_in_data(&uart1_queue_out,p_buf,size);
}
/* **************************************************************************************
* 函 数 名: uart_send_poll
* 功能说明: 轮询uart out 队列并通过dma发送
* 形 参:
*
* 返 回 值: 发送数据个数
* 备 注: 无
*****************************************************************************************/
uint8_t uart0_send_poll(void)
{
uint8_t n = 0;
if(uart1_send_ready)//串口tx缓冲区是否有数据并传输完成?
{
n = queue_out_data(&uart1_queue_out,usart1_tx_buf,sizeof(usart1_tx_buf)); //计算大小
if(n)
{
uart1_send_ready=0;
DMA_Cmd(DMA1_Channel4,DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel4,n);
DMA_Cmd(DMA1_Channel4,ENABLE);
return n;
}
}
return 0;
}
void USART1_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1, ENABLE);
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); // 使能USART1的DMA发送请求(关键!)
myDMA_init();
myNVIC_Config();
uart1_queue_init();
}
void myDMA_init(void)
{
DMA_InitTypeDef DMA_InitStructure;
// 使能DMA1时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// 配置DMA1通道4(USART1_TX)
DMA_DeInit(DMA1_Channel4); // 复位DMA通道4到默认值
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; // 外设基址:USART1数据寄存器
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)usart1_tx_buf; // 内存基址:发送缓冲区
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; // 传输方向:内存到外设
DMA_InitStructure.DMA_BufferSize = 1; // 传输数据量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址不递增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 内存地址递增(因为发送多个字节)
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设数据宽度8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 内存数据宽度8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // 普通模式(非循环)
DMA_InitStructure.DMA_Priority = DMA_Priority_High; // 中等优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 非内存到内存模式
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
// 使能DMA1通道4传输完成中断
DMA_ITConfig(DMA1_Channel4, DMA_IT_TE, ENABLE);
}
void myNVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 配置DMA1_Channel4_IRQn的中断优先级
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void USART1_IRQHandler(void)
{
uint8_t Res;
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
Res = USART_ReceiveData(USART1);//接收到的数据进行入栈,压栈
queue_in_data(&uart1_queue_in,&Res,1);
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
void DMA1_Channel4_IRQHandler(void)
{
if (DMA_GetITStatus(DMA1_IT_TC4) != RESET) // 检查DMA1通道4传输完成中断标志
{
uart1_send_ready = 1;
DMA_ClearITPendingBit(DMA1_IT_TC4); // 清除中断标志
}
}
queue.c
cs
#include "queue.h"
/**
* @brief Initialize the circular queue
* @param queue: Queue
* @param buffer: Queue's buffer
* @param size: buff size
* @retval None
*/
void queue_init(queue_t *queue,uint8_t *buffer, uint16_t size)
{
queue->buffer = buffer;
queue->size = size;
queue->head = 0;
queue->tail = 0;
queue->length = 0;
queue->GetLen = 0;
queue->PutLen = 0;
}
/**
* @brief Insert element into the circular queue
* @param queue: Queue
* @param buffer: Queue's buffer
* @param count: element length
* @retval Number of elements inserted successfully
*/
uint16_t queue_in_data(queue_t *queue, const uint8_t *buffer, uint16_t count) //Zhixing Change 250430
{
uint16_t i = 0;
for(i=0; i<count; i++)
{
if(queue->GetLen == 0)
{
if(queue->PutLen == (queue->size - 1)) return i;
}
else
{
if(queue->PutLen == (queue->GetLen - 1)) return i;
}
queue->buffer[queue->PutLen++] = *buffer++;
queue->PutLen %= queue->size;
}
return i;
}
/**
* @brief Delete element from the circular queue
* @param queue: Queue
* @param buffer: Queue's buffer
* @param count: element length
* @retval Number of elements deleted successfully
*/
uint16_t queue_out_data(queue_t *queue,uint8_t *buffer, uint16_t count) //Zhixing Change 250430
{
uint16_t i = 0;
//__disable_irq();
for(i=0; i<count; i++)
{
/*if(queue->length == 0)//empty
{
__enable_irq();
return i;
}*/
if(queue->PutLen == queue->GetLen) return i;
*buffer++ = queue->buffer[queue->GetLen++];
if(queue->GetLen == queue->size) queue->GetLen = 0;
}
//__enable_irq();
return i;
}
/**
* @brief Get the remaining amount of data length from queue
* @param queue: Queue
* @retval data length
*/
uint16_t queue_get_num(queue_t *queue)
{
return queue->length;
}
/******************** (C)Copyright MidiPlus Software ********************/

