Aruidno(Avr)自定义输出PWM

本文目标:

通过修改Arduino Uno(芯片)的 Timer2 相关的寄存器来定制PWM。

准备知识:(大概了解下就行了,不用深究,看完之后的例子就会明白)

Arduino内置有3个Timer0、Timer1、Timer2。
Timer是干什么的呢,说简单点就是用来数(shǔ)数(shù)的,怎么数的呢?就是从0数到最大值,或者从最大值数到0。
然后通过timer2对应的寄存器值,输出频率,以及中断等。本例只用到Timer2,所以只说下Timer2。

Timer2 是8位的也就是只能从0数到255,作用的引脚是 pin11pin3 (这是物理设计固定的记住就行,具体可以看文档和Aruidno引脚图)所以修改后的PWM只能从pin11和pin3输出。


相关寄存器:TCCR2A,TCCR2B,ORC2A,ORC2B、TCNT2、OCR2A、OCR2B

下面是这几个寄存器的格式说明:

寄存器TCCR2A

寄存器TCCR2B

寄存器ocr2a

寄存器ocr2b

TCNT2:存timer数(shǔ)的数(shù)(比如数(shǔ)到10,TCNT2的值就是10,范围是0~255,因为timer2是8位,上文也说了)
OCR2A/B就是2个8位二进制数(0~255)
OCR2A 对应作用于 pin11
OCR2B 对应作用于 pin3
这里不需要解释说明意思,因为解释了也不会很了解,知道有这2个值就行了,以及他们作用的引脚就好了,最下面会有例子,看了就懂了。

寄存器作用描述:

TCCR2A/B就是来控制Timer2如下的3个设置:
Waveform Generation Mode (波形产生模式)
Clock Select(降频预除数)
Compare Match Output Mode (比较输出模式)
这里先分别描述这3个东西的内容,然后再连起来说明内部的运行原理。

Waveform Generation Mode (波形产生模式)

通过寄存器TCCR2A的WGM22WGM21 和 TCCR2B的WGM20这3个值是用来控制模式。(WCM22 WGM 21WGM20的位置可以对照上面的寄存器格式图片)
如图

图一,7种模式

本文章只讲解Mode:7,如何生成PWM,
即WGM22=1、WGM21=1、WGM20=1。

该模式具体运行方式接下来会结合设置COM2A1、COM2A0、 COM2B1、 COM2B0、 ORC2A、 ORC2B这6个值来说明。


Clock Select(降频预除数)

通过CS22、CS21、CS20这3个值来控制。如图

PWMCS2X.png

顾名思义,该值主要是用来降低频率的,看图也能知道,用 时钟频率除以1,8,32,64,128,256,1024 来降低频率。


Compare Output Mode(比较输出模式设置)

该设置的意思就是:TCNT2 达到 要比较的值了 如何设置OC2A 和 OC2B的电频输出(高 或 低)

还记得TCNT2是什么意思吗?这里提示下“存timer数(shǔ)的数(shù)”

需要特别注意的是这里的OC2A、OC2B不是寄存器,只是pin11和pin3引脚的别名,其实物理上,OC2A是pin11、OC2B是pin3。不要把OC2A/B和 OCR2A/B搞混了
还有一点,这个输出模式在不同“模式设置”下,功能各不相同,本文章只讲Mode7的设置。

控制OC2A和OC2B输出,分别有自己对应的值来设置,来看图:

OC2A设置
这里解释下4种设置的意思:
00:OC2A没有连接到Pin11针脚
01:WGM22=0时,OC2A没有连接到Pin11针脚
WGM22=1时,当TCNT2 等于“比较值”(Fast PWM的比较值是OCR2A,参考图一)的时候,反转电频(高->低 or 低->高)
10:当TCNT2等于“比较值”时,设置OC2A为低电频,当TCNT2等于0(Bottom)时,设置OC2A为高点频
11:和上面的10设置,相反。
OC2B设置

OC2B的设置 和 OC2A是一样的(当然除了 01设置 和WGM22无关,仔细看图)这里就不重复说明了。


好了,了解了以上的基础知识,下面就要说明以2个例子来说明Mode7(Fast PWM)的运行方式了。

例子1:(只使用OCR2A)

在本例子中,我们的寄存器设置为
WGM22 = 1,WGM21 = 1, WGC20 = 1(这里废话了,因为本来都是Mode7)
Com2A1 = 0,Com2A0 = 1,也就是上面的01模式(具体移上去看)
CS22 = 0,CS21 = 1,CS20 = 0,预除值为 8 (具体对照上面的图)
OCR2A = 99
OC2A(pin11引脚)目前输出是高电频

1.根据CPU时钟频率(arduino uno的频率是16Mhz,也就是1秒可以数16000000次),TCNT2从0开始累加1(就是,0,1,2,3,4,5,6....一直这样数数)
2.当TCNT2数到99也就是等于 OCR2A时,OC2A(pin11)反转电频(高变低or低变高),
TCNT2又变0,然后回到第1步,,,,

一直这样1,2步的循环,电频不断的高低变化就产生了PWM。
该例子的最终的频率是 16000000 / (2 * 8 * (99 + 1))= 10000hz = 10khz

例1源代码:

TCCR2A = (1 << COM2A0) | (1 << WGM21) | (1 << WGM20);
TCCR2B = (1 << WGM22) | (1 << CS21);
OCR2A = 99;
例子2:(同时使用OCR2A 和 OCR2B)

Com2B1 = 1,Com2B0 = 0 (10模式,可以参考上面设置COM2B的图)
OCR2B = 24。其他设置和例1一样

1.根据CPU时钟频率,TCNT2从0开始+1
2.当TCNT2等于24也就是等于OCR2B时,OC2B(pin3)变为低电频
3.TCNT2继续+1,一直到99,等于OCR2A时,TCNT2变为0,OC2B(pin3)变为高电频,OC2A(pin11)反转电频,然后回到第1步,周而复始...
说起来有点抽象 可以参考下图理解:


图片来自于https://www.jianshu.com/p/cef09d3411ab

仔细观察图片会发现,ORC2B 可以用来设置该频率下 的占空比。
https://www.jianshu.com/p/cef09d3411ab这篇文章最后部分就对这个描述得很仔细,可以参考一下。

例2源代码:
TCCR2A = (1 << COM2A0) | (1 << WGM21) | (1 << WGM20) | (1 << COM2B1);
TCCR2B = (1 << WGM22) | (1 << CS21);
OCR2A = 99;
OCR2B = 24;

你可能感兴趣的:(Aruidno(Avr)自定义输出PWM)