华大HC32F460 TimerA输出可调节PWM

代码使用官方库2.2.0版本的timera_triangular_wave_compare_output例程修改而来。

总结写在前面,要注意的点:
1、周期计数值PeriodVal最大值是65535,注意不要溢出,配合分频系数可以灵活改动输出PWM的频率。
2、输出PWM建议使用锯齿波,并配置周期匹配和比较匹配时输出确定的高/低电平,而不是像官方例程里那样反转电平,看了别人博客说有问题自己也试过了,确实有问题= =。
3、配置项里那个Func_Tima0/1/2使我困惑了很久(宏定义里配置的),搜帮助文档也没搜出什么名堂,后来发现可能是对应数据手册2.2引脚功能表的Func4/5/6
在这里插入图片描述
比如要使用上图PE2引脚输出PWM,就是TIMA-UNIT3-CH5,对应Func_Tima0
(不确定是不是对的,没试过)


头文件宏定义相关

/*******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/ 
/* TIMERA unit and clock definition */	 
#define TIMERA_UNIT3                    (M4_TMRA3)
#define TIMERA_UNIT3_CLOCK              (PWC_FCG2_PERIPH_TIMA3)
#define TIMERA_UNIT3_OVERFLOW_INT       (INT_TMRA3_OVF) 
	
/* TIMERA channel 1 Port/Pin definition */
#define TIMERA_UNIT3_CH5              	(TimeraCh5)
#define TIMERA_UNIT3_CH5_PORT           (PortA)
#define TIMERA_UNIT3_CH5_PIN            (Pin04)
#define TIMERA_UNIT3_CH5_FUNC           (Func_Tima1)

#define TIMERA_COUNT_OVERFLOW           (SystemCoreClock/2U/256U/10U)  //10hz 计数值最大65535

代码如下

static uint8_t u8TmraUnit3Cnt;
static uint8_t m_NowDuty;		// 当前PWM占空比
/**
 *******************************************************************************
 ** \brief Configure Timera peripheral function
 **
 ** \param [in] None
 **
 ** \retval None
 **
 ******************************************************************************/
static void Timera_Config(void)
{
    stc_timera_base_init_t stcTimeraInit;
    stc_timera_compare_init_t stcTimerCompareInit;
    stc_irq_regi_conf_t stcIrqRegiConf;
    stc_timera_hw_startup_config_t stcTimeraHwConfig;
    stc_port_init_t stcPortInit;

    /* configuration structure initialization */
    MEM_ZERO_STRUCT(stcTimeraInit);
    MEM_ZERO_STRUCT(stcIrqRegiConf);
    MEM_ZERO_STRUCT(stcTimerCompareInit);
    MEM_ZERO_STRUCT(stcTimeraHwConfig);
    MEM_ZERO_STRUCT(stcPortInit);

    /* Configuration peripheral clock */
    PWC_Fcg2PeriphClockCmd(TIMERA_UNIT3_CLOCK, Enable);

    /* Configuration TIMERA compare pin */
    PORT_SetFunc(TIMERA_UNIT3_CH5_PORT, TIMERA_UNIT3_CH5_PIN, TIMERA_UNIT3_CH5_FUNC, Disable);

    /* Configuration timera unit 2 base structure */
    stcTimeraInit.enClkDiv = TimeraPclkDiv256;				// 时钟源 PCLK1分频 100M/128
    stcTimeraInit.enCntMode = TimeraCountModeSawtoothWave;	// 锯齿波 原为三角波TimeraCountModeTriangularWave
    stcTimeraInit.enCntDir = TimeraCountDirUp;				// 向上计数
    stcTimeraInit.enSyncStartupEn = Disable;				// 关闭同步
    stcTimeraInit.u16PeriodVal = TIMERA_COUNT_OVERFLOW;		// 10Hz
    TIMERA_BaseInit(TIMERA_UNIT3, &stcTimeraInit);

    /* Configuration timera unit 2 compare structure */
    stcTimerCompareInit.u16CompareVal = stcTimeraInit.u16PeriodVal * 4u / 5u;	// 占空比20
    stcTimerCompareInit.enStartCountOutput = TimeraCountStartOutputLow;			// 计数开始时输出低电平
    stcTimerCompareInit.enStopCountOutput = TimeraCountStopOutputLow;			// 计数停止时输出低电平
    stcTimerCompareInit.enCompareMatchOutput = TimeraCompareMatchOutputHigh;	// 比较匹配时输出高电平(不要反转!)
    stcTimerCompareInit.enPeriodMatchOutput = TimeraPeriodMatchOutputLow;	// 周期匹配时输出低电平(不要反转!)
    stcTimerCompareInit.enSpecifyOutput = TimeraSpecifyOutputInvalid;			// 强制端口状态设定无效
//    stcTimerCompareInit.enCacheEn = Enable;										//
//    stcTimerCompareInit.enTriangularTroughTransEn = Enable;						// 
//    stcTimerCompareInit.enTriangularCrestTransEn = Disable;						// 
//    stcTimerCompareInit.u16CompareCacheVal = stcTimerCompareInit.u16CompareVal;	// 比较缓存值
	
    /* Configure Channel 2 */
    TIMERA_CompareInit(TIMERA_UNIT3, TIMERA_UNIT3_CH5, &stcTimerCompareInit);	// 初始化定时器比较功能
    TIMERA_CompareCmd(TIMERA_UNIT3, TIMERA_UNIT3_CH5, Enable);					// 使能定时器比较功能

	/* Enable period count interrupt */
    TIMERA_IrqCmd(TIMERA_UNIT3, TimeraIrqOverflow, Enable);		// 中断使能
    /* Interrupt of timera unit 2 */
    stcIrqRegiConf.enIntSrc = TIMERA_UNIT3_OVERFLOW_INT;
    stcIrqRegiConf.enIRQn = Int013_IRQn;
    stcIrqRegiConf.pfnCallback = &TimeraUnit3_IrqCallback;		// 计时周期匹配中断
    enIrqRegistration(&stcIrqRegiConf);
    NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
    NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
    NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
	
	TIMERA_Cmd(TIMERA_UNIT3, Enable);		// 使能启动定时器A
	
}

// 周期匹配中断回调
static void TimeraUnit3_IrqCallback(void)
{
    u8TmraUnit3Cnt++;
    
	if(u8TmraUnit3Cnt >= 20u)      //2s
    {
		PWM_ChangeDuty(m_NowDuty+20);
        u8TmraUnit3Cnt = 0u;
    }
    TIMERA_ClearFlag(TIMERA_UNIT3, TimeraFlagOverflow);
}

/** 修改PWM占空比
 *******************************************************************************
 ** \brief Timera unit2 CH2 change PWM Duty Ratio
 **
 ** \param [in] NewDuty 要修改的占空比百分比数值,范围0-100
 **
 ** \retval None
 **
 ******************************************************************************/
void PWM_ChangeDuty(uint8_t NewDuty)
{
	uint16_t u16TimerPeriod = 0u, u16DutyCycle = 0u;
    u16DutyCycle = TIMERA_GetCompareValue(TIMERA_UNIT3, TIMERA_UNIT3_CH5);	// 比较值
    u16TimerPeriod = TIMERA_GetPeriodValue(TIMERA_UNIT3);					// 计数周期值

    if (NewDuty > 100)
    {
        NewDuty = 0u;
    }
	u16DutyCycle = u16TimerPeriod *(100-NewDuty)/100;
	TIMERA_SetCompareValue(TIMERA_UNIT3, TIMERA_UNIT3_CH5, u16DutyCycle);		// 设置比较值
	m_NowDuty = NewDuty;
}	 

一些关于代码的说明:
TIMA时钟源是PCLK1,官方例程里系统时钟是200MHz(SystemCoreClock),PCLK1分频系数为2,既PLCK1=100MHZ。
代码的结果是每隔2秒钟输出的占空比会增加20%,增加到100%后变回0%(输出的PWM占空比含100和0)。


参考博客
TimerA输出可调占空比PWM——华大HC32F460
HC32f460 如何动态改pwm的占空比
关于HC32F460 输出可调占空比PWM波遇到的问题记录
【技术问答】hc32f460系列输出可调占空比的PWM波
【HC32F448测评】+用高级定时器6输出PWM

### HC32F460 Microcontroller TimerA PWM Output Example Code and Tutorial #### Overview of TimerA Configuration Parameters In the `timera_capture.h` file, several predefined parameters configure the TimerA module. These definitions specify units, channels, ports, pins, and functions associated with TimerA operations on the HC32F460 microcontroller[^1]. For instance: - The TimerA unit is defined as `(M4_TMRA1)` - Its clock source comes from peripheral function control register bit for TimerA1 `(PWC_FCG2_PERIPH_TIMA1)` - Channel 5 port configuration involves Port E Pin 8 functioning specifically for Timer A channel 0 `(Func_Tima0)`. #### Common Issues Encountered During Development During development using the HC32F460 to drive a three-axis gimbal motor via PWM signals, developers encountered issues where motors would randomly reverse direction upon startup due to incorrect PWM duty cycle settings at either extreme values like 0% or 100%. This anomaly caused unpredictable behavior in which complementary outputs were observed instead of expected ones[^2]. To avoid such problems, it's crucial that when configuring PWM through TimerA, ensure proper initialization avoiding edge cases especially near zero or full duty cycles. #### Sample Initialization Function Using TimerA for PWM Generation Below demonstrates how one might initialize TimerA for generating PWM waveforms while taking precautions against known pitfalls: ```c #include "hc32f460.h" void Timera_Init(void){ stc_timera_init_t stcTimeraInit; // Initialize system core clock. SystemCoreClockUpdate(); // Enable timerA1 clock gate. PWC_FcgPeriphClockCmd(PWC_FCG2_PERIPH_TIMA1, ENABLE); // Configure TimerA mode selection. M4_TMRA1->CFG_f.MDSEL = TMRA_MODE_PWM; // Set period value based on desired frequency. uint32
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值