我帮厂商找BUG系列之华大(小华)HC32F460——PWM输出占空比错误与解决方案

本文介绍了在使用DDL3.0.0库函数操作HC32F460芯片的TIMERA3通道PWM5时遇到的输出波形异常问题。作者分析了官方提供的初始化代码,并怀疑可能是period时的翻转或控制寄存器状态导致的。通过改变初始化设置,将捕获和更新极性固定,问题得到解决。作者呼吁官方对可能存在的问题进行解释,并分享了完整的修复代码段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0x00 前言

阅读本文,您可能需要掌握的知识:

本文使用的是DDL3.0.0库函数。接口为官方最新的函数API。采用的操作为官方的DEMO操作稍加修改。

技能熟练度
PWM了解
C语言了解

0x10 故障出现

输出占空比的定时器为TIMERA的3通道PWM5,并且使用矩形波进行计数,

这里发现当前的输出波形乱七八糟,各种奇奇怪怪的显示方案。随后查看官方对于当前库函数的定义协议。

发现如下代码


/**
 * @brief  Set a default value for the PWM initialization structure.
 * @param  [out] pstcPwmInit            Pointer to a stc_tmra_pwm_init_t structure value that
 *                                      contains the configuration information for PWM.
 * @retval int32_t:
 *           - LL_OK:                   No error occurred.
 *           - LL_ERR_INVD_PARAM:       pstcPwmInit == NULL.
 */
int32_t TMRA_PWM_StructInit(stc_tmra_pwm_init_t *pstcPwmInit)
{
    int32_t i32Ret = LL_ERR_INVD_PARAM;

    if (pstcPwmInit != NULL) {
        pstcPwmInit->u32CompareValue         = TMRA_REG_VALUE_MAX;
        pstcPwmInit->u16StartPolarity        = TMRA_PWM_HIGH;
        pstcPwmInit->u16StopPolarity         = TMRA_PWM_LOW;
        pstcPwmInit->u16CompareMatchPolarity = TMRA_PWM_INVT;
        pstcPwmInit->u16PeriodMatchPolarity  = TMRA_PWM_INVT;
        i32Ret = LL_OK;
    }

    return i32Ret;
}

这里可以看到,官方人员想的还是蛮周到的,在开始时高电平,关闭的时候低电平,捕获、更新时反转当前电平。

于是初始化为高,第一次捕获为低,更新时为高。第二次捕获时翻转为低。

但是实际上输出的情况惨不忍睹。

笔者的代码逻辑

初始化占空比为1
设置10*i的占空比捕获
等待一秒钟

这里可以看到当前设置的占空比乱七八糟的

帮着大厂找bug之小华HC32F460 PWM输出bug

0x20 查找问题

在确定自己的计算方式没有问题后。笔者查到了上文的代码内。

检查了这个参数后,笔者发现在period时可能会出现无法翻转的情况。亦或者是其控制寄存器卡在了未知的控制逻辑下。也就是说,有可能出现在update之后,异常的翻转导致当前的结构出现误判(笔者怀疑可能有未知通道的输出被触发,但是实在没有证据,因为如果内部捕获输出操作本身有问题,那么笔者的使用方式也会有问题,所以肯定底层是正常的),这种情况下几乎是必然的。

随后笔者采用了莽着来的定点清楚的操作:

 	
	(void)TMRA_PWM_StructInit(&stcPwmInit);
    
     stcPwmInit.u16StartPolarity        = TMRA_PWM_LOW;
     stcPwmInit.u16StopPolarity         = TMRA_PWM_HIGH;
     stcPwmInit.u16CompareMatchPolarity = TMRA_PWM_HIGH;
     stcPwmInit.u16PeriodMatchPolarity  = TMRA_PWM_LOW;
     GPIO_SetFunc(GPIO_PORT_A, GPIO_PIN_04, TMRA_PWM_PIN_FUNC);
    stcPwmInit.u32CompareValue = ret_compare;
    (void)TMRA_PWM_Init(CM_TMRA_3, TMRA_CH5, &stcPwmInit);
    TMRA_SetPeriodValue(CM_TMRA_3,ret_period);
   TMRA_SetCompareValue(CM_TMRA_3, TMRA_CH5, ret_compare);

这种结构下,在捕获时固定为高电平极性,更新时固定为低电平极性。则更可靠。

可以看一下同样的应用逻辑下的具体表现。

帮着大厂找bug之小华HC32F460 PWM输出bug

顺便@一下官方,帮忙解释一下到底为什么会这样。

0x30 总结

这个计算方式写死了当前的接口状态。在现在PWM的结构下可以使用,但是可能在其他的状态下出现异常的情况。比如在三角波的情况下触发,所以可能也是官方并没有完全进行测试。否则一个判断语句也就可以了

本文首发自 我帮厂商找BUG系列之华大(小华)HC32F460——PWM输出占空比错误与解决方案,更多文章可进入我的博客详查。

<think>嗯,用户提供的代码是关于配置Timer A(TMRA)生成PWM的,但遇到了没有输出问题。我需要一步步分析可能的原因。 首先,查看预编译宏定义部分。TMRA_UNIT设置为CM_TMRA_2,可能指的是使用Timer A2单元。然后检查时钟配置,TMRA_PERIPH_CLK是FCG2_PERIPH_TMRA_2,是否正确使能了时钟?代码中确实调用了FCG_Fcg2PeriphClockCmd函数,传入了这个宏,所以可能没问题。但需要确认时钟是否真的被启用,是否有其他寄存器需要配置。 接下来是PWM通道设置,TMRA_PWM_CH为TMRA_CH4,即通道4。需要确认该通道对应的GPIO是否正确配置。TMRA_PWM_PORT是GPIO_PORT_B,PIN_07,功能选择GPIO_FUNC_17。这可能涉及到引脚复用功能是否正确,需要查阅芯片手册确认该引脚是否支持Timer A的PWM输出,以及功能号是否正确。例如,某些芯片的GPIO功能可能有不同的映射,选错功能号会导致信号无法输出。 然后是Timer A的工作模式,TMRA_MD设置为锯齿波模式(SAWTOOTH),计数方向向上。周期值TMRA_PERIOD_VAL为40000-1,比较值TMRA_PWM_CMP_VAL为2-1。这里可能存在一个问题:比较值是否过小?比如,在锯齿波模式下,计数器从0增加到PERIOD,当计数值小于CMP_VAL时,输出高电平或低电平。如果CMP_VAL太小,比如1,占空比可能极低,导致肉眼难以观察到输出,或者频率过高,示波器无法捕捉。需要确认比较值是否合理,比如设置为中间值测试。 接着看代码流程。首先使能外设时钟,然后初始化Timer结构体,设置计数模式、方向和周期。然后配置PWM的比较值,初始化PWM,并使能输出。这里是否有遗漏的步骤?比如是否启动了Timer的计数?代码中没有看到TMRA_Cmd或类似的启动函数,可能Timer未开始运行,导致无输出。需要检查是否存在TMRA_Start或类似的函数调用。 另外,GPIO的配置是否正确?虽然调用了GPIO_SetFunc,但可能还需要配置GPIO的方向(输出使能)、上下拉等。但有些芯片的复用功能会自动配置,所以可能不是问题,但需要确认。 可能的错误点总结:1. Timer未启动;2. 比较值过小;3. 引脚复用配置错误;4. 时钟配置问题;5. 工作模式或计数方向设置不当。需要用户检查这些方面,特别是Timer是否启动和比较值是否合理。</think>让我们逐步分析这段代码为何没有PWM输出: $\boxed{关键问题排查步骤}$ **1. 定时器启动缺失(最常见问题)** - 代码中没有看到启动定时器的操作 - 需要添加:`TMRA_Cmd(TMRA_UNIT, ENABLE);` - 典型位置应在初始化完成后添加 **2. 比较值配置异常** - `TMRA_PWM_CMP_VAL = 2U - 1U` 会导致占空比极低: $$占空比 = \frac{CMP+1}{PERIOD+1} = \frac{2}{40000} = 0.005\%$$ - 建议调整为中间值测试,例如:`(20000U - 1U)` **3. 引脚复用验证** - 确认 `GPIO_FUNC_17` 对应TMRA_CH4输出: $$PB07 \rightarrow TMRA_CH4输出映射关系需查数据手册$$ - 检查GPIO是否配置为推挽输出模式 **4. 时钟配置验证** - 确认FCG2时钟树实际输出频率 - 添加调试代码检查时钟状态: ```c if(FCG_Fcg2GetClockFreq(FCG2_PERIPH_TMRA_2) == 0) { // 时钟未正确使能 } ``` **5. 工作模式验证** - 锯齿波模式(SAWTOOTH)的计数行为: $$0 \rightarrow PERIOD \rightarrow 0(自动重载)$$ - 比较器在上升计数时生效,需确认极性设置是否匹配 **补充检查项:** 1. 输出使能否被覆盖: ```c // 需要确认是否存在反向控制 TMRA_PWM_SetPolarity(TMRA_UNIT, TMRA_PWM_CH, TMRA_PWM_HIGH); ``` 2. 死区时间配置: ```c // 如果启用了死区控制需特殊处理 stcPwmInit.stcDeadZone.u8Enable = DISABLE; ``` 3. 中断冲突: - 检查是否因未处理的中断导致定时器挂起 **推荐调试方法:** 1. 用示波器测量GPIO引脚 2. 在GPIO初始化后强制输出高低电平验证硬件连接 3. 使用调试器查看定时器CNT寄存器是否在计数 **修正后的关键代码补充:** ```c /* 添加定时器启动命令 */ TMRA_Cmd(TMRA_UNIT, ENABLE); /* 修改比较值为可观测值 */ #define TMRA_PWM_CMP_VAL (20000U - 1U) /* 添加极性配置(根据需求选择) */ TMRA_PWM_SetPolarity(TMRA_UNIT, TMRA_PWM_CH, TMRA_PWM_HIGH); ``` $\boxed{总结}$:最可能的原因是缺少定时器启动命令和比较值过小导致不可观测的输出,建议优先补充`TMRA_Cmd()`函数调用并调整比较值测试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GreenDreamer

如果帮到了你,还望请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值