12
2025
06

串口+DMA非中断接收不定长数据

1.DMA重要知识点

单次模式时:当传输计数器减到0就停止了;还想再次启动,得先失能装载计数器的值再使能
循环模式:当减到0时会重新加载

0BDE87189A82BE15E329B6565829AD26.png

2.STM32使用串口工具高波特率发送多数据的时候,使用DMA能减少MCU的负担,并进行快速搬运数据,此代码是非中断接收不定长数据的.

Snipaste_2025-06-12_13-40-13.jpg


#include "usart.h"
void Usart_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	/* Enable GPIO clock */
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
	 

   /* Configure USARTy Rx as input floating */
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
   GPIO_Init(GPIOA, &GPIO_InitStructure);
   
   /* Configure USARTy Tx as alternate function push-pull */
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
   GPIO_Init(GPIOA, &GPIO_InitStructure);
		
   USART_InitStructure.USART_BaudRate = 115200;
   USART_InitStructure.USART_WordLength = USART_WordLength_8b;
   USART_InitStructure.USART_StopBits = USART_StopBits_1;
   USART_InitStructure.USART_Parity = USART_Parity_No;
   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
   USART_InitStructure.USART_Mode = USART_Mode_Rx |USART_Mode_Tx;
   
   /* Configure USARTy */
   USART_Init(USART1, &USART_InitStructure);
 
   /* Enable USARTy DMA TX request */
   USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
   /* Enable USARTz */
   USART_Cmd(USART1, ENABLE);

}

void Usart_send(uint8_t ch)
 {
   /* Place your implementation of fputc here */
   /* e.g. write a character to the USART */
   USART_SendData(USART1, (uint8_t) ch);
 
   /* Loop until the end of transmission */
   while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
   {}
 
 }
 
 void Usart_sendBuff(uint8_t *buf,uint32_t size)
{
	for(uint32_t i=0;i<size;i++)
	{
		Usart_send(buf[i]);
	}
}

#include "dma.h"
#include "string.h"
//M to M
/*定义数组作为DMA传输数据源
*使用const关键字修饰,使其定义为常量类型,表示数据存储在内部的FLASH中
*/
const uint32_t DMA_S_Const_Buffer[BufferSIze]={
    0x12345678,0x12345679,0x1234567A,
    0x1234567B,0x1234567C,0x1234567D,0x1234567E};

//定义DMA传输目标存储器,存储在内部的SRAM中
uint32_t DMA_D_Buffer[BufferSIze];
uint8_t DMA_D_Buffer_RX[BufferSIze];
void Dma_Config()
{
    DMA_InitTypeDef dma_InitStruct;
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
    dma_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;//当内存传内存时可看作数据的源
    dma_InitStruct.DMA_MemoryBaseAddr = (uint32_t)DMA_D_Buffer_RX;
    dma_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
    dma_InitStruct.DMA_BufferSize = BufferSIze; //传输数目
    dma_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址增量模式
    dma_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
    dma_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    dma_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    dma_InitStruct.DMA_Mode = DMA_Mode_Normal;
    dma_InitStruct.DMA_M2M = DMA_M2M_Disable;
    dma_InitStruct.DMA_Priority = DMA_Priority_High ;
    DMA_Init(DMA1_Channel5,&dma_InitStruct);

    DMA_Cmd(DMA1_Channel5, ENABLE);
	
}


uint16_t Get_Revbuf(uint8_t *buf,uint32_t size)
{
	uint16_t count=0,len=0;
	memset(buf,0,size);
	if(DMA1_Channel5->CNDTR < BufferSIze)
	{
		count = DMA1_Channel5->CNDTR ;
		delay_ms(30);
		if(count==DMA1_Channel5->CNDTR)
		{
			len = BufferSIze-count;
			for(int i=0;i<len;i++)
			{
				buf[i]=DMA_D_Buffer_RX[i];
			}
			return len;
		}
	}
	
	return 0;
}


gzh

微信扫码关注

更新实时通知

« 上一篇

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。