ATmega88PB配置相位频率校正PWM时OCR1A引脚持续高电平求助
问题描述
在ATmega88PB单片机上实现相位频率校正PWM功能时,编写了如下PWM初始化函数:
void PWM_INIT2() { DDRB|=(1<<PINB1) | (1<<PINB2); TCCR1B |= (1<<WGM13) | (1<<CS10); TCCR1A |= (1<<COM1B0) | (1<<COM1B1) | (1<<COM1A1); }
将该初始化函数加入主函数运行后,OCR1A对应的输出引脚始终保持高电平,主函数代码如下:
int main(void) { PWM_INIT2(); while (1) { } }
问题根源
- PWM计数周期上限未配置:当前代码中WGM13置1、其余WGM1位为0,对应定时器1相位频率校正PWM模式8,该模式的计数TOP值由ICR1寄存器决定。代码未给ICR1赋值,芯片上电后ICR1默认值为0,定时器无法完成正常的上下计数循环。
- OCR1A比较值未初始化:芯片上电后OCR1A默认值为0,配合当前设置的COM1A1置1的非反转PWM输出规则,没有有效比较匹配事件触发引脚电平翻转,最终引脚持续锁死高电平。
- 寄存器配置未做前置清零:直接使用
|=操作写TCCR1A、TCCR1B寄存器,没有先清除寄存器上电后的默认残留值,可能混入无关配置位导致PWM运行逻辑异常。 - OC1B输出配置错误:代码同时置位COM1B0和COM1B1,在相位频率校正PWM模式下该配置为比较匹配时OC1B引脚电平反转,不是常规的固定占空比PWM输出模式,会导致OC1B输出不符合预期。
可行解决方案
修正后的初始化参考代码如下(以系统时钟8MHz、输出200Hz PWM为例):
void PWM_INIT2() { // 配置OC1A(PB1)、OC1B(PB2)为输出方向 DDRB |= (1<<PINB1) | (1<<PINB2); // 先清零定时器1控制寄存器,排除默认值干扰 TCCR1A = 0; TCCR1B = 0; // 配置相位频率校正PWM模式(模式8,TOP=ICR1),无预分频 TCCR1B |= (1<<WGM13) | (1<<CS10); // OC1A、OC1B均配置为非反转PWM输出 TCCR1A |= (1<<COM1A1) | (1<<COM1B1); // 设置PWM周期TOP值,8MHz无预分频下PWM频率=8000000/(2*ICR1) ICR1 = 20000; // 设置OCR1A比较值,对应50%占空比 OCR1A = 10000; // 设置OCR1B比较值,对应25%占空比 OCR1B = 5000; }
配置注意事项:
- 选择相位频率校正PWM模式时,必须根据所选WGM组合给对应的TOP源寄存器(ICR1或OCR1A)赋值大于0的有效值,否则定时器无法启动正常计数循环。
- 启动PWM前必须给OCR1x寄存器设置小于TOP值的初始比较值,避免输出电平锁死。
- 配置定时器功能寄存器前建议先将寄存器清零,避免复位残留值导致功能异常。
- COM位配置要匹配输出需求:常规非反转PWM输出仅需置位COM1x1,同时置位COM1x0会开启比较匹配反转功能,占空比逻辑会偏离预期。
内容的提问来源于stack exchange,提问作者Rj Choudhary
相关产品推荐
相关产品推荐

