计数单元持续不断的计数,
每计一次数,就比较一下当前计数(TCNT0)和预设值(其实就是analogWrite函数中的val值)OCRnx。
当发现两者相等,就立即给波形发生器(Waveform Generator)一个信号:
你要向OCnx内输出下一个状态了,
而OCnx直接影响其对应的外部IO口,
就这样,PWM就产生了!
由于ATmega328P(Arduino Uno选用的MCU)内部共有3个定时/计数器:
TC0、TC1、TC2
TC0对应数字IO:5、6两个输出口;
TC1对应数字IO:9、10两个输出口;
TC2对应数字IO:3、11两个输出口;
这也就解释了为什么只能在3、5、6、9、10、11端口上产生PWM波了!
PWM其实是通过设置一系列寄存器才能正常工作的,
涉及:TCCRx(控制寄存器)、TCNTx(计数值寄存器)、OCRx(输出比较寄存 器)等等。
为达到简化的目的,Arduino预设了 这些寄存器!
而且,有能力,你是完全可以自己改的!
由于三种计数器的差异性,Arduino分别量身定制了PWM方案:
TC0(端口5、6)输出的PWM方波的频率为980Hz左右。
TC1(端口9、10)输出的PWM方波的频率为490Hz左右。
TC2(端口3、11)输出的PWM方波的频率为490Hz左右。
差异性体现在计数方式上,
TC0采用单向计数,从0计到255算一个周期。
TC1和TC2采用循环向计数,从0计到255,再从255计到0才算一个周期。
在计数频率一致的情况下,
TC0输出的PWM波频率自然是TC1和TC2的两倍了!
下面给出图示,不深入讲解了,
感兴趣的撸友,可以参见ATmega328P数据手册TC章节!
`