在使用STM324的I2S全双工模式时发现HAL库可能存在的一个问题,DMA使能循环模式后I2S发送和接收完成的回调不执行。 

查找原因发现是HAL库的stm32f4xx_hal_i2s_ex.c文件中I2SEx_TxRxDMACplt函数在判断到开启了DMA循环模式就不在调用完成回调。


/**

  * @brief DMA I2S transmit receive process complete callback

  * @param  hdma pointer to a DMA_HandleTypeDef structure that contains

  *               the configuration information for the specified DMA module.

  * @retval None

  */

static void I2SEx_TxRxDMACplt(DMA_HandleTypeDef *hdma)

{

  I2S_HandleTypeDef* hi2s = (I2S_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;


  /* if DMA is not configured in DMA_CIRCULAR mode */

  if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U)

  {

    if (hi2s->hdmarx == hdma)

    {

      /* Disable Rx DMA Request */

      if (((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_TX) ||

          ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_TX))

      {

        CLEAR_BIT(I2SxEXT(hi2s->Instance)->CR2,SPI_CR2_RXDMAEN);

      }

      else

      {

        CLEAR_BIT(hi2s->Instance->CR2,SPI_CR2_RXDMAEN);

      }


      hi2s->RxXferCount = 0U;


      if (hi2s->TxXferCount == 0U)

      {

        hi2s->State = HAL_I2S_STATE_READY;


        HAL_I2SEx_TxRxCpltCallback(hi2s);

      }

    }


    if (hi2s->hdmatx == hdma)

    {

      /* Disable Tx DMA Request */

      if (((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_TX) ||

          ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_TX))

      {

        CLEAR_BIT(hi2s->Instance->CR2,SPI_CR2_TXDMAEN);

      }

      else

      {

        CLEAR_BIT(I2SxEXT(hi2s->Instance)->CR2,SPI_CR2_TXDMAEN);

      }


      hi2s->TxXferCount = 0U;


      if (hi2s->RxXferCount == 0U)

      {

        hi2s->State = HAL_I2S_STATE_READY;


        HAL_I2SEx_TxRxCpltCallback(hi2s);

      }

    }

  }

}


有点不太理解为什么开启了DMA循环模式就不给完成回调,我还在想是不是ST的工程师有什么特别的意图我没有理解。所以我决定看一下F4的半双工模式是不是也是这样操作的,打开stm32f4xx_hal_i2s.c,发送和接收的回调分别是在不同的函数上实现的。很明显是否开启DMA的循环模式并不影响完成回调的执行,也就是说在半双工模式开启DMA的循环模式是可以正常使用传输完成回调。


/**

  * @brief DMA I2S transmit process complete callback

  * @param  hdma pointer to a DMA_HandleTypeDef structure that contains

  *                the configuration information for the specified DMA module.

  * @retval None

  */

static void I2S_DMATxCplt(DMA_HandleTypeDef *hdma)

{

  I2S_HandleTypeDef* hi2s = ( I2S_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;


  if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U)

  {

    /* Disable Tx DMA Request */

    CLEAR_BIT(hi2s->Instance->CR2,SPI_CR2_TXDMAEN);


    hi2s->TxXferCount = 0U;

    hi2s->State       = HAL_I2S_STATE_READY;

  }

  HAL_I2S_TxCpltCallback(hi2s);

}

/**

  * @brief DMA I2S transmit process half complete callback

  * @param  hdma pointer to a DMA_HandleTypeDef structure that contains

  *                the configuration information for the specified DMA module.

  * @retval None

  */

static void I2S_DMATxHalfCplt(DMA_HandleTypeDef *hdma)

{

  I2S_HandleTypeDef* hi2s = (I2S_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;


  HAL_I2S_TxHalfCpltCallback(hi2s);

}


/**

  * @brief DMA I2S receive process complete callback

  * @param  hdma pointer to a DMA_HandleTypeDef structure that contains

  *                the configuration information for the specified DMA module.

  * @retval None

  */

static void I2S_DMARxCplt(DMA_HandleTypeDef *hdma)

{

  I2S_HandleTypeDef* hi2s = ( I2S_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;


  if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U)

  {

    /* Disable Rx DMA Request */

    CLEAR_BIT(hi2s->Instance->CR2,SPI_CR2_RXDMAEN);

    hi2s->RxXferCount = 0U;

    hi2s->State       = HAL_I2S_STATE_READY;

  }

  HAL_I2S_RxCpltCallback(hi2s);

}


/**

  * @brief DMA I2S receive process half complete callback

  * @param  hdma pointer to a DMA_HandleTypeDef structure that contains

  *                the configuration information for the specified DMA module.

  * @retval None

  */

static void I2S_DMARxHalfCplt(DMA_HandleTypeDef *hdma)

{

  I2S_HandleTypeDef* hi2s = (I2S_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;


  HAL_I2S_RxHalfCpltCallback(hi2s);

}


此时我已经开始怀疑是不是F4的HAL库存在BUG,为了验证我的想法我决定看一下F3的库是否也是如此。为什么是F3,以为我发现F1和F7都是只有半双工模式,F7这么高端的芯片竟然在I2S的功能上比F4弱,实在是不能理解啊。 

F3的HAL库半双工模式和全双工模式是共用同一个回调函数,通过代码我们可以发现F3不会出现使能DMA循环模式就不执行传输完成回调的问题。


/**

  * @brief DMA I2S transmit receive process complete callback 

  * @param hdma DMA handle

  * @retval None

  */

static void I2S_TxRxDMACplt(DMA_HandleTypeDef *hdma)   

{

  I2S_HandleTypeDef* hi2s = ( I2S_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;


  /* DMA Normal Mode */

  if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)

  {

    /* Disable Rx/Tx DMA Request */

    if(((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_TX) || ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_TX))

    {

      hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_TXDMAEN);

      I2SxEXT(hi2s->Instance)->CR2 &= (uint32_t)(~SPI_CR2_RXDMAEN);

    }

    else

    {

      hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_RXDMAEN);

      I2SxEXT(hi2s->Instance)->CR2 &= (uint32_t)(~SPI_CR2_TXDMAEN);

    }


    hi2s->RxXferCount = 0U;

    hi2s->TxXferCount = 0U;


    hi2s->State = HAL_I2S_STATE_READY;

  }


  HAL_I2S_TxRxCpltCallback(hi2s);

}


static void I2S_TxRxDMAHalfCplt(DMA_HandleTypeDef *hdma)

{

  I2S_HandleTypeDef* hi2s = ( I2S_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;


  HAL_I2S_TxRxHalfCpltCallback(hi2s);

}


关键字:STM32F4  HAL库  I2S  全双工模式  BUG 引用地址:STM32F4 HAL库I2S 全双工模式的一个BUG

上一篇:STM32Cube-USART
下一篇:stm32f103 keil5 HAL库 UART中断接收

推荐阅读

    随着九月的即将到来,新品旗舰即将发布,不少手机都开始了新的一轮大降价,苹果也不例外,尤其是新iPhone即将发布了,iPhone 8大降价促销那是肯定的。不过今天笔者要给大家推荐的并不是iPhone,而是目前市场上最值得购买的安卓手机,新机发布,老机让路,这已经是手机圈的潜规则,目前为了迎接新机,多款旗舰价格不断下跌,降至最低价,市场竞争...
已发送遥控器供电电压为例 函数Print_BSP_VOLTAGE中data前5位为帧头,最后一位校验。void Print_BSP_VOLTAGE(void){ uint8_tdata[13]; uint8_t count; data[0] = '$'; data[1] = 'M'; data[2] = '>';// data[3] = 7; //校验用数据长度 data[4] = MSP_ANALOG; data[5] = ...
一、实验目的1、学习步进电机驱动原理;2、掌握通过CPU控制步进电机的方法。二、实验内容1、了解步进电机的运行控制;2、了解步进电机运行速度的控制方法;3、了解步进电机运行方向的控制方法。三、实验设备DM2410B十实验系统;PC机;JTTAG仿真器;串口线。2、软件:PC机操作系统(WINDOWS 2000);ARM Developer Suite v1.2;MulTI-ICE V2.2.5;DNW 2410(或...
近日,韩国KNCAP公布了2021款 特斯拉Model 3 ( 参数 | 询价 ) 安全测试结果:综合分83.3分,但在自动刹车环节失利。在韩国KNCAP所设计的AEB自动紧急制动测试环节中,特斯拉Model 3分别以20km/h、25km/h和40km/h三个速度与行驶中的自行车、行人发生多次碰撞,导致该车的在行人安全与事故预防方面丢分较多,仅为三级(最高为一级)。在韩国,汽车安全测试...

史海拾趣

问答坊 | AI 解惑

普斯PS61005变频电源(500W)

经过AC→DC→AC变换的逆变电源称为变频电源,它有别于用于电机调速用的变频调速控制器,也有别于普通交流稳压电源。变频电源的主要功用是将现有交流电网电源变换成所需频率的稳定的纯净的正弦波电源。理想的交流电源的特点是频率稳定、电压稳定、内 ...…

查看全部问答∨

适应新形式下的无线数字城市视频监控方案

摘要:本文主要对无线数字城市视频监控提出综合的监控方案,方案中融合了卫星、4G、CDMA、智能手机终端、指挥中心等各项技术,是适应新形式下城市新发展的无线移动视频监控方案。   关键词:无线移动视频监控、卫星、4G、CDMA、智能手机终端、 ...…

查看全部问答∨

谁能帮我画画电路图?

我是作软件的,突然被要求画出下面板子的电路图,实在是杀了我也不会啊 就是这两张,一张正面一张背面 神啊,硬件我都不会 …

查看全部问答∨

各位老师 我定制Wince6.0 Attache Device之后 出现黑屏 怎么办啊

并且出现了 下面这些Warning  是什么原因啊  我正在做一项国家大学生创新性实验项目  用Wince做  wince对我来说都是新的   急啊     老师们帮帮我吧 Pass 1... Warnin ...…

查看全部问答∨

EVC中用msxml dom如何写xml文件?

我用的是ppc2003模拟器,是不是要在模拟器中加载msxml.dll文件? 包含的头文件应该如何设置? 全部分数奉上! …

查看全部问答∨

驱动模块makefile文件编写求助

自己编的一个linux驱动,我原来的工程目录是这样的:工程总目录下有一个include文件夹,所有的.c源文件,makefile文件,还有一个总的x.h头文件,x.h中include了include文件夹中所有的头文件和一些内核的头文件。include文件夹里有几个子文件夹,按 ...…

查看全部问答∨

要买ARM9(2410)开发板,帮忙介绍一下哈!

    TE2410型ARM9开发板是由慧通科技自主研发的一款嵌入式开发平台,基于三星公司的ARM处理器S3C2410A,开发板走线经过精心优化,性能稳定可靠,具有高性能、低功耗、接口丰富、体积小、集成度高和可配置性强等优良特性,可以满足客户 ...…

查看全部问答∨

意法半导体(ST)为STR91x的用户提供免费的TCP/IP协议栈

问个问题:是不是和uCosII配合用比较合适?复杂一点的OS都自带TCP/IP了。可以裸奔吗? …

查看全部问答∨

STM8的UART与GPIO切换

STM8的D5、D6口上电时初始化为UART,运行当中想切换成通用GPIO,怎么切换,用GPIO_Init重新初始化无效,找了一下资料没有头绪,请高手指点。…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved