HC32L130单片机可调独立PWM输出,调试过程的问题记录

文章详细描述了在STM32平台上使用高级定时器TIM4实现25kHzPWM波输出的过程,涉及周期设置、比较值配置、三角波与锯齿波选择以及电平设置问题。作者探讨了如何调整周期值以匹配PWM频率,并注意到计数模式对占空比的影响。
摘要由CSDN通过智能技术生成
使用外设:高级定时器tim4;
引脚PD01,端口复用:GpioAf2;
实现功能:单通道25kHz PWM波输出,占空比可调
1.关于PWM波周期设置:Adt_SetPeriod(M0P_ADTIM4, u16Period);                 //周期值配置

我的理解:1/PWM频率  = 1/(系统时钟➗分频系数➗u16Period)                  //公式1

我要实现25kHz的pwm波形,即周期是1/25kHz = 40us;但按照上面公式,上述 =系统时钟4MHz ➗2分频 ➗u16Period;计算出u16Period = 80。
   

2.比较值的设置问题:

2.1 比较输出时:通道A的值填充到比较基准值寄存器(GCMAR)中,若开启缓存,则比较基准   值缓存寄存器(GCMCR)自动填充到   ==》  比较基准值寄存器(GCMAR)中(所以开启缓存就要配置缓存寄存器)

2.2 输入捕获时:通道A的值填充到比较基准值寄存器(GCMAR)中,若开启缓存,则比较基准   值寄存器(GCMAR)自动填充到 ==》比较基准值缓存寄存器(GCMCR)中。

2.3通道B同上,则比较基准值寄存器(GCMBR)《==》比较基准值缓存寄存器(GCMDR)

 3.三角波和锯齿波的选择:

3.1 三角波计数会有从上往下,从下往上的往返两次,一个周期会触发两次  计数值 = 比较值;

会出现实际占空比 = 设计的一半,计数值等于比较值时,占空比达到最大 = 50%。

3.2 锯齿波计数只有一个方向,所以一个周期只有触发一次 计数值 = 比较值;

4.计数值与周期值,比较值匹配时的电平设置问题
4.1 周期值匹配电平保持,比较值匹配电平翻转:

需注意,此状态存在电平不确定性,比如设置的占空比为10%,则开启时,则占空比会是10%,也可能出现90%(实测效果如此,具体原因未深究)

4.2 周期值匹配电平高/低,比较值匹配电平高/低:

出现占空比 = 实际设计的一半;

4.3 周期值匹配电平高/低,比较值匹配电平翻转:

目前这么设置实测效果稳定;

5.最后代码,有问题恳请指正(刚发现官方应用指南里其实更详细)
void hal_Fan_PWMConfig(uint16_t u16CHB_PWMDuty)//PWM输出配置
{
		uint16_t u16Period;				//周期值
	  en_adt_compare_t          enAdtCompare;
    stc_adt_basecnt_cfg_t     stcAdtBaseCntCfg;
    stc_adt_CHxX_port_cfg_t   stcAdtTIM4BCfg;

    DDL_ZERO_STRUCT(stcAdtBaseCntCfg);
    DDL_ZERO_STRUCT(stcAdtTIM4BCfg);
	
    Sysctrl_SetPeripheralGate(SysctrlPeripheralAdvTim, TRUE);     //ADT外设时钟使能

    stcAdtBaseCntCfg.enCntMode = AdtTriangleModeB;                //三角波A   实测波形不同占空比也不同,但周期相同
    stcAdtBaseCntCfg.enCntDir = AdtCntUp;													//方向:向上计数
    stcAdtBaseCntCfg.enCntClkDiv = AdtClkPClk0;										//系统时钟 不分频
    Adt_Init(M0P_ADTIM4, &stcAdtBaseCntCfg);                      //ADT载波、计数模式、时钟配置
    
		u16Period	= SystemCoreClock/(2*FAN_PWM_HZ*(stcAdtBaseCntCfg.enCntClkDiv+1));		//周期 = 系统时钟/(2 * 分频系数 * pwm频率)
	
    Adt_SetPeriod(M0P_ADTIM4, u16Period);                         //周期值  
	
		enAdtCompare = AdtCompareB;
    Adt_SetCompareValue(M0P_ADTIM4, enAdtCompare, u16CHB_PWMDuty);    //通用比较基准值寄存器B设置
																																		//占空比  =  	(u16Period - u16CHB_PWMDuty)/u16Period     
																																		//但是:外部有mos管,逻辑取反 :占空比 = u16CHB_PWMDuty / u16Period
//		enAdtCompare = AdtCompareD;
//		Adt_SetCompareValue(M0P_ADTIM4, enAdtCompare, u16CHB_PWMDuty);    //通用比较缓存寄存器D设置
//	  Adt_EnableValueBuf(M0P_ADTIM4, AdtCHxB, TRUE);  //缓存传送B使能//笔记:使能此处,则需要配置缓存寄存器D

    stcAdtTIM4BCfg.enCap = AdtCHxCompareOutput;    //比较输出模式
    stcAdtTIM4BCfg.bOutEn = TRUE;                  //CHB输出使能
    stcAdtTIM4BCfg.enPerc = AdtCHxPeriodLow;      //计数值与周期匹配时电平低/高   //此处要是确定的电平,设置为保持会出现占空比随机出现相反的情况    
    stcAdtTIM4BCfg.enCmpc = AdtCHxCompareHigh;      //计数值与比较值B匹配时,CHB电平翻转
    stcAdtTIM4BCfg.enStaStp = AdtCHxStateSelSS;    //CHB起始结束电平由STACA与STPCA控制
    stcAdtTIM4BCfg.enStaOut = AdtCHxPortOutLow;   //CHB起始电平为低
    stcAdtTIM4BCfg.enStpOut = AdtCHxPortOutLow;    //CHB结束电平为低
    Adt_CHxXPortCfg(M0P_ADTIM4, AdtCHxB, &stcAdtTIM4BCfg);   //端口CHB配置
		
//		Adt_SetDTUA(M0P_ADTIM4, 0);  //CNT向上计数时的死区时间,GCMBR = GCMAR - DTUAR
//    Adt_SetDTDA(M0P_ADTIM4, 0);  //CNT向下计数时的死区时间,GCMBR = GCMAR - DTDAR
//    Adt_CfgDT(M0P_ADTIM4, TRUE, TRUE); //死区功能禁用,并且DTUAR和DTDAR自动相等			//笔记:只有A B通道都输出,死区才使能
			
//    Adt_ClearAllIrqFlag(M0P_ADTIM4);          //清标志位
//    Adt_CfgIrq(M0P_ADTIM4, AdtUDFIrq, TRUE);  //下溢中断配置
//    EnableNvic(ADTIM4_IRQn, IrqLevel3, TRUE); //使能AdvTimer4 中断
		
}

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
HC32L130单片机的外部中断可以通过以下步骤进行配置: 1. 配置外部中断引脚,确定所需的中断引脚及其所属的GPIO口。 2. 配置中断触发方式,包括上升沿触发、下降沿触发、边沿触发等。 3. 使能中断,开启外部中断的总开关。 下面是一个简单的外部中断配置例程: ```c #include "hc32l130.h" void ExtIntInit(void) { // 配置中断引脚所属的GPIO口 M0P_GPIO->PAADS &= ~(1 << 0); // PA0不使用模拟功能 M0P_GPIO->PAOE &= ~(1 << 0); // PA0不使用开漏输出 M0P_GPIO->PAPU &= ~(1 << 0); // PA0不使用上拉 M0P_GPIO->PADIR &= ~(1 << 0); // PA0设置为输入 M0P_GPIO->PASTP |= (1 << 0); // PA0不作为休眠唤醒引脚 M0P_GPIO->PAINEN |= (1 << 0); // PA0使能输入 // 配置中断触发方式为上升沿触发 M0P_EXTINT->ENIR_f.EN0 = 1; // 使能中断0 M0P_EXTINT->EINT0_f.ELVL = 1; // 上升沿触发 // 使能外部中断 NVIC_ClearPendingIRQ(EXTI0_IRQn); // 清除中断标志 NVIC_SetPriority(EXTI0_IRQn, 3); // 设置中断优先级 NVIC_EnableIRQ(EXTI0_IRQn); // 使能中断 } void EXTI0_IRQHandler(void) { // 处理中断事件 // ... // 清除中断标志 M0P_EXTINT->EIFR_f.EIF0 = 1; } int main(void) { // 系统初始化 // ... // 初始化外部中断 ExtIntInit(); while (1) { // 主循环 // ... } return 0; } ``` 在上面的例程中,我们首先配置了PA0口作为中断引脚,并设置了中断触发方式为上升沿触发。然后通过使能中断,开启了外部中断的总开关。在中断处理函数中,我们可以处理中断事件,并清除中断标志以便下一次中断触发。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值