你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32串口接收DMA中断不能进

[复制链接]
GKoSon 提问时间:2018-7-2 15:16 /
背景说明

以前写以前写串口接收是:

  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);



微信看了一篇文章,我这种方法比较低能了,别人用的串口空闲中断,数据接收完毕以后,空闲,随即触发DMA来搬运数据到内存
这一部分我已经试验成功了。
现在我想实现DMA数据搬运完成以后触发DMA的中断,但是搞了一上午没找到问题,求助。
  1. void uart_init(u32 bound)
  2.         {

  3.   GPIO_InitTypeDef  GPIO_InitStructure;
  4.         USART_InitTypeDef USART_InitStructure;
  5.         NVIC_InitTypeDef  NVIC_InitStructure;
  6.          
  7. //1时钟       
  8.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);

  9.   
  10.         //2GPIO USART1_TX   GPIOA.9
  11.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  12.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  13.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
  14.   GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9


  15.                
  16.   //USART1_RX          GPIOA.10初始化
  17.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  18.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  19.   GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  



  20.   //3中断  NVIC 配置
  21.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  22.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
  23.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                //子优先级3
  24.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
  25.         NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器



  26.    //4配置 USART设置

  27.         USART_InitStructure.USART_BaudRate = bound;//串口波特率
  28.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
  29.         USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  30.         USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
  31.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  32.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //收发模式

  33.   USART_Init(USART1, &USART_InitStructure); //初始化串口1
  34. //  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  35. //  USART_Cmd(USART1, ENABLE);                    //使能串口1

  36.     USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);  
  37.     USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
  38.     USART_Cmd(USART1,ENABLE);
  39.                 DMA_init();
  40. }
复制代码

  1. void DMA_init(void)
  2. {
  3.    DMA_InitTypeDef    DMA_Initstructure;
  4.    NVIC_InitTypeDef   NVIC_Initstructure;

  5.        
  6.    /*开启DMA时钟*/
  7.    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
  8.       DMA_DeInit(DMA1_Channel5); ///////
  9.    /* Enable the DMA1 Interrupt */
  10.    NVIC_Initstructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;       //通道设置为串口1中断
  11.    NVIC_Initstructure.NVIC_IRQChannelSubPriority = 2;     //中断响应优先级0
  12.    NVIC_Initstructure.NVIC_IRQChannelPreemptionPriority=3;
  13.    NVIC_Initstructure.NVIC_IRQChannelCmd = ENABLE;        //打开中断
  14.    NVIC_Init(&NVIC_Initstructure);  


  15.        
  16.    /*DMA配置*/
  17.    DMA_Initstructure.DMA_PeripheralBaseAddr =  (u32)(&USART1->DR);;
  18.    DMA_Initstructure.DMA_MemoryBaseAddr     = (u32)receive_data;
  19.    DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  20.    DMA_Initstructure.DMA_BufferSize = 128;
  21.    DMA_Initstructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  22.    DMA_Initstructure.DMA_MemoryInc =DMA_MemoryInc_Enable;
  23.    DMA_Initstructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  24.    DMA_Initstructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  25.    DMA_Initstructure.DMA_Mode = DMA_Mode_Normal;
  26.    DMA_Initstructure.DMA_Priority = DMA_Priority_High;
  27.    DMA_Initstructure.DMA_M2M = DMA_M2M_Disable;
  28.    DMA_Init(DMA1_Channel5,&DMA_Initstructure);


  29.         DMA_ITConfig(DMA1_Channel5,  DMA_IT_TC, ENABLE);
  30.                                 DMA_Cmd(DMA1_Channel5,ENABLE);
  31. }
复制代码
结果就是void USART1_IRQHandler(void)正常 可以进来
{
//             unsigned char num=0;
//    if(USART_GetITStatus(USART1,USART_IT_IDLE) == SET)
//    {
//       num = USART1->SR;
//       num = USART1->DR; //清USART_IT_IDLE标志
//       DMA_Cmd(DMA1_Channel5,DISABLE);    //关闭DMA
//      num = 128 -  DMA_GetCurrDataCounter(DMA1_Channel5);      //得到真正接收数据个数  
//      receive_data[num] = '\0';
//      DMA1_Channel5->CNDTR=128;       //重新设置接收数据个数        DMA_Cmd(DMA1_Channel5,ENABLE);  //开启DMA
//     //  receive_flag = 1;           //接收数据标志位置1
//                        DMA_Cmd(DMA1_Channel5,ENABLE);  //开启DMA
//                        printf("%s ",receive_data );               
//    }
}

void DMAChannel5_IRQHandler(void)
{
    if(DMA_GetITStatus(DMA1_IT_TC5) != RESET)
    {
      TestLive();
      DMA_ClearITPendingBit(DMA1_IT_TC5);
    }
        //进不来

}

说明:我百度找了找别人的问题,一种是中断函数名字的问题,我这里不存在这个问题,如图
0000000.jpg

收藏 评论5 发布时间:2018-7-2 15:16

举报

5个回答
GKoSon 回答时间:2018-7-2 15:26:35
本帖最后由 与龙共舞 于 2018-7-2 15:51 编辑

串口助手循环不停的发送
现在注意到一个现象 中断在CNDRT为0是可以进去的
所以我的配置是有问题的 发个几十次 DMA表示完成了
代码问题大了  我DMA设置的是128个bit 串口过来数据其实是不定长的而我在128的时候才表示传输完成,。。。是不是无法这样写了。。
参考:http://blog.csdn.net/u010001130/article/details/77816020  所以void DMAChannel5_IRQHandler(void)这个函数一般没啥用?
4. DMA接收数据初始化

在串口使用DMA接收时,由于不知道数据传输的长度,故不能使能DMA接收中断。

11111.jpg
梁子 回答时间:2018-7-2 15:34:34
我用的是串口空闲中断+DMA,DMA干的活就是搬运串口数据(如果有则一直搬),直到串口出现空闲中断,再由中断函数中的用户代码,接着折腾串口数据。我认为这个思路是对的;你的思路,我还真没考虑过。

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

GKoSon 回答时间:2018-7-2 15:50:20
梁子 发表于 2018-7-2 15:34
我用的是串口空闲中断+DMA,DMA干的活就是搬运串口数据(如果有则一直搬),直到串口出现空闲中断,再由中 ...

嗯   我的思路好像有问题 串口空闲中断+DMA可以的 不能再加DMA中断  你的这个评论 我又迷糊了:空闲中断是怎么发生的?我上午以为是PC上位机 发送结束不在发送 那么串口空闲产生的中断 随后触发DMA去搬  你的说法是DMA搬运完数据 串口产生空闲中断
GKoSon 回答时间:2018-7-2 16:11:52
梁子 发表于 2018-7-2 15:34
我用的是串口空闲中断+DMA,DMA干的活就是搬运串口数据(如果有则一直搬),直到串口出现空闲中断,再由中 ...

是的 是搬完了 再进空闲中断的
void USART1_IRQHandler(void)
{
             unsigned char num=0;
        memset(receive_data,0,128);..此后看到清空了
梁子 回答时间:2018-7-2 16:28:52
本帖最后由 梁子 于 2018-7-2 16:30 编辑
与龙共舞 发表于 2018-7-2 15:50
嗯   我的思路好像有问题 串口空闲中断+DMA可以的 不能再加DMA中断  你的这个评论 我又迷糊了:空闲中断是 ...

当波特率确定后,一个字节的接收时间就已经确定了(假设当前波特率下一字节的发送时间为1ms),假设串口一直在接收数据,突然有1ms空闲下来,没有数据可接收了,这时CPU就可以提出串口空闲中断了;原理就是这样。DMA是自动搬运工,当有匹配数据时,它自然会去搬。

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版