查看: 300|回复: 0

[主题月] 【2026电机控制】+ 学习FRDM-MCXC444的PWM例程

[复制链接]
  • TA的每日心情
    开心
    昨天 20:34
  • 签到天数: 1437 天

    连续签到: 8 天

    [LV.10]以坛为家III

    31

    主题

    4999

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    7271
    最后登录
    2026-10-23
    发表于 2026-7-20 16:31:36 | 显示全部楼层 |阅读模式
    本帖最后由 suncat0504 于 2026-7-20 16:35 编辑

    本次电机月活动中我报名参加了,参加的项目是使用FRDM-MCXC444开发板制作《温控自动摇头桌面风扇》。
    这个风扇的制作,在我看来,需要两个关键点:
    1、量化温度数据
    2、使用量化的温度数据,改变PWM的占空比,控制风扇的转速。
    所以当收到FRDM-MCXC444开发板后,第一件事儿是就是熟悉这个开发板的开发IDE。因为是恩智浦的开发板,毫无疑问使用恩智浦自己的IDE是最快、最好的选择。
    在这个IDE中提供了Installed SDKs功能,可以从官网快速安装指定型号的开发板对应的SDK。安装好SDK,可以使用“Import SDK example(s)”功能导入学习例程。
    我从例程库中导入frdmmcxc444_tpm_simple_pwm例程。这个例程提供了一个产生PWM信号的例子,可以直接拿来用。我初步打算在此基础上做修改,并加上温度采集处理,利用温度值控制PWM的占空比,控制风扇的转速。
    测试的第一步是先熟悉PWM程序。这个例程的主程序:
    1. int main(void) {
    2.         tpm_config_t tpmInfo;                     // TPM模块配置结构体
    3.         tpm_chnl_pwm_signal_param_t tpmParam;     // PWM通道参数结构体
    4.         uint8_t control;                          // 用于保存通道控制寄存器的原始值

    5.         // 初始化板级硬件(时钟、引脚、调试串口、PWM输出引脚的复用功能配置等)
    6.         BOARD_InitHardware();

    7.         PRINTF("MCUX SDK version: %s\r\n", MCUXSDK_VERSION_FULL_STR);

    8.         /* Print a note to terminal */
    9.         PRINTF("\r\nTPM example to output center-aligned PWM signal\r\n");
    10.         PRINTF(
    11.                         "\r\nIf an LED is connected to the TPM pin, you will see a change in LED brightness if you enter different "
    12.                                         "values");
    13.         PRINTF(
    14.                         "\r\nIf no LED is connected to the TPM pin, then probe the signal using an oscilloscope");

    15.         // 获取默认配置
    16.         TPM_GetDefaultConfig(&tpmInfo);

    17.         // 根据目标PWM频率(DEMO_PWM_FREQUENCY)和TPM模块的输入时钟(TPM_SOURCE_CLOCK),
    18.         // 自动计算出一个合适的时钟分频系数(prescale),确保计数器能精确产生所需的频率。
    19.         tpmInfo.prescale = TPM_CalculateCounterClkDiv(BOARD_TPM_BASEADDR, DEMO_PWM_FREQUENCY, TPM_SOURCE_CLOCK);

    20.         // 将配置写入硬件寄存器,启动TPM模块(但此时定时器还未开始计数)
    21.         TPM_Init(BOARD_TPM_BASEADDR, &tpmInfo);

    22.         /* Configure tpm params with frequency 24kHZ */
    23.         // 指定通道(对应GPIO哪个引脚)
    24.         tpmParam.chnlNumber = (tpm_chnl_t) BOARD_TPM_CHANNEL;

    25.     // 定义"有效电平"(高电平有效或低电平有效)
    26.         tpmParam.level = TPM_LED_ON_LEVEL;

    27.         // 初始占空比(全局变量,最开始0%)
    28.         tpmParam.dutyCyclePercent = updatedDutycycle;
    29.         if (kStatus_Success != TPM_SetupPwm(BOARD_TPM_BASEADDR, &tpmParam, 1U, kTPM_CenterAlignedPwm, DEMO_PWM_FREQUENCY, TPM_SOURCE_CLOCK)) {
    30.                 PRINTF("\r\nSetup PWM fail!\r\n");
    31.                 return -1;
    32.         }

    33.         // 开始运行TPM计数器,PWM信号正式开始在引脚上输出
    34.         TPM_StartTimer(BOARD_TPM_BASEADDR, kTPM_SystemClock);

    35.         // 获取当前通道的控制寄存器值
    36.         control = TPM_GetChannelContorlBits(BOARD_TPM_BASEADDR, (tpm_chnl_t) BOARD_TPM_CHANNEL);

    37.         while (1) {


    38.                 //updatedDutycycle = getCharValue * 10U;
    39.                 // 每1000一个等级
    40.             cnt = (cnt+1)% (99 * duan + 1);

    41.                 if ((cnt/duan) !=  oldDutycycle) {
    42.                         // 保存本次占空比
    43.                         oldDutycycle = cnt/duan;
    44.                         // 占空比以10个单位改变,避免太频繁,导致闪烁
    45.                         if ((oldDutycycle%seg) == 0) {
    46.                                 // 禁用通道输出(避免更新过程中产生毛刺)
    47.                                 TPM_DisableChannel(BOARD_TPM_BASEADDR, (tpm_chnl_t) BOARD_TPM_CHANNEL);

    48.                                 // 更新占空比
    49.                                 if (kStatus_Success == TPM_UpdatePwmDutycycle(BOARD_TPM_BASEADDR, (tpm_chnl_t) BOARD_TPM_CHANNEL, kTPM_CenterAlignedPwm, oldDutycycle)) {
    50.                                         PRINTF("The duty cycle was successfully updated! %d, %d  \r\n", cnt, oldDutycycle);
    51.                                 }

    52.                                 // 开通道,使更新后占空比体现在通道(引脚PTD5)上
    53.                                 TPM_EnableChannel(BOARD_TPM_BASEADDR, (tpm_chnl_t) BOARD_TPM_CHANNEL, control);
    54.                         }
    55.                 }
    56.         }
    57. }
    复制代码

    根据代码和电路原理图,
    图片1.png
    程序运行后,PWN的输出信号由J2的PTD5引脚输出,同时板载的绿色LED会根据PWM的占空比调整亮度。改变占空比需要通过串口输入“0” - “9“的字符实现,分别对应0 - 90%的占空比,数值越大,亮度越低。 在此程序的基础上做简单修改,就可以改成呼吸灯中的渐灭方式的处理模式。
    1. int main(void) {
    2.         tpm_config_t tpmInfo;                     // TPM模块配置结构体
    3.         tpm_chnl_pwm_signal_param_t tpmParam;     // PWM通道参数结构体
    4.         uint8_t control;                          // 用于保存通道控制寄存器的原始值

    5.         // 初始化板级硬件(时钟、引脚、调试串口、PWM输出引脚的复用功能配置等)
    6.         BOARD_InitHardware();

    7.         PRINTF("MCUX SDK version: %s\r\n", MCUXSDK_VERSION_FULL_STR);

    8.         /* Print a note to terminal */
    9.         PRINTF("\r\nTPM example to output center-aligned PWM signal\r\n");
    10.         PRINTF(
    11.                         "\r\nIf an LED is connected to the TPM pin, you will see a change in LED brightness if you enter different "
    12.                                         "values");
    13.         PRINTF(
    14.                         "\r\nIf no LED is connected to the TPM pin, then probe the signal using an oscilloscope");

    15.         // 获取默认配置
    16.         TPM_GetDefaultConfig(&tpmInfo);

    17.         // 根据目标PWM频率(DEMO_PWM_FREQUENCY)和TPM模块的输入时钟(TPM_SOURCE_CLOCK),
    18.         // 自动计算出一个合适的时钟分频系数(prescale),确保计数器能精确产生所需的频率。
    19.         tpmInfo.prescale = TPM_CalculateCounterClkDiv(BOARD_TPM_BASEADDR, DEMO_PWM_FREQUENCY, TPM_SOURCE_CLOCK);

    20.         // 将配置写入硬件寄存器,启动TPM模块(但此时定时器还未开始计数)
    21.         TPM_Init(BOARD_TPM_BASEADDR, &tpmInfo);

    22.         /* Configure tpm params with frequency 24kHZ */
    23.         // 指定通道(对应GPIO哪个引脚)
    24.         tpmParam.chnlNumber = (tpm_chnl_t) BOARD_TPM_CHANNEL;

    25.     // 定义"有效电平"(高电平有效或低电平有效)
    26.         tpmParam.level = TPM_LED_ON_LEVEL;

    27.         // 初始占空比(全局变量,最开始0%)
    28.         tpmParam.dutyCyclePercent = updatedDutycycle;
    29.         if (kStatus_Success != TPM_SetupPwm(BOARD_TPM_BASEADDR, &tpmParam, 1U, kTPM_CenterAlignedPwm, DEMO_PWM_FREQUENCY, TPM_SOURCE_CLOCK)) {
    30.                 PRINTF("\r\nSetup PWM fail!\r\n");
    31.                 return -1;
    32.         }

    33.         // 开始运行TPM计数器,PWM信号正式开始在引脚上输出
    34.         TPM_StartTimer(BOARD_TPM_BASEADDR, kTPM_SystemClock);

    35.         // 获取当前通道的控制寄存器值
    36.         control = TPM_GetChannelContorlBits(BOARD_TPM_BASEADDR, (tpm_chnl_t) BOARD_TPM_CHANNEL);

    37.         while (1) {
    38.                 // 每1000一个等级
    39.             cnt = (cnt+1)% (99 * duan + 1);

    40.                 if ((cnt/duan) !=  oldDutycycle) {
    41.                         // 保存本次占空比
    42.                         oldDutycycle = cnt/duan;
    43.                         // 占空比以10个单位改变,避免太频繁,导致闪烁
    44.                         if ((oldDutycycle%seg) == 0) {
    45.                                 // 禁用通道输出(避免更新过程中产生毛刺)
    46.                                 TPM_DisableChannel(BOARD_TPM_BASEADDR, (tpm_chnl_t) BOARD_TPM_CHANNEL);

    47.                                 // 更新占空比
    48.                                 if (kStatus_Success == TPM_UpdatePwmDutycycle(BOARD_TPM_BASEADDR, (tpm_chnl_t) BOARD_TPM_CHANNEL, kTPM_CenterAlignedPwm, oldDutycycle)) {
    49.                                         PRINTF("The duty cycle was successfully updated! %d, %d  \r\n", cnt, oldDutycycle);
    50.                                 }

    51.                                 // 开通道,使更新后占空比体现在通道(引脚PTD5)上
    52.                                 TPM_EnableChannel(BOARD_TPM_BASEADDR, (tpm_chnl_t) BOARD_TPM_CHANNEL, control);
    53.                         }
    54.                 }
    55.         }
    56. }
    复制代码

    运行效果:
    demo.gif

    哎...今天够累的,签到来了~
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2026-10-24 01:11 , Processed in 0.073207 second(s), 19 queries , Redis On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表