ATmega328 Timer1快速PWM模式15配置异常及无信号问题排查
问题分析与解决方案
核心疑问解答
比较输出模式(COM)选择:
对于OC1B的非反相PWM,需设置COM1B1=1且COM1B0=0——此时定时器计数到OCR1B时,OC1B引脚电平清零;计数到TOP值(OCR1A)时,引脚电平置位。如果是反相PWM,则设置COM1B1=1且COM1B0=1,电平翻转逻辑相反。若COM1B1=0,无论COM1B0取值如何,定时器都不会驱动OC1B引脚,引脚仅受GPIO寄存器控制。OC1A/OC1B断开的含义:
当COMx1=0时,定时器的比较匹配模块与OCxA/OCxB引脚“断开”,引脚不再受定时器控制,仅作为普通IO口使用,电平由DDR和PORT寄存器决定。模式15下OC1A的作用:
快速PWM模式15(WGM1[3:0]=0b1111)的TOP值固定为OCR1A寄存器的值,和OC1A引脚是否配置为输出无关。即使OC1A断开(COM1A1=0),OCR1A依然承担TOP值的角色,定时器的计数周期由它决定,只是OC1A引脚不会输出PWM信号。
代码错误与修正
你的代码中预分频器配置错误是导致PB2无输出的核心原因:Timer1的预分频位是CS12、CS11、CS10,而非Timer0的CS02、CS00。错误的配置导致定时器未启动,自然没有PWM输出。
修正后的代码如下:
void setup(){ DDRB |= (1 << PB2) | (1 << PB1); // 设置OC1A(PB1)和OC1B(PB2)为输出 // 配置快速PWM模式15(WGM1[3:0]=0b1111) // OC1B非反相PWM(COM1B1=1, COM1B0=0) TCCR1A |= (1 << COM1B1) | (1 << WGM11) | (1 << WGM10); // 配置TOP=OCR1A,预分频器1024(CS12=1, CS10=1) TCCR1B |= (1 << WGM13) | (1 << WGM12) | (1 << CS12) | (1 << CS10); TCNT1 = 0; // 重置计数器 // 计算100Hz频率的TOP值:OCR1A = (16000000/(100*1024)) -1 = 155 OCR1A = 155; OCR1B = 77; // 50%占空比((77+1)/(155+1)=50%) } void loop() {}
额外说明
- 全局中断(
SREG |= 0b10000000)无需开启,硬件PWM不需要中断支持,可直接删除该行。 - 非反相PWM的占空比公式为
(OCR1B + 1)/(TOP + 1),设置OCR1B=77时,占空比为78/156=50%,符合需求。
内容的提问来源于stack exchange,提问作者paxel
相关产品推荐
相关产品推荐

