對于很多剛剛接觸Arduino的人來說,占空比和PWM 這兩個詞可能不太容易理解,下面就讓我們深度剖析一下這兩個概念。
你也可以通過與視頻結(jié)合的方式學(xué)習(xí),PWM的概念與應(yīng)用,這是個不錯的視頻;更詳細(xì)的介紹參看 用Arduino剖析PWM脈寬調(diào)制。
PWM(Pulse Width Modulation)
簡介
PWM,也就是脈沖寬度調(diào)制,用于將一段信號編碼為脈沖信號(一般是方波信號)。是在數(shù)字電路中 達(dá)到 模擬輸出效果的一種手段。即:使用數(shù)字控制產(chǎn)生占空比不同的方波(一個不停在開與關(guān)之間切換的信號)來控制模擬輸出。我們要在數(shù)字電路中輸出模擬信號,就可以使用PWM技術(shù)實(shí)現(xiàn)。在嵌入式開發(fā)中,我們常用PWM來驅(qū)動LED的暗亮程度,電機(jī)的轉(zhuǎn)速等。
PWM的頻率
pwm的頻率決定了輸出的數(shù)字信號on ,1 和 off,0 的切換速度。頻率越高,切換就越快。頻率的大小就是前面提到的調(diào)制周期T的倒數(shù) : f = 1/T。
1秒內(nèi),0.5秒開,0.5秒滅,占空比是50%。那么,1毫秒內(nèi),0.5毫秒開,0.5毫秒滅,占空比也是50%,對于前者,頻率就是1HZ,而后者,是1毫秒,頻率就是1KHZ。
一般pwm頻率都是因硬件設(shè)計(jì)而固定的,是由pwm發(fā)生器決定的。PWM頻率越高,調(diào)制出來的輸出曲線就更加的smooth,效果越好,完成一個調(diào)制周期的時間越短。這個和手機(jī)的ppi越高,顯示越清晰是一個道理。當(dāng)然PWM的頻率越高,對硬件的要求就也越高。
如何產(chǎn)生PWM?
Arduino有三種方式可以產(chǎn)生PWM。第一種:
用analogWrite(pin, val)命令
其中pin是引腳的編號,只能用3,5,6,9,10,11這幾條;val是0~255的整數(shù)值,對應(yīng)電壓從0到+5V。
具體的使用可以看下面的示例代碼:
int pin = 8; //0~13
void setup()
{
pinMode(pin, OUTPUT);
}
void loop()
{
analogWrite(pin, 128);
delay(500);
}
這種方式產(chǎn)生的方波周期大概是2ms左右(490Hz),不需要占用額外的cpu命令時間。據(jù)說99%的同學(xué)看到這里就可以下課了,技術(shù)宅請繼續(xù)看第二種方式:
手動用代碼實(shí)現(xiàn)PWM
int pin = 38; //這個可以隨意點(diǎn)
void setup()
{
pinMode(pin, OUTPUT);
}
void loop()
{
digitalWrite(pin, HIGH);
delayMicroseconds(100);
digitalWrite(pin, LOW);
delayMicroseconds(1000 - 100);
}
上面這段代碼會產(chǎn)生一個PWM=0.1的,周期為1ms的方波(1000Hz),這種方式的優(yōu)缺點(diǎn)很明顯:
1.PWM的比例可以更精確;
2.周期和頻率可控制;
3.所有的pin腳都可以輸出,不局限于那幾個腳;
缺點(diǎn):CPU干不了其他事情了;
好吧,缺點(diǎn)只有一個,卻非常致命,以至于上面這些基本都是廢話。但是對于周期比較大的PWM,可以用算法模擬CPU的多任務(wù)系統(tǒng),從而在輸出PWM的同時做點(diǎn)兼職。
那么能不能既調(diào)節(jié)PWM的頻率和周期,又不要占用額外的CPU時間呢?請看第三種方式:
使用PWM寄存器(不作要求)
ATmega168有三個時鐘,名字分別叫Timer0, Timer1和Timer2。每個時鐘都使用了兩個寄存器,其中一個是設(shè)定值例如128,另一個則從0開始不斷遞增,到1024之后溢出回到0。那么當(dāng)兩個值相同的時候,Timer就會把某個管腳反相。不同的Timer之間頻率是相同的,占空比則根據(jù)設(shè)置值不同。
占空比有了,那么周期怎么控制呢?有一種叫做時鐘控制器的東東,這個控制器可以設(shè)置周期為CPU周期的某個倍數(shù),例如1,8,64,256,1024等等,Timer0和Timer1共用一個控制器,Timer2和它們是獨(dú)立的。
Atmega 168/328的時鐘們
ATmega328P有三個時鐘,Timer0,Timer1和Timer2。每個時鐘都有兩個比較寄存器,可以同時支持兩路輸出。其中比較寄存器用于控制PWM的占空比,具體的原理等會兒會介紹。大多數(shù)情況下,每個時鐘的兩路輸出會有相同的頻率,但是可以有不同的占空比(取決于那兩個比較寄存器的設(shè)置)
每個時鐘都有一個“預(yù)定標(biāo)器”,它的作用是設(shè)置timer的時鐘周期,這個周期一般是有Arduino的系統(tǒng)時鐘除以一個預(yù)設(shè)的因子來實(shí)現(xiàn)的。這個因子一般是1,8,64,256或1024這樣的數(shù)值。Arduino的系統(tǒng)時鐘周期是16MHz,所以這些Timer的頻率就是系統(tǒng)時鐘除以這個預(yù)設(shè)值的標(biāo)定值。需要注意的是,Timer2的時鐘標(biāo)定值是獨(dú)立的,而Timer0和Timer1使用的是相同的。
這些時鐘都可以有多種不同的運(yùn)行模式。常見的模式包括“快速PWM”和“相位修正PWM”,這兩種PWM的定義也會在后面解釋。這些時鐘可以從0計(jì)數(shù)到255,也可以計(jì)數(shù)到某個指定的值。例如16位的Timer1就可以支持計(jì)數(shù)到16位(2個字節(jié))。
除了比較寄存器外,還有一些其他的寄存器用來控制時鐘。例如TCCRnA和TCCRnB就是用來設(shè)置時鐘的計(jì)數(shù)位數(shù)。這些寄存器包含了很多位(bit),它們分別的作用如下:
脈沖生成模式控制位(WGM):用來設(shè)置時鐘的模式
時鐘選擇位(CS):設(shè)置時鐘的預(yù)定標(biāo)器
輸出模式控制位(COMnA和COMnB):使能/禁用/反相 輸出A和輸出B
輸出比較器(OCRnA和OCRnB):當(dāng)計(jì)數(shù)器等于這兩個值時,輸出值根據(jù)不同的模式進(jìn)行變化
不同時鐘的這些設(shè)置位稍有不同,所以使用的時候需要查一下資料。其中Timer1是一個16位的時鐘,Timer2可以使用不同的預(yù)定標(biāo)器。
占空比(duty cycle)
有了前面的知識,相信你已經(jīng)對占空比理解了,其實(shí)很好理解 ,所謂占空比就是調(diào)整led通過電流和不通過電流的時間比來控制的,由于人眼有視覺暫留特性,所以只要頻率比較高是看不出來閃爍的。有關(guān)這部分介紹在PWM的概念與應(yīng)用這個視頻里有直觀的說明。
當(dāng)然通過電流比不通過電流的時間比例越大,led做的功就越多,這樣也就越亮,需要注意的是led芯片的溫升和最大電流值不要超標(biāo),不然會影響其壽命。
下面給出占空比的公式

D: 占空比
PW: 脈沖寬度(調(diào)制周期中脈沖持續(xù)時間)
T: 一個調(diào)制周期
所以我們可以很自然的得出結(jié)論:
- 低占空比意味著輸出的能量低,因?yàn)樵谝粋€周期內(nèi)大部分時間信號處于關(guān)閉狀態(tài),如果pwm控制的負(fù)載為led,則具體表現(xiàn)例如led燈很暗。
- 高占空比意味著輸出的能量高,在一個周期內(nèi),大部分時間信號處于on狀態(tài),具體表現(xiàn)為LED比較亮。
- 當(dāng)占空比為100%時,表示 fully on,也就是在一個周期內(nèi),信號都處于on狀態(tài),具體表現(xiàn)為led亮度到達(dá)100%。
- 當(dāng)占空比為0%時則表示 totally off,在一個周期內(nèi),一直處于off狀態(tài),具體表現(xiàn)為led熄滅。
現(xiàn)在一切都明了了:脈沖寬度調(diào)制,這個寬,不是物體的寬度,而是高電平(有效電平)信號在一個調(diào)制周期中持續(xù)時間長短,它可以用占空比去衡量,占空比越大,脈沖寬度越寬。