关于STM32 定时器通道从输入捕获切换到PWM模式的遇到问题(HAL库)

        这些天在学习研究基于STM32 HAL库的FreeRTOS系统,打算自行设计一个小项目,其中要实现这样一个功能:

        STM32F103C8T6中的 PB11引脚开机默认初始化为TIM2CH4定时器输入捕获功能,在中间任务切换后,将该引脚再定义成TIM2CH4的PWM输出功能,下一次切换再换回来。

        由于STM32CubeMX只能生成初始化的代码,只能默认一种模式初始化。所以切换后的引脚初始化要自己重新写。查询HAL库源代码发现,官方给出了两个针对输入逆初始化函数,于是写上:

HAL_TIM_IC_DeInit(&htim2);
HAL_TIM_Base_MspDeInit(&htim2);

        然后,进行通道PWM的设置以及引脚的初始化,启用PWM输出。结果执行切换之后,PWM就是输出不出来,没信号。调试也没发现有哪句代码出现初始化错误。如果一开始就将其初始化为PWM模式的话,功能是正常的,所以排除硬件问题。万般无奈只能去研究底层的寄存器。

        通过查询《STM32 参考手册》发现输入捕获切换PWM过程中主要影响的是两个寄存器,捕获/比较模式寄存器(TIMx_CCMR1/2)和捕获/比较使能寄存器(TIMx_CCER),其中TIM2CH4对应的捕获/比较模式寄存器是TIM2_CCMR2。于是在代码中加入了以下两句,方便调式:

printf("%x",htim2.Instance->CCMR2);
printf("%x",htim2.Instance->CCER);

        结果发现了端倪,CCER寄存器是没有变化的,而TIM2_CCMR2有问题,在TIM2CH4是输入捕获模式时,TIM2_CCMR2值为0xF568,而切换为PWM波模式时是0xE868(此时PWM输出有问题),如果一开始就初始化为PWM模式,TIM2_CCMR2值为0x6868(此时正常工作)。

        有问题时的TIM2_CCMR2:0xE868,二进制:1110100001101000

        没问题时的TIM2_CCMR2:0x6868,二进制:0110100001101000

        问题很明显,最左边一位出了问题!这时候其实可以解决了,但是还是想知道因为什么。所以再次查一下《STM32 参考手册》,TIMx_CCMR2的寄存器有下面一张图:

        可以看出,TIM2_CCMR2两种模式下,16位数字的代表意义不同,上面一行是通道作为输出时的初始化设置,下面一行为作为输入时的初始化设置。可以看出,从IC模式向OC模式转换时,第15位的OC4CE没有转变成初始状态,本来应该是置0的,结果为1。

        ·进一步查查手册这一位是干什么的:

         可以看出当OCxCE(本项目为OC4CE)为的时候输出的PWM会收到外部触发信号影响,一旦ETRF信号为高电平,会把输出的PWM信号(OCxREF)全部拉低。这就是为啥我的PWM信号一直为0了。至于为啥我的ETRF信号一直在触发,那可能是硬件问题了。

        知道这个原因后,解决办法有很多种。之所以那两个DeInit函数没能将这个OC4CE复位,可能是我没有找到对应的函数,或者是官方库存在BUG。解决办法是切换模式之前可以手动将整个TIM2_CCMR2值复位(查询得知默认复位值就是0),在加入下面一句代码即可。

htim2.Instance->CCMR2 &=0x0000;

        完整的切换代码段如下:

   //逆初始化通道
    HAL_TIM_IC_DeInit(&htim2);
    HAL_TIM_Base_MspDeInit(&htim2);

    __HAL_RCC_TIM2_CLK_ENABLE();
    
    TIM_OC_InitTypeDef sConfigOC = {0};
    

    if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
    {
        Error_Handler();
        
    }
    
    //复位TIM2_CCMR2的值
    htim2.Instance->CCMR2 &=0x0000;
      
    
    //初始化PWM模式
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 0;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
    {
        Error_Handler();
    }

    
     //初始化引脚
    __HAL_RCC_GPIOB_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

   __HAL_AFIO_REMAP_TIM2_PARTIAL_2();
    
    HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4);

 

版权声明:本文为CSDN博主「洛小白2233」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/baidu_38952193/article/details/122697039

        这些天在学习研究基于STM32 HAL库的FreeRTOS系统,打算自行设计一个小项目,其中要实现这样一个功能:

        STM32F103C8T6中的 PB11引脚开机默认初始化为TIM2CH4定时器输入捕获功能,在中间任务切换后,将该引脚再定义成TIM2CH4的PWM输出功能,下一次切换再换回来。

        由于STM32CubeMX只能生成初始化的代码,只能默认一种模式初始化。所以切换后的引脚初始化要自己重新写。查询HAL库源代码发现,官方给出了两个针对输入逆初始化函数,于是写上:

HAL_TIM_IC_DeInit(&htim2);
HAL_TIM_Base_MspDeInit(&htim2);

        然后,进行通道PWM的设置以及引脚的初始化,启用PWM输出。结果执行切换之后,PWM就是输出不出来,没信号。调试也没发现有哪句代码出现初始化错误。如果一开始就将其初始化为PWM模式的话,功能是正常的,所以排除硬件问题。万般无奈只能去研究底层的寄存器。

        通过查询《STM32 参考手册》发现输入捕获切换PWM过程中主要影响的是两个寄存器,捕获/比较模式寄存器(TIMx_CCMR1/2)和捕获/比较使能寄存器(TIMx_CCER),其中TIM2CH4对应的捕获/比较模式寄存器是TIM2_CCMR2。于是在代码中加入了以下两句,方便调式:

printf("%x",htim2.Instance->CCMR2);
printf("%x",htim2.Instance->CCER);

        结果发现了端倪,CCER寄存器是没有变化的,而TIM2_CCMR2有问题,在TIM2CH4是输入捕获模式时,TIM2_CCMR2值为0xF568,而切换为PWM波模式时是0xE868(此时PWM输出有问题),如果一开始就初始化为PWM模式,TIM2_CCMR2值为0x6868(此时正常工作)。

        有问题时的TIM2_CCMR2:0xE868,二进制:1110100001101000

        没问题时的TIM2_CCMR2:0x6868,二进制:0110100001101000

        问题很明显,最左边一位出了问题!这时候其实可以解决了,但是还是想知道因为什么。所以再次查一下《STM32 参考手册》,TIMx_CCMR2的寄存器有下面一张图:

        可以看出,TIM2_CCMR2两种模式下,16位数字的代表意义不同,上面一行是通道作为输出时的初始化设置,下面一行为作为输入时的初始化设置。可以看出,从IC模式向OC模式转换时,第15位的OC4CE没有转变成初始状态,本来应该是置0的,结果为1。

        ·进一步查查手册这一位是干什么的:

         可以看出当OCxCE(本项目为OC4CE)为的时候输出的PWM会收到外部触发信号影响,一旦ETRF信号为高电平,会把输出的PWM信号(OCxREF)全部拉低。这就是为啥我的PWM信号一直为0了。至于为啥我的ETRF信号一直在触发,那可能是硬件问题了。

        知道这个原因后,解决办法有很多种。之所以那两个DeInit函数没能将这个OC4CE复位,可能是我没有找到对应的函数,或者是官方库存在BUG。解决办法是切换模式之前可以手动将整个TIM2_CCMR2值复位(查询得知默认复位值就是0),在加入下面一句代码即可。

htim2.Instance->CCMR2 &=0x0000;

        完整的切换代码段如下:

   //逆初始化通道
    HAL_TIM_IC_DeInit(&htim2);
    HAL_TIM_Base_MspDeInit(&htim2);

    __HAL_RCC_TIM2_CLK_ENABLE();
    
    TIM_OC_InitTypeDef sConfigOC = {0};
    

    if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
    {
        Error_Handler();
        
    }
    
    //复位TIM2_CCMR2的值
    htim2.Instance->CCMR2 &=0x0000;
      
    
    //初始化PWM模式
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 0;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
    {
        Error_Handler();
    }

    
     //初始化引脚
    __HAL_RCC_GPIOB_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

   __HAL_AFIO_REMAP_TIM2_PARTIAL_2();
    
    HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4);

 

版权声明:本文为CSDN博主「洛小白2233」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/baidu_38952193/article/details/122697039

生成海报
点赞 0

洛小白2233

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32F4最小系统硬件设计

对于硬件工程师来讲,想要入门STM32相关的开发,我想除了深入阅读一下STM32的数据手册外,最实用且有效的方法就是自己实际做一个STM32的最小系统板了。本文将以一个小的STM32F427VG的电路最

STM32F1移植U8g2库

STM32移植U8g2库 MCU为STM32F1030C8T6最小系统,使用STM32CubeMX生成HAL库工程模板,采用硬件四线SPI连接0.96寸单色OLED(驱动芯片为SSD1306,128*