小华芯片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);
    }
}

实验结果:

相关推荐
Freak嵌入式15 小时前
MCU 低功耗模式解析:时钟门控、电源门控、深度休眠
人工智能·python·单片机·嵌入式硬件·开源·依赖倒置原则·micropython
国科安芯15 小时前
FreeRTOS RISC-V 浮点上下文切换移植:在 IAR 工程中完整保存 FPU 寄存器
java·开发语言·单片机·嵌入式硬件·算法·系统架构·risc-v
躺不平的理查德16 小时前
STM32时钟树(Clock Tree)
stm32·单片机·嵌入式硬件
Javenwww17 小时前
STM32中DMA的使用——串口数据的DMA传输
单片机
qq_4017004117 小时前
经典的电压基准源电路
单片机·嵌入式硬件
茯苓gao18 小时前
嵌入式开发笔记:电机参数辨识与自学习完全指南——从电气参数到机械特性的深度解析
笔记·嵌入式硬件·学习
西安景驰电子18 小时前
PCIe 授时卡原理及应用
运维·服务器·windows·单片机·嵌入式硬件·fpga开发
派勤电子20 小时前
5G物联网网关工控主板选型指南(超小尺寸工业级嵌入式硬件解决方案)
嵌入式硬件·工业网关·工控主板·工控主板选型·嵌入式工控主板·5g物联网网关·超小尺寸工控主板
&Hello Code20 小时前
2.一套可落地的 STM32 六层架构:基础工程框架搭建
stm32·嵌入式硬件·架构