STM32F4 HAL库I2S 全双工模式的一个BUG

发布者:xrmilk最新更新时间:2019-08-28 来源: eefocus关键字:STM32F4  HAL库  I2S  全双工模式  BUG 手机看文章 扫描二维码
随时随地手机看文章

在使用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中断接收

推荐阅读最新更新时间:2024-11-12 00:14

STM32F4学习笔记8——NIVC向量中断
Cortex—M4内核支持128级中断嵌套,他有一个8位寄存器,用户可以通过这个寄存器设置中断优先级,但考虑到现在有些芯片不可能有这么多中断源,且支持这么多级中断嵌套堆栈也吃不消,大部分厂家都根据自己生产的芯片做出了调整,STM32F1和F4只是用了这个8位寄存器的高四位,低四位取零,这样=16也就是表示支持16级中断嵌套,对于这个NVIC还有一个新概念就是抢占优先级pre-emption和子优先级subpriority ·具有高抢占优先级的中断可以在具有低抢占优先级的中断处理过程中被响应,即中断嵌套,或者说高响应级别的中断可以嵌套低抢占优先级的中断 ·在抢占优先级相同的情况下,如果有低副优先级的中断正在执行,高副优先级的中断
[单片机]
<font color='red'>STM32F4</font>学习笔记8——NIVC向量中断
STM32F207串口DMA模式(串口中断bug稳定性)
使用DMA操作UART4: 一、DMA映射表 见下表: UART4的发送 UART4_TX 在Stream4。 UART4的接收 UART4_RX在Stream2。 他们在Channel_4。 二、程序代码 unsigned char btDMARecbuf ;// DMA接收数据地址 unsigned char btDMASendbuf ;//DMA发送数据地址 // 初始化 void UartDMA() { //定义中断结构体 NVIC_InitTypeDef NVIC_InitStructure ; //定义IO初始化结构体 GPIO_InitTypeDef GPIO_InitStructure
[单片机]
STM32F207串口DMA模式(串口中断<font color='red'>bug</font>稳定性)
基于STM32F407ZGT6实现微生态花园控制系统设计
1. 引言 以STM32F407ZGT6单片机为核心控制器设计了一种微型生态花园控制系统,将传感器技术、WiFi技术、摄像头技术、自动追光技术、μC/OS-Ⅲ实时操作系统结合起来,实现对花园环境以及动植物情况的实时监控和及时控制,并具有环境温度、环境湿度、土壤湿度、光照强度监控,鱼缸自动换水、增氧以及宠物自动喂养等功能。 2.系统总体框架设计 微型生态花园控制系统基于现实背景 设计,STM32F407ZGT6单片机为核心控制器,通过μC/OS-Ⅲ实时操作系统和TFT-LCD主控显示屏设计出便捷友好的用户界面,实时显示环境参数信息。系统采用成熟的物联网技术进行通信连接,用户可以通过机智云和手机App连接,实现云端传输数据功能。
[单片机]
基于<font color='red'>STM32F4</font>07ZGT6实现微生态花园控制系统设计
STM32F407 GPIO口输出配置配置步骤
STM32F407ZGT6 是意法半导体(STMicroelectronics)公司推出的一款高性能ARM Cortex-M4核心的32位微控制器(MCU)。它是 STM32F4 系列的一员,具备强大的处理能力和丰富的外设功能,适用于各种应用领域。 【1】F407建工程所需依赖文件 【2】 新建工程 **说明:STM32F4 的主频最高是 168Mhz,所以我们一般设置 PLLCLK 为 168Mhz(M=8,N=336,P=2),通过 SW 选择 SYSCLK=PLLCLK即可得到 168Mhz 的系统运行频率。** 【3】分析LED硬件原理图 【4】编写L
[单片机]
<font color='red'>STM32F4</font>07 GPIO口输出配置配置步骤
STM32的SPI1、SPI2、SPI3初始化及RF1101的应用(标准库与HAL库
——基于STM32F103RCT6 ---- 标准库: 说明:相关文件共有两个:bsp_spi_cc1101.h;bsp_spi_cc1101.c;以SPI2为例。 1、“bsp_spi_cc1101.h”中的参数定义: #ifndef _BSP_SPI_1101_H_ #define _BSP_SPI_1101_H_ #include stdio.h #include stm32f10x.h #include misc.h #include os_cfg_app.h #include os.h #include core_cm3.h #include bsp.h #include stm32f10x_s
[单片机]
STM32F407 外扩SRAM
字节控制功能。支持高/低字节控制。 看看实现 IS62WV51216 的访问,需要对 FSMC进行哪些配置。 这里就做一个概括性的讲解。步骤如下: 1)使能 FSMC 时钟,并配置 FSMC 相关的 IO 及其时钟使能。 要使用 FSMC,当然首先得开启其时钟。然后需要把 FSMC_D0~15,FSMCA0~18 等相关IO 口,全部配置为复用输出,并使能各 IO 组的时钟。 使能 FSMC 时钟的方法: RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE); 对于其他 IO 口设置的方法前面讲解很详细,这里不做过多的讲解。 2)设置 FSMC BANK1 区域 3。
[单片机]
<font color='red'>STM32F4</font>07 外扩SRAM
STM32F4开发板----串口(002)
串口 1 相关串口库函数 /* Exported macro ------------------------------------------------------------*/ /* Exported functions --------------------------------------------------------*/ /* Function used to set the USART configuration to the default reset state ***/ void USART_DeInit(USART_TypeDef* USARTx); /* Initializati
[单片机]
CAN、I2S、I2C、SPI、SSP总线对比
  一、SPI总线说明   串行外围设备接口SPI(serial peripheral interface)总线技术是Motorola公司推出的一种同步串行接口,Motorola公司生产的绝大多数MCU(微控制器)都配有SPI硬件接口,如68系列MCU。SPI 用于CPU与各种外围器件进行全双工、同步串行通讯。SPI可以同时发出和接收串行数据。它只需四条线就可以完成MCU与各种外围器件的通讯,这四条线是:串行时钟线(CSK)、主机输入/从机输出数据线(MISO)、主机输出/从机输入数据线(MOSI)、低电平有效从机选择线CS。这些外围器件可以是简单的TTL移位寄存器,复杂的LCD显示驱动器,A/D、D/A转换子系统或其他的MCU。当
[嵌入式]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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