小华芯片HC32F460之TMR6输出互补PWM

平台:keil V5.31

宏定义:

复制代码
/* ================================================================
   引脚和定时器单元定义
   ================================================================ */

// 第一路:TMR6_1, PA8/PB13
#define TMR6_1_UNIT         CM_TMR6_1
#define PWM1_PORT_A         GPIO_PORT_A
#define PWM1_PIN_A          GPIO_PIN_08
#define PWM1_PORT_B         GPIO_PORT_B
#define PWM1_PIN_B          GPIO_PIN_13

// 第二路:TMR6_2, PA9/PB14
#define TMR6_2_UNIT         CM_TMR6_2
#define PWM2_PORT_A         GPIO_PORT_A
#define PWM2_PIN_A          GPIO_PIN_09
#define PWM2_PORT_B         GPIO_PORT_B
#define PWM2_PIN_B          GPIO_PIN_14

// 第三路:TMR6_3, PA10/PB15
#define TMR6_3_UNIT         CM_TMR6_3
#define PWM3_PORT_A         GPIO_PORT_A
#define PWM3_PIN_A          GPIO_PIN_10
#define PWM3_PORT_B         GPIO_PORT_B
#define PWM3_PIN_B          GPIO_PIN_15

#define PWM_FUNC            GPIO_FUNC_3

/* ================================================================
   PWM 参数配置
   ================================================================ */

#define PWM_FREQ_HZ         20000U              // 20kHz PWM 频率
#define SYSTEM_CLOCK_HZ     200000000U          // 200MHz 系统时钟 (PCLK0)
#define PWM_PERIOD          (SYSTEM_CLOCK_HZ / PWM_FREQ_HZ)  // 10000

// 死区时间: 1us
#define DEAD_TIME_NS        1000U
#define DEAD_TIME_COUNT     ((DEAD_TIME_NS * (SYSTEM_CLOCK_HZ / 1000000U)) / 1000U)  // 200

配置

复制代码
static void GPIO_ConfigSinglePin(uint8_t u8Port, uint16_t u16Pin)
{
    stc_gpio_init_t stcGpioInit;

    GPIO_StructInit(&stcGpioInit);
    stcGpioInit.u16PinDir       = PIN_DIR_OUT;
    stcGpioInit.u16PinOutputType= PIN_OUT_TYPE_CMOS;
    stcGpioInit.u16PinDrv       = PIN_HIGH_DRV;
    stcGpioInit.u16PinAttr      = PIN_ATTR_DIGITAL;

    GPIO_SetFunc(u8Port, u16Pin, PWM_FUNC);
    GPIO_Init(u8Port, u16Pin, &stcGpioInit);
}

void GPIO_Config(void)
{
    // 配置 PA8, PA9, PA10
    GPIO_ConfigSinglePin(PWM1_PORT_A, PWM1_PIN_A);
    GPIO_ConfigSinglePin(PWM2_PORT_A, PWM2_PIN_A);
    GPIO_ConfigSinglePin(PWM3_PORT_A, PWM3_PIN_A);

    // 配置 PB13, PB14, PB15
    GPIO_ConfigSinglePin(PWM1_PORT_B, PWM1_PIN_B);
    GPIO_ConfigSinglePin(PWM2_PORT_B, PWM2_PIN_B);
    GPIO_ConfigSinglePin(PWM3_PORT_B, PWM3_PIN_B);
}

void TMR6_SinglePWM_Init(CM_TMR6_TypeDef *tmrUnit, 
                          uint32_t fcgPeriph,
                          uint32_t period, 
                          uint32_t deadTime,
                          uint8_t duty)
{
    stc_tmr6_init_t stcTmr6Init;
    stc_tmr6_pwm_init_t stcPwmInit;

    // 1. 使能 Timer6 时钟
    FCG_Fcg2PeriphClockCmd(fcgPeriph, ENABLE);

    // 2. 基础计数配置
    TMR6_StructInit(&stcTmr6Init);
    stcTmr6Init.u8CountSrc             = TMR6_CNT_SRC_SW;       // 软件计数模式
    stcTmr6Init.sw_count.u32CountMode  = TMR6_MD_SAWTOOTH;      // 锯齿波模式 (向上计数)
    stcTmr6Init.sw_count.u32CountDir   = TMR6_CNT_UP;           // 向上计数
    stcTmr6Init.sw_count.u32ClockDiv   = TMR6_CLK_DIV1;         // 不分频
    stcTmr6Init.u32PeriodValue         = period;                // 周期值
    TMR6_Init(tmrUnit, &stcTmr6Init);

    // 3. 死区时间配置
    //   先使能死区功能
    TMR6_DeadTimeFuncCmd(tmrUnit, ENABLE);
    
    //   配置死区寄存器(向上计数阶段)
    TMR6_SetDeadTimeValue(tmrUnit, TMR6_DEADTIME_REG_UP_A, deadTime);
    TMR6_SetDeadTimeValue(tmrUnit, TMR6_DEADTIME_REG_UP_B, deadTime);
    
    //   配置死区寄存器(向下计数阶段),如果使用锯齿波模式,此值可设相同
    TMR6_SetDeadTimeValue(tmrUnit, TMR6_DEADTIME_REG_DOWN_A, deadTime);
    TMR6_SetDeadTimeValue(tmrUnit, TMR6_DEADTIME_REG_DOWN_B, deadTime);

    // 4. 配置 PWMA 通道(主通道)
    TMR6_PWM_StructInit(&stcPwmInit);
    stcPwmInit.u32CompareValue          = (period * duty) / 100;  // 占空比
    stcPwmInit.u32StartPolarity         = TMR6_PWM_LOW;           // 计数开始输出低
    stcPwmInit.u32StopPolarity          = TMR6_PWM_LOW;           // 计数停止输出低
    stcPwmInit.u32CompareMatchPolarity  = TMR6_PWM_HIGH;          // 比较匹配翻转为高
    stcPwmInit.u32PeriodMatchPolarity   = TMR6_PWM_LOW;           // 周期匹配翻转为低
    stcPwmInit.u32StartStopHold         = TMR6_PWM_START_STOP_CHANGE;
    TMR6_PWM_Init(tmrUnit, TMR6_CH_A, &stcPwmInit);

    // 5. 配置 PWMB 通道(互补通道,极性相反)
    TMR6_PWM_StructInit(&stcPwmInit);
    stcPwmInit.u32CompareValue          = (period * duty) / 100;
    stcPwmInit.u32StartPolarity         = TMR6_PWM_HIGH;          // 与PWMA相反
    stcPwmInit.u32StopPolarity          = TMR6_PWM_HIGH;          // 与PWMA相反
    stcPwmInit.u32CompareMatchPolarity  = TMR6_PWM_LOW;           // 与PWMA相反
    stcPwmInit.u32PeriodMatchPolarity   = TMR6_PWM_HIGH;          // 与PWMA相反
    stcPwmInit.u32StartStopHold         = TMR6_PWM_START_STOP_CHANGE;
    TMR6_PWM_Init(tmrUnit, TMR6_CH_B, &stcPwmInit);

    // 6. 设置引脚功能为比较输出
    TMR6_SetFunc(tmrUnit, TMR6_CH_A, TMR6_PIN_CMP_OUTPUT);
    TMR6_SetFunc(tmrUnit, TMR6_CH_B, TMR6_PIN_CMP_OUTPUT);

    // 7. 使能 PWM 输出
    TMR6_PWM_OutputCmd(tmrUnit, TMR6_CH_A, ENABLE);
    TMR6_PWM_OutputCmd(tmrUnit, TMR6_CH_B, ENABLE);
}

void TMR6_AllPWM_Init(void)
{
    // 初始化三路,初始占空比50%
    TMR6_SinglePWM_Init(CM_TMR6_1, FCG2_PERIPH_TMR6_1, PWM_PERIOD, DEAD_TIME_COUNT, 50);
    TMR6_SinglePWM_Init(CM_TMR6_2, FCG2_PERIPH_TMR6_2, PWM_PERIOD, DEAD_TIME_COUNT, 50);
    TMR6_SinglePWM_Init(CM_TMR6_3, FCG2_PERIPH_TMR6_3, PWM_PERIOD, DEAD_TIME_COUNT, 50);
}

设置

复制代码
void TMR6_StartAll(void)
{
    TMR6_Start(CM_TMR6_1);
    TMR6_Start(CM_TMR6_2);
    TMR6_Start(CM_TMR6_3);
}

void TMR6_StopAll(void)
{
    TMR6_Stop(CM_TMR6_1);
    TMR6_Stop(CM_TMR6_2);
    TMR6_Stop(CM_TMR6_3);
}

void TMR6_SetDuty(CM_TMR6_TypeDef *tmrUnit, uint8_t duty)
{
    uint32_t compareValue;
    
    if (duty > 100) duty = 100;
    compareValue = (PWM_PERIOD * duty) / 100;
    
    // 更新 PWMA 和 PWMB 的比较值(两者相同)
    TMR6_SetCompareValue(tmrUnit, TMR6_CMP_REG_A, compareValue);
    TMR6_SetCompareValue(tmrUnit, TMR6_CMP_REG_B, compareValue);
}

void TMR6_SyncStartAll(void)
{
    // 使用软件同步功能同时启动 TMR6_1, TMR6_2, TMR6_3
    TMR6_SWSyncStart(TMR6_SW_SYNC_ALL);
}

void TMR6_SyncStopAll(void)
{
    TMR6_SWSyncStop(TMR6_SW_SYNC_ALL);
}

主函数

复制代码
int main(void)
{
    // 系统时钟初始化 (假设已配置为200MHz)
//     SystemClock_Config();

	    /* Unlock peripherals or registers */
    LL_PERIPH_WE(LL_PERIPH_GPIO | LL_PERIPH_EFM | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU |	LL_PERIPH_SRAM);
    // 配置GPIO
    GPIO_Config();

    // 初始化三路互补PWM
    TMR6_AllPWM_Init();

    // 启动所有PWM(方式1:分别启动)
    // TMR6_StartAll();
    
    // 或使用软件同步同时启动(方式2:推荐)
    TMR6_SyncStartAll();

    while (1)
    {
        // 示例:动态调整占空比
////        TMR6_SetDuty(CM_TMR6_1, 30);  // 第一路 30%
////        TMR6_SetDuty(CM_TMR6_2, 60);  // 第二路 60%
////        TMR6_SetDuty(CM_TMR6_3, 90);  // 第三路 90%
//        delay_ms(1000);
    }
}

实验结果:

相关推荐
周洲083018 小时前
STM32 串口底层深度解析|USART 中断标志、硬件 FIFO,乱码根源底层定位
stm32·单片机·嵌入式硬件
女神下凡1 天前
芯参谋(29):UFS UMCP 软件设计规范
arm开发·单片机·嵌入式硬件
RISCV_Explorer1 天前
RISC-V电源管理与低功耗实战——WFI指令、电源域划分与唤醒路径设计
单片机·嵌入式硬件·risc-v
zd8451015001 天前
支持双向输入信号的开关量电路
单片机·嵌入式硬件
齐落山大勇1 天前
【裸机程序】IMX 6ULL的中断机制的理解
单片机·嵌入式硬件
cu1431 天前
细谈GM8229的具体功能与其应用
c语言·c++·人工智能·单片机
HRTOS1 天前
HRTOS 任务优先级与调度模式说明
单片机·嵌入式硬件·系统架构·51单片机
cu1431 天前
细谈GM7123C的具体功能与其应用
c语言·c++·人工智能·嵌入式硬件
嵌入式分享1 天前
驱动之路#44:硬件 I2C 和软件 I2C 谁更坑?
linux·嵌入式硬件
嵌入式分享1 天前
嵌入式分享#19:《嵌入式外设调试思路》--I2C设备篇
单片机·嵌入式硬件