OpenEdv-开源电子网

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

STM32F4 DMA+空闲中断 不能每次都进空闲中断 求原因

[复制链接]

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-10-12
在线时间
14 小时
发表于 2016-11-8 19:44:01 | 显示全部楼层 |阅读模式
10金钱
求教!在写STM32F405 DMA+空闲中断接收,用的是USART3,看了网上很多分享的帖子了,但是都不行,出现的现象是:
1)我设置的BufferSize是16,必须要满足16个数后,才能触发我的空闲中断,且继续发送数据,偶尔会触发中断,但是接收DMA可正常工作,但是DMA_GetCurrDataCounter(DMA1_Stream1)与实际发送数据不符!
2)调整配置顺序,如先使能DMA,再配置USART,每次可以进中断,但是DMA不接收数据,接收寄存器一直为0,DR寄存器里显示是我发的一帧数据的第一个;
我的源程序如下,请帮我找找原因,我已经调了很多天了,但是这个一直困扰我!谢谢谢谢谢谢!
void USART3_Configuration(void)    // 串口配置函数
{
   GPIO_InitTypeDef GPIO_InitStructure;      
   NVIC_InitTypeDef NVIC_InitStructure;
   USART_InitTypeDef USART_InitStructure;  

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

    GPIO_PinAFConfig(GPIOC,GPIO_PinSource10,GPIO_AF_USART3); //GPIOC10复用USART3_TX
    GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_USART3); //GPIOC11复用USART3_RX
//发送TXPIN  
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
     GPIO_Init(GPIOC, &GPIO_InitStructure);  
//接收RXPIN  
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;  
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //上拉   
     GPIO_Init(GPIOC, &GPIO_InitStructure);

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

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

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

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

void USART3_IRQHandler(void)
{

      uint32_t temp = 0;  
       uint16_t i = 0;
       unsigned char r = 0;   
if((USART_GetFlagStatus(USART3,USART_IT_IDLE)) != RESET)
  {
   DMA_Cmd(DMA1_Stream1, DISABLE);
   temp = USART3->SR;  
   temp = USART3->DR;
   i = 16 - DMA_GetCurrDataCounter(DMA1_Stream1);
   DMA_ClearFlag(DMA1_Stream1,DMA_FLAG_TCIF1 | DMA_FLAG_FEIF1 | DMA_FLAG_DMEIF1 | DMA_FLAG_TEIF1 | DMA_FLAG_HTIF1);//清除DMA1_Steam1传输完成标志
    DMA_SetCurrDataCounter(DMA1_Stream1, 16);
     receive_flag = 1; //????????1DMA_Cmd(DMA1_Stream1, ENABLE);
  }
}
配置程序和中断服务函数如上,请大家帮我看看!或者大家一起讨论一下呀!我真的已经试了很多很多种方案!



最佳答案

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

使用道具 举报

259

主题

806

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1887
金钱
1887
注册时间
2012-10-28
在线时间
353 小时
发表于 2016-11-8 19:44:02 | 显示全部楼层
rewpron321 发表于 2016-11-9 17:58
不好意思,阿mo论坛你有邀请码吗?原来他是要邀请码的呀

USART DMA_IDLE Cube hal 接收不定长数据.rar (3.79 MB, 下载次数: 1339)
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-10-12
在线时间
14 小时
 楼主| 发表于 2016-11-9 09:25:43 | 显示全部楼层
自己顶,难道都没有人有兴趣吗?~~~~(>_<)~~~~
回复

使用道具 举报

259

主题

806

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1887
金钱
1887
注册时间
2012-10-28
在线时间
353 小时
发表于 2016-11-9 15:35:47 | 显示全部楼层
rewpron321 发表于 2016-11-9 09:25
自己顶,难道都没有人有兴趣吗?~~~~(>_

貌似阿mo论坛里面有 关于 这个的 程序代码,你去搜一下下载来使用就可以了
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-10-12
在线时间
14 小时
 楼主| 发表于 2016-11-9 17:58:30 | 显示全部楼层
hpdell 发表于 2016-11-9 15:35
貌似阿mo论坛里面有 关于 这个的 程序代码,你去搜一下下载来使用就可以了

不好意思,阿mo论坛你有邀请码吗?原来他是要邀请码的呀
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-10-12
在线时间
14 小时
 楼主| 发表于 2016-11-10 09:45:31 | 显示全部楼层

谢谢!谢谢!我瞅瞅去
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-10-12
在线时间
14 小时
 楼主| 发表于 2016-11-10 15:03:26 | 显示全部楼层

你好,不好意思,你发的是USART Cube的,我参考着改了一下,还是不行
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-10-12
在线时间
14 小时
 楼主| 发表于 2016-11-10 15:59:55 | 显示全部楼层
我想说原子哥,我现在还是困惑满满,没有解决问题,而且我不明白为啥我的IDLE中断是定长的,有谁出现过这个情况吗?
回复

使用道具 举报

259

主题

806

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1887
金钱
1887
注册时间
2012-10-28
在线时间
353 小时
发表于 2016-11-10 17:05:25 | 显示全部楼层
rewpron321 发表于 2016-11-10 15:03
你好,不好意思,你发的是USART Cube的,我参考着改了一下,还是不行

这个肯定是可以使用的,要不你使用 cube 测试看看再移植到你的工程中
回复

使用道具 举报

2

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2016-7-27
在线时间
24 小时
发表于 2016-11-18 11:31:50 | 显示全部楼层
不要用循环传输,想办法用Normal传输。虽然循环传输的思想更正确,但是对于这种空闲中断应用有时候会有问题
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-10-12
在线时间
14 小时
 楼主| 发表于 2016-11-18 14:29:15 | 显示全部楼层
硬件搬砖师 发表于 2016-11-18 11:31
不要用循环传输,想办法用Normal传输。虽然循环传输的思想更正确,但是对于这种空闲中断应用有时候会有问题

这个方法我也试了,但是也不行的,我用了NORMAL,然后在中断里,重新配置了,也不行。我的问题是他必须达到buffersize后才会触发中断
回复

使用道具 举报

42

主题

297

帖子

0

精华

高级会员

Rank: 4

积分
994
金钱
994
注册时间
2016-7-22
在线时间
318 小时
发表于 2016-11-18 14:57:24 | 显示全部楼层
我也在做串口dma的相关实验,发送接受都是dma,而且开启了双缓冲,空闲中断也用了,你可以参考下http://www.openedv.com/forum.php ... mp;extra=#pid504076
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-10-12
在线时间
14 小时
 楼主| 发表于 2016-11-22 15:04:03 | 显示全部楼层
hi我歌月徘徊 发表于 2016-11-18 14:57
我也在做串口dma的相关实验,发送接受都是dma,而且开启了双缓冲,空闲中断也用了,你可以参考下http://www ...

好的,谢谢!我去瞅瞅
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-10-12
在线时间
14 小时
 楼主| 发表于 2016-11-22 16:24:19 | 显示全部楼层
谢谢大家!我找到原因了!if((USART_GetFlagStatus(USART3,USART_IT_IDLE)) != RESET),这句应该是if((USART_GetFlagStatus(USART3,USART_FLAG_IDLE)) != RESET),还是我自己不细心
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
18
金钱
18
注册时间
2021-5-21
在线时间
4 小时
发表于 2022-2-24 16:30:49 | 显示全部楼层

感谢大佬!!得补下基础了,被DMA要搞晕了。这个代码解决了我的问题
回复

使用道具 举报

259

主题

806

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1887
金钱
1887
注册时间
2012-10-28
在线时间
353 小时
发表于 2022-6-22 21:37:56 | 显示全部楼层
STM9696 发表于 2022-2-24 16:30
感谢大佬!!得补下基础了,被DMA要搞晕了。这个代码解决了我的问题

有用就好哇,
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-2-25 15:35

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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