STM32 使用DMA接收不定长数据

本文详细介绍了STM32微控制器使用DMA进行串口通信的实现方法,包括USART初始化、DMA配置、中断处理和数据收发过程。通过具体代码示例,展示了如何设置GPIO、USART、DMA和NVIC等模块,实现高效稳定的串口数据传输。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#define  MCU_TX     GPIO_Pin_9
#define  MCU_RX     GPIO_Pin_10 

#define  USARTCOM                 USART1
#define  Clock                    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE)
#define  USART_IRQ                USART1_IRQn
#define  USART_IRQHandler         USART1_IRQHandler
#define  USART_RX_DMA_CHANNEL     DMA1_Channel5

#define  BUF_SIZE                 0xFF
char USART_RX_BUF[BUF_SIZE];

//USART初始化
extern void USARTInit(uint32_t BaudRate)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    GPIO_InitStructure.GPIO_Pin   = MCU_TX;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   = MCU_RX;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = RS485_CTL ;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    Clock;
    USART_DeInit(USARTCOM);//串口默认配置 波特率9600 数据位8 停止位 无,控制位 NONE
    USART_StructInit(&USART_InitStructure);
    USART_InitStructure.USART_BaudRate = BaudRate;    
    USART_Init(USARTCOM, &USART_InitStructure);    
    USART_ITConfig(USARTCOM, USART_IT_RXNE, ENABLE);
    USART_ITConfig(USARTCOM, USART_IT_IDLE, ENABLE);
    USART_Cmd(USARTCOM, ENABLE);

    NVICInit();

    DMAINIT();
}

//DMA配置
void DMAINIT(void)

{
        USART_DMACmd(USARTCOM,USART_DMAReq_Rx,ENABLE);   //使能串口1 DMA接收
        //相应的DMA配置
        DMA_InitTypeDef DMA_InitStructure;
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
        DMA_DeInit(USART_RX_DMA_CHANNEL);   //将DMA的通道5寄存器重设为缺省值  串口1对应的是DMA通道5
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR; //DMA外设usart基地址
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART_RX_BUF;  //DMA内存基地址
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //数据传输方向,从外设读取发送到内存
        DMA_InitStructure.DMA_BufferSize = BUF_SIZE;  //DMA通道的DMA缓存的大小
        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_Medium; //DMA通道 x拥有中优先级 
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
        DMA_Init(USART_RX_DMA_CHANNEL, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道     
        DMA_Cmd(USART_RX_DMA_CHANNEL, ENABLE);  //正式驱动DMA传输

}

void NVICInit(void)
{
     NVIC_InitTypeDef NVIC_InitStructure;
      NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); 
     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);    
    
     NVIC_InitStructure.NVIC_IRQChannel = USART_IRQ;
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 7;
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);
}

void MYDMA_Enable(void)

    DMA_Cmd(USART_RX_DMA_CHANNEL, DISABLE );  //关闭USART1 TX DMA1所指示的通道    
    DMA_SetCurrDataCounter(USART_RX_DMA_CHANNEL,RxSize);//DMA通道的DMA缓存的大小
    DMA_Cmd(USART_RX_DMA_CHANNEL, ENABLE);  //打开USART1 TX DMA1所指示的通道  
}  

//中断处理函数
void USART_IRQHandler(void)
{
      if(USART_GetITStatus(USARTCOM, USART_IT_IDLE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
      {   
          USART_ReceiveData(USARTCOM);//读取数据注意:这句必须要,否则不能够清除中断标志位。
          RLen =RxSize-DMA_GetCurrDataCounter(USART_RX_DMA_CHANNEL); //算出接本帧数据长度
          USART_ClearITPendingBit(USARTCOM,USART_IT_IDLE);         //清除中断标志
     } 

}
//输出数据
extern void USARTWrite(char *pSrc,uint16_t len)
{
    USART_ClearFlag(USARTCOM,USART_FLAG_TXE);
    USART_ClearFlag(USARTCOM,USART_FLAG_TC);
    while(len-- > 0)
    {
        while(USART_GetFlagStatus(USARTCOM,USART_FLAG_TXE) == RESET);
        USART_SendData(USARTCOM,*pSrc++);
    }
    while(USART_GetFlagStatus(USARTCOM,USART_FLAG_TC) == RESET);
}
//接收数据处理
extern void USARTRead(void)
{
    if(RLen > 0)
    {
        USARTWrite(USART_RX_BUF,RLen);
        RLen = 0;
        MYDMA_Enable();//恢复DMA指针,等待下一次的接收
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值