stm32---dma串口发送+fifo队列框架

之前分享了一个关于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 ********************/
相关推荐
tyl21102 小时前
凌科芯安国产安全MCU简介
单片机·嵌入式硬件·安全
郦7772 小时前
国产入门级32位单片机PY32F002A开发板
单片机·嵌入式硬件
电院工程师2 小时前
轻量级密码算法CHAM的python实现
python·嵌入式硬件·算法·安全·密码学
飞凌嵌入式3 小时前
基于RK3588,飞凌教育品牌推出嵌入式人工智能实验箱EDU-AIoT ELF 2
linux·人工智能·嵌入式硬件·arm·nxp
13631676419侯11 小时前
ESP32-C3FH4X—低功耗、高集成度的 MCU 系统级芯片 (SoC)
嵌入式硬件·智能家居·芯片
passer__jw76713 小时前
【51单片机】6. 定时器、按键切换流水灯&时钟Demo
单片机·51单片机
Wendy_robot13 小时前
【零基础勇闯嵌入式岗】从单片机低功耗中获得的启发
c++·单片机·嵌入式硬件
学习噢学个屁14 小时前
基于STM32汽车温度空调控制系统
c语言·stm32·单片机·嵌入式硬件·汽车
郦77714 小时前
价格性价比高系列的高性能单片机MS32C001-C
单片机·嵌入式硬件
iCxhust14 小时前
汇编字符串比较函数
c语言·开发语言·汇编·单片机·嵌入式硬件