使用外设:高级定时器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 中断
}