本文主要是介绍PWM移相以及占空比可变(上),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本文以 STC8H 芯片为例,输出两路相位可调以及占空比可调的PWM(CH1 CH2)。
一、PWM输出原理
我们所使用的是 STC8H 高级定时器的输出比较模式。
1.1、普通PWM输出
图1.1.1
图1.1.2
上两图展示的是普通的PWM输出模式,该模式下可以自己设定ARR和CCR,其中CCR用于控制占空比。
1.2、输出比较模式
输出比较模式通俗来说 是CNT = CCR时 电平会翻转。例如 你配置了 向上计数,ARR=100, CCR=30,初始电平为高电平,那么 CNT从0计数到30时, CNT =CCR =30,此时高电平就会跳变到低电平,CNT继续在30的基础上计数,直到计数到100并溢出,此时CNT会置0并重新开始计数。
值得注意的是,PWM模式与翻转模式下所输出的波形频率是相差 2倍的,即 PWM输出频率为10HZ,那么输出比较模式下的输出频率只有5HZ。
这是因为 输出比较模式下不关心CNT比 CCR值大还是小,只关心CNT和CCR值什么时候相等,两个值相等时,就翻转输出电平。在PWM模式下,CNT值从0增加到ARR一个周期内输出电平有两次变化,而在输出比较模式下时CNT值从0增加到ARR一个周期内输出电平只有一次变化。所以输出比较模式下,定时器输出方波的频率为PWM模式下定时器输出方波频率的一半。(该段内容源自--生成两路PWM波相位差90°的方法)
要想 输出比较模式 下输出的PWM波的频率与普通PWM模式下输出的频率相等,则需要对输出比较模式下输出的PWM频率进行2分频。该点后续详解。
二、相位差原理
本文可调节的相位差在 0-180°范围
CH1为普通PWM输出,其自动重装值为 ARR1=100,CH2为输出比较模式,其自动重装值为ARR2
2.1、频率相等
要实现CH1与CH2的输出频率相等,最重要的是两者的ARR的设置。其设置应为
ARR2=ARR1 / 2,且 CH2的 CCR应设置为0或50。
这是因为 输出比较模式下不关心CNT比 CCR值大还是小,只关心CNT和CCR值什么时候相等,两个值相等时,就翻转输出电平。在PWM模式下,CNT值从0增加到ARR一个周期内输出电平有两次变化,而在输出比较模式下时CNT值从0增加到ARR一个周期内输出电平只有一次变化。
我们设置 CH2 的ARR2 的值为50,其目的就是是为了 让 输出比较模式 在 PWM模式下的一个 ARR1周期内,有两次电平跳变,从而达到2分频的效果。而CCR设置为0或50,只是让电平在最大量程临界点电平跳变。可参考下图理解。
2.2、移相原理
想要得到0-180°范围内的相位差,最重要的是懂得如何调节输出通道CH1与输出通道2 CH2的 CCR关系。
首先我们理解 ARR 从0 --100这个范围对应着角度值的 0-- 360°。那么 0点对应的是 0°,25对应的就是90°,50 对应的就是 180°, 75对应的就是270°。那么想要实现移相的角度,无非是确定 输出比较模式 输出的 电平翻转点。
以180°移相为例。
要实现图中 CH1与CH2波形相位差为180°,我们要思考的是图中1 , 2 ,3点的电平该如何翻转。
仔细思考其实就可以知道,1点电平应该跳转为低电平,2点电平应跳转为高电平,3点应跳转为低电平。效果如下图所示。改图就是实现了180°移相,且占空比不改变的效果。
那么90°相位差呢?
电平翻转点应该就是在CCR=25 这个点位。如下图所示
确定了 翻转点位为 CCR=25,那么为何在 CCR=75的时候还要翻转多一次?
这是因为前文所说的,需要保持与PWM输出频率相等。至于为什么一定是75这个点而不是其他的点,这是因为 CNT=CCR1=25 时,电平翻转后,CNT是继续计数到 CCR1 = 75 电平翻转,CNT继续计数到 CCR1 =100 并溢出后置零重新计数的。而在75 --- 100这个过程,CNT是走过了25个计数值,而 CNT重新从0 到 CNT=25这个过程,也走过了25个计数值,那合起来就一共是走了50个计数值,这与我们 设定的 ARR2是一致的,保持了PWM 与 输出比较模式下的频率相等。
所以,在0-180°范围内 想要得到任意的相位差x,只需要计算出该相位差x对应的 ARR1的值并将该值设置为 输出比较的CCR2的值即可。
计算公式 CCR2 = ARR1 /(360°/x)
三、代码
u8 PWMA_ISR_En; //每个通道可以单独允许中断处理, bit4:通道4, bit3:通道3, bit2:通道2, bit1:通道1.u16 pwma1; //PWMA1输出高电平时间
u16 pwma2; //PWMA2输出高电平时间
u16 pwma2N;void PWMA_config(void)
{u8 ccer1;u8 ccer2;u8 ps;u8 eno;P_SW2 |= 0x80; //SFR enable PWMA_ENO = 0; // IO输出禁止PWMA_IER = 0; // 禁止中断PWMA_SR1 = 0; // 清除状态PWMA_SR2 = 0; // 清除状态PWMA_CR1 = 0; // 清除控制寄存器PWMA_CR2 = 0; // 清除控制寄存器ccer1 = 0;ccer2 = 0;ps = 0;eno = 0;PWMA_ISR_En = 0;PWMA_PSCR = 100; // 预分频寄存器, PWM时钟 = 12MHz/(11+1)=1MHz, 分频 Fck_cnt = Fck_psc/(PSCR[15:0}+1), 边沿对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)), 中央对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)*2).PWMA_DTR = 12; // 死区时间配置, n=0~127: DTR= n T, 0x80 ~(0x80+n), n=0~63: DTR=(64+n)*2T, // 0xc0 ~(0xc0+n), n=0~31: DTR=(32+n)*8T, 0xE0 ~(0xE0+n), n=0~31: DTR=(32+n)*16T,
// PWMA_ARR = PWMA_DUTY-1; // 自动重装载寄存器, 控制PWM周期PWMA_ARRH=((PWMA_DUTY-1) >> 8);PWMA_ARRL=((PWMA_DUTY-1) & 0xFF);PWMA_CCMR4 = 0x10; // 通道模式配置, PWM模式1, 预装载允许
// PWMA_CCR4 =pwma2; //PWMA_PHASE2+pwma2; // 比较值, 控制占空比(高电平时钟数)ccer2 |= 0x50; // 开启比较输出, 高电平有效ps |= 0xC0; // 选择IO, 0:选择P1.0 P1.1, 1:选择P2.0 P2.1, 2:选择P6.0 P6.1, eno |= 0xC0; // IO输出允许, bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P, bit3: ENO2N, bit2: ENO2P, bit1: ENO1N, bit0: ENO1PPWMA_ISR_En |= 0x10; // 使能中断PWMA_CCMR1 = 0x68; // 通道模式配置, PWM模式1, 预装载允许PWMA_CCR1 = pwma1; // 比较值, 控制占空比(高电平时钟数)ccer1 |= 0x05; // 开启比较输出, 高电平有效ps |= 0; // 选择IO, 0:选择P1.0 P1.1, 1:选择P2.0 P2.1, 2:选择P6.0 P6.1, eno |= 0x03; // IO输出允许, bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P, bit3: ENO2N, bit2: ENO2P, bit1: ENO1N, bit0: ENO1P
// PWMA_ISR_En |= 0x02; // 使能中断PWMA_CCER1 = ccer1; // 捕获/比较使能寄存器1PWMA_CCER2 = ccer2; // 捕获/比较使能寄存器2PWMA_PS = ps; // 选择IOPWMA_IER = PWMA_ISR_En; //设置允许通道1~4中断处理PWMA_BKR = 0x80; // 主输出使能 相当于总开关PWMA_CR1 = 0x81; // 使能计数器, 允许自动重装载寄存器缓冲, 边沿对齐模式, 向上计数, bit7=1:写自动重装载寄存器缓冲(本周期不会被打扰), =0:直接写自动重装载寄存器本(周期可能会乱掉)PWMA_EGR = 0x01; //产生一次更新事件, 清除计数器和预分频计数器, 装载预分频寄存器的值PWMA_ENO = eno; // 允许IO输出
}void PWMA_ISR(void) interrupt PWMA_VECTOR
{u8 sr1;
// u8 sr2;sr1 = PWMA_SR1; //为了快速, 中断标志用一个局部变量处理PWMA_SR1 = 0; //清除中断标志
// sr2 = PWMA_SR2; //为了快速, 中断标志用一个局部变量处理PWMA_SR2 = 0; //清除中断标志sr1 &= PWMA_ISR_En; //每个通道可以单独允许中断处理if(sr1 & 0x10) //通道4匹配中断标志{if(!P34) //当前输出低电平, 预装载的是输出高电平的匹配值, 则准备好输出低电平的匹配值{PWMA_CCR4 = pwma2;
// pwma2; //PWMA_PHASE2; // 通道2匹配值, 匹配时输出低PWMA_CCMR4 = 0x10; // 通道模式配置, 匹配模式2, 禁止预装载, 匹配时输出低}else //当前输出高电平, 预装载的是输出低电平的匹配值, 则准备好输出高电平的匹配值{PWMA_CCR4 =PWMA_PHASE2 + pwma2N; // 通道2匹配值, 匹配时输出高PWMA_CCMR4 = 0x20; // 通道模式配置, 匹配模式1, 禁止预装载, 匹配时输出高}}
}void main(void)
{ P_SW2 = 0x80;Tick_Init();Io_Init();pwma1 =200;pwma2 =50;pwma2N =850;PWMA_config(); EA = 1;while (1) {}
}
这篇关于PWM移相以及占空比可变(上)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!