OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2250|回复: 0

关于DMA+USART接收空闲中断的问题

[复制链接]

1

主题

3

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2019-6-10
在线时间
9 小时
发表于 2020-2-24 21:21:46 | 显示全部楼层 |阅读模式
14金钱
最近由于手里面没有片子,使用MDK的仿真调试,调试DMA节合串口中断时发现一个有意思的问题:1.可以接收到数据,有时候完整有时候不完整(使用XCOM V2.0调试助手);
2.接受完一帧数据后,在空闲时间内不能产生中断(使用XCOM V2.0调试助手);
3.在数据帧结尾加0X00 或者0XFF,可以产生空闲中断(使用XCOM V2.0调试助手);
4.使用Modbus poll调试软件发送数据帧,数据没有接收完整就会进入空闲中断;


软件仿真调试环境:
MDK5.28 + VSPD + XCOM V2.0 + MODBUS POLL

期待各位前辈指点一二,感谢!!!第一次发帖不知道这个金钱代表什么,我将我所有的金钱悬赏了。

下面是代码:

  • void My_UART_Init(void)  
  • {  
  •     GPIO_InitTypeDef GPIO_InitStruct;  
  •     USART_InitTypeDef USART_InitStruct;  
  •     NVIC_InitTypeDef NVIC_InitStruct;  
  •     DMA_InitTypeDef DMA_InitStruct;  
  •       
  •       
  •       
  •     DMA_DeInit(DMA1_Channel5);  
  •     DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)(&USART1->DR);    //外设--->内存  
  •     DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)RxBuffer;  
  •     DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;  
  •     DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
  •     DMA_InitStruct.DMA_BufferSize = BufferSize;  
  •     DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;  
  •     DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;  
  •     DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;  
  •     DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
  •     DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;  
  •     DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;  
  •     DMA_Init(DMA1_Channel5, &DMA_InitStruct);  
  •   
  •     DMA_Cmd(DMA1_Channel5, ENABLE);  
  •       
  •       
  •     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);      // 使能DMA  
  •     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   // 使能GPIOA  
  •     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);   // 使能时钟 复用USART  
  •   
  •     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;  
  •     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;  
  •     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;  
  •     GPIO_Init(GPIOA,&GPIO_InitStruct);  //初始化 USART_TX 即 GPIOA.9  
  •   
  •     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;  
  •     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;  
  •     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;  
  •     GPIO_Init(GPIOA,&GPIO_InitStruct);          //初始化 USART_RX 即 GPIOA.10  
  •   
  •     USART_InitStruct.USART_BaudRate = 9600;  
  •     USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  
  •     USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  
  •     USART_InitStruct.USART_Parity = USART_Parity_No;  
  •     USART_InitStruct.USART_StopBits = USART_StopBits_1;  
  •     USART_InitStruct.USART_WordLength = USART_WordLength_8b;  
  •     USART_Init(USART1,&USART_InitStruct);   //初始化 USART  
  •   
  •     USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);  // 开启 USART 接收缓冲区非空中断  
  •     USART_ITConfig(USART1, USART_IT_TC, DISABLE);   // 开启 USART 发送缓冲区空中断  
  •   
  •     USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);  //开启 USART1 总线空闲中断  
  •       
  •   
  •      
  •       
  •   
  •     NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;  
  •     NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;  
  •     NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01;   //抢占优先级 2位 00 01 10 11  
  •     NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x01;          //响应优先级 2位 00 01 10 11  
  •     NVIC_Init(&NVIC_InitStruct);                                //初始化中断  
  •   
  •     USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);              // 使能 USART1接收DMA  
  •     USART_Cmd(USART1, ENABLE);//使能USART中断  
  • }  
  •   
  • void USART1_IRQHandler(void)                    //串口1中断服务程序  
  • {  
  •     uint8_t clear = clear;  // 用来消除编译器的“没有用到”的提醒  
  •     uint8_t data = 0;  
  •   
  •     if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)  
  •     {  
  •         clear = USART1->SR;  
  •         clear = USART1->DR;  
  •   
  • //      RxCounter = BufferSize - DMA1_Channel5->CNDTR;//缓存中的字节数  
  •         RxCounter = BufferSize - DMA_GetCurrDataCounter(DMA1_Channel5);//缓存中的字节数  
  •   
  • //      USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);  
  •   
  •         RxStatus = 1;   //标记接收到一帧  
  •         USART_ClearITPendingBit(USART1, USART_IT_IDLE); // 清除空闲中断  
  •   
  •         DMA_Cmd(DMA1_Channel5, DISABLE);                // 停止DMA,清除DMA缓存  
  •     }  
  • }  
  • int main(void)  
  • {  
  •     uint8_t i = 0;  
  •     delay_init();  
  •     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);             // 初始化中断优先级分组  
  •     My_UART_Init();  
  •     while(1)  
  •     {  
  •         if(RxStatus == 1)  
  •         {  
  •             RxStatus = 0;  
  •             i = 0;  
  •   
  •             while(RxCounter--)  
  •             {  
  •                 USART_SendData(USART1, RxBuffer[i++]);  
  •                 while(USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);  
  •             }  
  •               
  •             memset(RxBuffer, 0, i); // 清除缓存  
  •             RxCounter = 0;  
  •   
  • //          DMA1_Channel5->CNDTR = BufferSize;  
  •             DMA_SetCurrDataCounter(DMA1_Channel5, BufferSize);  
  •             DMA_Cmd(DMA1_Channel5, ENABLE);  
  •         }  
  •          
  •     }  
  • }  






正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-20 20:07

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表