STM32
直播中

低调de炫耀爱

12年用户 762经验值
私信 关注
[问答]

请问大神怎样去使用STM32串口+DMA呢

请问大神怎样去使用STM32串口+DMA呢?

回帖(1)

冯虎虔

2021-12-13 15:16:59

uint8_t UART4_Rx_buffer[512],UART4_Rx_num;  

void UART4_Config(void)  
{  
    GPIO_InitTypeDef GPIO_InitStructure;               
    USART_InitTypeDef USART_InitStructure;  
    NVIC_InitTypeDef NVIC_InitStructure;  
    DMA_InitTypeDef DMA_InitStructure;      
         
//  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);      //选择NVIC优先级分组0   
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);  
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);  
  
    //串口4所使用管脚输出输入定义  
    //定义UART4 Tx (PC.10)脚为复用推挽输出  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;         //IO口的第2脚  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   //IO口复用推挽输出  
    GPIO_Init(GPIOC, &GPIO_InitStructure);            //初始化串口1输出IO口  
      
    //定义 UART4 Rx (PC.11)为悬空输入   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;           //IO口的第3脚  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//IO口悬空输入  
    GPIO_Init(GPIOC, &GPIO_InitStructure);               //初始化串口1输入IO口  
  
    //串口4参数初始化定义部分,串口1参数为9600 , 8 ,1 ,N  接收中断方式   
    USART_InitStructure.USART_BaudRate = 9600;                  //设定传输速率  
    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;   //使用接收和发送功能   
    USART_Init(UART4, &USART_InitStructure);      //初始化串口4  
      
    USART_ITConfig(UART4, USART_IT_IDLE,ENABLE);  //使能串口4接收中断     
    USART_Cmd(UART4, ENABLE);                     //使能串口4     
    USART_ClearFlag(UART4, USART_FLAG_TC);        // 清标志(后增加)  
  
    DMA_DeInit(DMA2_Channel3);   //重置DMA 2通道配置   
    DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40004C04;   //外设地址   
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)UART4_Rx_buffer;     //内存地址   
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;   //外设作为数据目的地   
    DMA_InitStructure.DMA_BufferSize = 512;  //DMA缓存大小:BufferSize   
    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_PeripheralDataSize_Byte;  //内存数据宽度为8位   
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //工作在正常缓存模式   
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;  //设置DMA通道优先级为高   
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;     //禁止DMA通道设置为内存至内存传输   
    DMA_Init(DMA2_Channel3, &DMA_InitStructure);     //初始化  
        
    DMA_ITConfig(DMA2_Channel3, DMA_IT_TC, ENABLE);  
    DMA_ITConfig(DMA2_Channel3, DMA_IT_TE, ENABLE);  
  
    USART_DMACmd(UART4, USART_DMAReq_Rx, ENABLE);  
    DMA_Cmd(DMA2_Channel3, ENABLE);  
    //使能串口4中断  
    NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;  
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
    NVIC_Init(&NVIC_InitStructure);   
  
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel3_IRQn;   
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;   
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;   
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   
    NVIC_Init(&NVIC_InitStructure);  
}  

void UART4_IRQHandler(void)  
{  
    uint16_t i;  
    uint16_t Data_Len;  
if(USART_GetITStatus(UART4, USART_IT_IDLE) != RESET)    //如果为中断  
{   
    DMA_Cmd(DMA2_Channel3, DISABLE);  
    Data_Len=512-DMA_GetCurrDataCounter(DMA2_Channel3);  
    USART_PutStr(USART1,UART4_Rx_buffer,Data_Len);   
    UART4_Rx_num=0;  
    DMA_ClearFlag(DMA2_FLAG_GL3 | DMA2_FLAG_TC3 | DMA2_FLAG_TE3 | DMA2_FLAG_HT3); //清标志  
    DMA2_Channel3->CNDTR = 512;                //重装填  
    DMA_Cmd(DMA2_Channel3, ENABLE);            //处理完,重开DMA  
    //读SR后读DR清除IDLE  
    i = UART4->SR;  
    i = UART4->DR;  
    if(i) i=0;  
    if(Data_Len) Data_Len=0;
}
}   

if(USART_GetITStatus(UART4, USART_IT_PE | USART_IT_FE | USART_IT_NE) != RESET)
{    //出错  
    USART_ClearITPendingBit(UART4, USART_IT_PE | USART_IT_FE | USART_IT_NE);  
    USART_ClearITPendingBit(UART4, USART_IT_TC);  
    USART_ClearITPendingBit(UART4, USART_IT_IDLE);
    void DMA2_Channel3_IRQHandler(void)  
    USART_PutStr(USART1," DMA23:rn",9);  
    DMA_ClearITPendingBit(DMA2_IT_TC3);  
    DMA_ClearITPendingBit(DMA2_IT_TE3);  
    DMA_Cmd(DMA2_Channel3, DISABLE);         //关闭DMA,防止处理其间有数据  
    DMA2_Channel3->CNDTR = 512;              //重装填  
    DMA_Cmd(DMA2_Channel3, ENABLE);          //处理完,重开DMA  
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分