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

查看: 8126|回复: 16

STM32F407 是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误

[复制链接]

1

主题

10

回帖

0

蝴蝶豆

初级会员

最后登录
1970-1-1
发表于 2014-7-13 12:37:32 | 显示全部楼层 |阅读模式
 新手请教   在使用STM32F407的DMA向外设SPI2发送数据时  使能DMA的半传输 与 传输完成中断
但是当DMA进入中断处理函数后    DMA的FEIF  TCIF HTIF 都被置位  
中断进入后发现SXNDTI内的值位8(DMA需要发送的数据个数为16) 在中断中关闭DMA 在半传输的 判断语句中再将DMA打开 
结果 中断退出后 很短时间内DMA的FEIF  TCIF HTIF 会再次被置位   
 
 //配置SPI2 DMA传输
  //配置SPI2 DMA传输
  void DMA_SPI_Configuration(void)
 {
                         DMA_InitTypeDef  DMA_InitStructure;
                         SPI_InitTypeDef   SPI_InitStructure;
                         GPIO_InitTypeDef GPIO_InitStructure;
                         NVIC_InitTypeDef NVIC_InitStructure;
         
         
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_DMA1,ENABLE); //使能GPIOA的AHB1时钟RCC_APB2Periph_AFIO|
  
 
          RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
 
 
 
 
         GPIO_PinAFConfig(GPIO_PORT_KKPJ_SPIX,GPIO_PinSource13, GPIO_AF_SPI2);
    GPIO_PinAFConfig( GPIO_PORT_KKPJ_SPIX ,GPIO_PinSource14, GPIO_AF_SPI2);
    GPIO_PinAFConfig( GPIO_PORT_KKPJ_SPIX ,GPIO_PinSource15, GPIO_AF_SPI2);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
    GPIO_Init(GPIO_PORT_XJ128_SPIX, &GPIO_InitStructure);
 
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
                GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
                GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
                GPIO_Init(GPIOB, &GPIO_InitStructure);
         
 //设置SPI1 SPI2 
                                         SPI_I2S_DeInit(SPI2);
                                   SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex ;//;SPI_Direction_1Line_Tx // SPI设置为双线双向全双工 ;
                                   SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // 设置为主SPI ;
                                   SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // SPI发送接收8位帧结构 ;
                                   SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;        // Low时钟悬空低 ;
                                   SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // 数据捕获于第二个时钟沿 ;
                                   SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;  // 内部NSS信号有SSI位控制 ;
                                   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; // 波特率预分频值为4 ;
                                   SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;  // 数据传输从MSB位开始 ;
                                   SPI_InitStructure.SPI_CRCPolynomial = 7;  // 定义了用于CRC值计算的多项式 7。
                                   SPI_Init(SPI2, &SPI_InitStructure); // 初始化外设SPI1寄存器 ;
 
                                        DMA_InitStructure.DMA_Channel = DMA_Channel_0;                    //DMA通道4 RM0090手册-&gt165
                                        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(SPI2->DR));    //外设地址
                                        DMA_InitStructure.DMA_Memory0BaseAddr = (u32)SPI1_Buffer_Tx;                   //内存地址
                                        DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;           //传输方向
                                        DMA_InitStructure.DMA_BufferSize = 0;                        //设置DMA传输时缓冲区大小
                                        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //设置DAM外设地址递增模式,因为目前就一个外设,故此处设置为禁止
                                        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;           //内存地址递增
                                        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;    //8位数据位宽度
                                        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; 
                                        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;   //DMA_Mode_Circular;                                                                //这里必须设置为这个模式
                                        DMA_InitStructure.DMA_Priority = DMA_Priority_High;    //DMA_Priority_VeryHigh;   //DMA_Priority_High;                       //设置优先级
                                        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;    //DMA_FIFOMode_Disable; 
                                        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
                                        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
                                        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
                                        DMA_Init(DMA1_Stream4, &DMA_InitStructure);
 
                                       
                         //Enable DMA2 Channel3 Tx Interrupt
                                NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream4_IRQn;     
                                NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //抢占优先级设置,值越大,表示优先级越低
                                NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;         //响应优先级设置,值越大,表示优先级越低
                                NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
                                NVIC_Init(&NVIC_InitStructure);  
 
 
                                DMA_ClearFlag(DMA1_Stream4,DMA_FLAG_HTIF4);        //清除数据传输一半中断标志DMA_FLAG_HTIF3
                                DMA_ClearFlag(DMA1_Stream4,DMA_FLAG_TCIF4);//清除数据传输完成中断标志       
                                DMA_ITConfig(DMA1_Stream4,DMA_IT_TC | DMA_IT_HT,ENABLE); 
                                  //使能 SPI2 DMA传输
                                 SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);
 }
 
 
 
 
 
 
 
 
 
void    DMA1_Stream4_IRQHandler(void)
 {          u16 ty=3;                  
      DMA1_Stream4 ->CR &= 0xFFFFFFFE; //除能DMA1_Stream3 
      while( DMA1_Stream4 ->CR & 0x00000001);//确保DMA可以被设置                
      //等待 SPI 数据寄存器空          
      while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
         SPI_Cmd(SPI2, DISABLE);
                //若数据传输一半
                        if(DMA_GetFlagStatus( DMA1_Stream4 ,DMA_FLAG_HTIF4))                                 
                         {
                                DMA_ClearFlag(KKHG_DMA_Stream,DMA_FLAG_HTIF4); 
                                SPI_Cmd(SPI2, ENABLE);  
                                 DMA1_Stream4 ->CR |= (uint32_t)DMA_SxCR_EN;//打开DMA的数据传输                                       
                         }       
                        if(DMA_GetFlagStatus( DMA1_Stream4 ,DMA_FLAG_TCIF4))           
                //若数据传输完成  数据传输完成后要关闭DMA传输   若想再一次使用DMA传输就必须 重新写入传输数目
                         {                       
                                DMA_ClearFlag( DMA1_Stream4 ,DMA_FLAG_TCIF4); 
                         }         
 }
 
反复搞了几天 实在没辙了  还请 大侠看下
 
 
<
回复

使用道具 举报

1

主题

10

回帖

0

蝴蝶豆

初级会员

最后登录
1970-1-1
 楼主| 发表于 2014-7-13 12:38:55 | 显示全部楼层

RE:STM32F407 是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误

补充下: 若在中断进入时不关闭DMA  那么数据的发送时正常的
回复 支持 反对

使用道具 举报

16

主题

560

回帖

1

蝴蝶豆

金牌会员

最后登录
2020-6-25
发表于 2014-7-13 13:32:17 | 显示全部楼层

RE:STM32F407 是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误

dma传输未完就关闭,再打开dma要重新告诉dma要传送哪个数据。
回复 支持 反对

使用道具 举报

1

主题

10

回帖

0

蝴蝶豆

初级会员

最后登录
1970-1-1
 楼主| 发表于 2014-7-13 23:22:01 | 显示全部楼层

回复:STM32F407 是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误

 非常感谢 您的回复   F103 使用半传输中断是不需要重新赋值的 当在半传输中断中再将DMA打开数据会自动继续传输 
 
您的意思是在半传输中断中再次对外设 与 内存地址重新赋值吗? 这样感觉半传输中断就没有意义了 
 
在DMA传输中断中 查询  EN  是否为0   但是得到的结果是 只有全部数据传输完毕后 读EN位 才会为0 
 
 
 
回复 支持 反对

使用道具 举报

24

主题

514

回帖

6

蝴蝶豆

金牌会员

最后登录
2019-4-8
发表于 2014-7-17 22:31:40 | 显示全部楼层

RE:STM32F407 是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误

为了解决你这个问题,我上网搜了一下相关的问题,发现出现你这种类似的问题的人还真不少,难道真像你说的是BUG?你现在解决了吗,记得分享一下
回复 支持 反对

使用道具 举报

1

主题

10

回帖

0

蝴蝶豆

初级会员

最后登录
1970-1-1
 楼主| 发表于 2014-7-20 23:53:10 | 显示全部楼层

回复:STM32F407 是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误

 没有解决  不过找到了折中的办法  还没有验证他的准确性   
要传输16字节数据  那么只开启传输完成中断  每次传输个数为8   这样在DMA中断中给DMA后8个数据的地址 然后在进行传输
 半传输也可以进入  只是不能暂停  找到好的办法再来发布
 
回复 支持 反对

使用道具 举报

91

主题

4603

回帖

4

蝴蝶豆

论坛元老

最后登录
2020-12-8
发表于 2014-7-23 02:26:55 | 显示全部楼层

RE:STM32F407 是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误

能设置中断逐步检查吗
回复 支持 反对

使用道具 举报

1

主题

10

回帖

0

蝴蝶豆

初级会员

最后登录
1970-1-1
 楼主| 发表于 2014-7-23 10:17:21 | 显示全部楼层

RE:STM32F407 是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误

能进入版半中断 但在半中断不能暂停DMA
在半中断中不能关闭DMA  手册中说 只有DMA传输完毕  写EN 位 才会有效
回复 支持 反对

使用道具 举报

23

主题

195

回帖

0

蝴蝶豆

初级会员

最后登录
1970-1-1
发表于 2014-7-24 16:17:36 | 显示全部楼层

RE:STM32F407 是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误

那你想怎么改, 总要等中断看看的呀
回复 支持 反对

使用道具 举报

1

主题

10

回帖

0

蝴蝶豆

初级会员

最后登录
1970-1-1
 楼主| 发表于 2014-7-24 16:26:50 | 显示全部楼层

回复:STM32F407 是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误

 大家有没有实际验证过  我没有实现  使用示波器 来查看程序的执行情况  (不要使用串口打印的方式 --太占用时间  ) 进入半中断后   关闭 SPI   关闭 DMA  等等吧  在保证数据完整传输的情况下 都没有得到正确的结果   若是DMA 不停止 那么没有问题 可以非常流畅的进入中断  好似 407 的DMA 在传输中就不能被打断吧!!!!
看手册说是 只有数据传输完毕 DMA 才会被允许设置 (EN位)
 
QQ:475503748
回复 支持 反对

使用道具 举报

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版