[应用相关] STM32F4 DMA+空闲中断 不能每次都进空闲中断 求原因

[复制链接]
4468|16
 楼主| 发顺丰更大nc 发表于 2022-2-24 16:57 | 显示全部楼层 |阅读模式
AD, AC, DM, ST
我在写STM32F405 DMA+空闲中断接收。用的USART3。
看了网上很多调试的帖子,但都不行。求帮忙!

1)我设置的BufferSize是16,必须要满足16个数后,才能触发我的空闲中断,且继续发送数据,偶尔会触发中断,但是接收DMA可正常工作,但是DMA_GetCurrDataCounter(DMA1_Stream1)与实际发送数据不符!


2)调整配置顺序,如先使能DMA,再配置USART,每次可以进中断,但是DMA不接收数据,接收寄存器一直为0,DR寄存器里显示是我发的一帧数据的第一个;
我的源程序如下,请帮我找找原因,已经调了很多天,但一直没办法解决。




 楼主| 发顺丰更大nc 发表于 2022-2-24 17:09 | 显示全部楼层
  1. void USART3_Configuration(void)    // 串口配置函数
  2. {
  3.    GPIO_InitTypeDef GPIO_InitStructure;      
  4.    NVIC_InitTypeDef NVIC_InitStructure;
  5.    USART_InitTypeDef USART_InitStructure;  

  6.    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); //使能GPIOC时钟
  7.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//使能USART3时钟,挂在APB1上

  8.     GPIO_PinAFConfig(GPIOC,GPIO_PinSource10,GPIO_AF_USART3); //GPIOC10复用USART3_TX
  9.     GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_USART3); //GPIOC11复用USART3_RX
  10. //发送TXPIN  
  11.     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  
  12.      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  
  13.      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  
  14.      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  15.      GPIO_Init(GPIOC, &GPIO_InitStructure);  
  16. //接收RXPIN  
  17.      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  
  18.      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;  
  19.      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //上拉   
  20.      GPIO_Init(GPIOC, &GPIO_InitStructure);

  21.     USART_InitStructure.USART_BaudRate = 115200;//波特率设置

  22.    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
  23.    USART_InitStructure.USART_StopBits = USART_StopBits_1;//1个停止位
  24.    USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
  25.    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  26.    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //收发模式
  27.    USART_Init(USART3, &USART_InitStructure); //初始化串口3
  28.    USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);
  29.    USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE);

  30.   NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; //串口3中断通道
  31.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级2
  32.   NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;  //子优先级0
  33.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   //IRQ通道使能
  34.   NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
  35.   USART_Cmd(USART3, ENABLE);  //使能串口3
  36. }

  37. void DMA_Usart_Init()
  38. {
  39.   DMA_InitTypeDef DMA_InitStructure;
  40.    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); // 开启DMA1时钟
  41. DMA_InitStructure.DMA_Channel =  DMA_Channel_4;    //外设的接收通道
  42.   DMA_InitStructure.DMA_PeripheralBaseAddr =  (int32_t)&USART3->DR; //source  buf
  43.   DMA_InitStructure.DMA_Memory0BaseAddr = (int32_t)&USART3_R_BUF; //target buf
  44.   DMA_InitStructure.DMA_DIR =  DMA_DIR_PeripheralToMemory;  //外设寄存器 -> 内存缓冲区?
  45.   DMA_InitStructure.DMA_BufferSize = 18;  //BuffSize;
  46.   DMA_InitStructure.DMA_PeripheralInc =  DMA_PeripheralInc_Disable;
  47.   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  48.   DMA_InitStructure.DMA_PeripheralDataSize =   DMA_PeripheralDataSize_Byte;
  49.   DMA_InitStructure.DMA_MemoryDataSize =  DMA_MemoryDataSize_Byte;
  50.   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA_Mode_Circular;  //DMA_Mode_Normal; //接收设计为循环收,否则接收一次后,无法正常接收到数据
  51.   DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  52.   
  53.   DMA_InitStructure.DMA_FIFOMode =  DMA_FIFOMode_Disable;
  54.   DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; //指定FIFO阈值水平
  55. //  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  56.   DMA_InitStructure.DMA_MemoryBurst =  DMA_MemoryBurst_Single;// DMA_MemoryBurst_Single;      //指定Burst转移配置内存传输,单次传输
  57.   DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; // 指定的burst转移配置外围转移
  58.   
  59.   DMA_Init(DMA1_Stream1,  &DMA_InitStructure);
  60.   DMA_Cmd(DMA1_Stream1, ENABLE);
  61. }

  62. void USART3_IRQHandler(void)
  63. {

  64.       uint32_t temp = 0;  
  65.        uint16_t i = 0;
  66.        unsigned char r = 0;   
  67. if((USART_GetFlagStatus(USART3,USART_IT_IDLE)) != RESET)
  68.   {
  69.    DMA_Cmd(DMA1_Stream1, DISABLE);
  70.    temp = USART3->SR;  
  71.    temp = USART3->DR;
  72.    i = 16 - DMA_GetCurrDataCounter(DMA1_Stream1);
  73.    DMA_ClearFlag(DMA1_Stream1,DMA_FLAG_TCIF1 | DMA_FLAG_FEIF1 | DMA_FLAG_DMEIF1 | DMA_FLAG_TEIF1 | DMA_FLAG_HTIF1);//清除DMA1_Steam1传输完成标志
  74.     DMA_SetCurrDataCounter(DMA1_Stream1, 16);
  75.      receive_flag = 1; //????????1DMA_Cmd(DMA1_Stream1, ENABLE);
  76.   }
  77. }
 楼主| 发顺丰更大nc 发表于 2022-2-24 17:09 | 显示全部楼层
配置程序和中断服务函数如上,请大家帮我看看!或者大家一起讨论一下呀!我真的已经试了很多很多种方案!

 楼主| 发顺丰更大nc 发表于 2022-2-24 17:11 | 显示全部楼层
阿mo论坛据说有,求个邀*码?
呐咯密密 发表于 2022-2-25 09:19 | 显示全部楼层
额,你的中断里的这个if判断是不是有毛病:if((USART_GetFlagStatus(USART3,USART_IT_IDLE)) != RESET)
你可以试试这个:if((USART_GetFlagStatus(USART3,USART_FLAG_IDLE)) != RESET)
kingkits 发表于 2022-2-25 11:26 | 显示全部楼层
DMA 虽然好,但不是万能的,尤其是用在UART通讯中,如果对协议没有很好的规划时,建议最好不要用DMA通讯。
sr19861126 发表于 2022-7-11 10:20 | 显示全部楼层
DMA可以减少中断次数
sr19861126 发表于 2022-7-11 10:22 | 显示全部楼层
  我用的是原子的例程,不能移植,不能Debug,不知道是什么问题
SantaBunny 发表于 2023-3-1 12:58 | 显示全部楼层
当波特率确定后,一个字节的接收时间就已经确定了(假设当前波特率下一字节的发送时间为1ms),假设串口一直在接收数据,突然有1ms空闲下来,没有数据可接收了,这时CPU就可以提出串口空闲中断了;原理就是这样。DMA是自动搬运工,当有匹配数据时,它自然会去搬
童雨竹 发表于 2024-5-11 09:02 | 显示全部楼层

CPU借助于APB总线访问相关寄存器达到对I2C1工作模块的控制
Wordsworth 发表于 2024-5-11 10:05 | 显示全部楼层

ART2固定使用PCLK时钟,只有开启和关闭的问题,不存在其它时钟源选择
Clyde011 发表于 2024-5-11 11:08 | 显示全部楼层

一部分是I2C1的工作模块,另外一部分是其控制模块
公羊子丹 发表于 2024-5-11 12:01 | 显示全部楼层

控制模块的时钟仍然由外设时钟PCLK提供
万图 发表于 2024-5-11 13:04 | 显示全部楼层

USART1可以有多个时钟源
Uriah 发表于 2024-5-11 14:07 | 显示全部楼层

STM32CUBEMX配置生成初始化代码
帛灿灿 发表于 2024-5-11 16:03 | 显示全部楼层

通过访问寄存器来控制I2C1工作时钟的开启。
周半梅 发表于 2024-5-11 19:02 | 显示全部楼层

I2C1工作时钟源选择;I2C1模块工作时钟的开启使能。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

28

主题

276

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部