ez a cikk az előző PWM bejegyzéssel folytatódik. Ismerje meg, hogyan kell programozni az időzítőket PWM módban történő működésre! Tehát kezdjük!
Helló emberek! Régóta nem láttuk egymást! 🙂
előző bejegyzésemben a PWM alapfogalmait tárgyaltuk. Először foglaljuk össze:
- a PWM az impulzusszélesség-modulációt jelenti.
- előállítható az előre meghatározott hullámforma referenciafeszültség-szinttel történő összehasonlításával vagy egyszerű analóg áramkörök készítésével.
- a PWM hullámforma terhelhetőségét a következő reláció adja meg.
- a PWM működésének három módja van: gyors PWM, fázis helyes PWM és frekvencia és fázis helyes PWM
- hogyan válasszuk ki az időzítőt, az üzemmódot és hasonlítsuk össze a kimeneti módot a kívánt PWM előállításához.
Vegyünk egy probléma nyilatkozatot. 50 Hz-es PWM jelet kell generálnunk, amelynek 45% – os terhelhetősége van.
analízis
tekintettel arra, hogy
Frequency = 50 Hz
más szavakkal, az időtartam, T
T = T(on) + T(off) = 1/50 = 0.02 s = 20 ms
továbbá, tekintettel arra, hogy
Duty Cycle = 45%
így a fent megadott egyenlet szerint megoldva megkapjuk
T(on) = 9 msT(off) = 11 ms
most ez lehet két módon érhető el:
- használja az időzítőt CTC módban
- használja az időzítőt PWM módban
módszertan – CTC mód
Oké, tehát itt nem írok semmilyen kódot (csak az álkódot). Feltételezem, hogy az előző bejegyzéseim elolvasása után elég okos vagy ahhoz, hogy magad írj egyet! Csak a fogalmakat fogjuk megvitatni.
először válasszon megfelelő időzítőt. Ehhez az alkalmazáshoz az ATMEGA32-ben elérhető három időzítő közül választhatunk. Válasszon megfelelő prescalert. Ezután állítsa be az időzítőt, és folytassa a szokásos módon. A fogás itt rejlik, hogy minden alkalommal frissítenie kell az OCRx regiszter összehasonlító értékét. Az egyik ilyen módszert az alábbiakban megadott pszeudo kód tárgyalja.
ez Analóg a hagyományos LED-es villogóval, kivéve azt a tényt, hogy a be-és kikapcsolási idők eltérőek.
pszeudo kód
#include <avr/io.h>#include <avr/interrupt.h> uint8_t count = 0; // global counter // initialize timer, interrupt and variablevoid timerX_init(){ // set up timerX with suitable prescaler and CTC mode // initialize counter // initialize compare value // enable compare interrupt // enable global interrupts} // process the ISR that is firedISR (TIMERx_COMPA_vect){ // do whatever you want to do here // say, increment the global counter count++; // check for the global counter // if count == odd, delay required = 11 ms // if count == even, delay required = 9 ms // thus, the value of the OCRx should be constantly updated if (count % 2 == 0) OCRx = 9999; // calculate and substitute appropriate value else OCRx = 10999; // calculate and substitute appropriate value} int main(void){ // initialize the output pin, say PC0 DDRC |= (1 << 0); // initialize timerX timerX_init(); // loop forever while(1) { // do nothing }}
most ez az egyik módszer. És nagyon hatástalan. Növelheti hatékonyságát egy jobb C kód írásával (szintaxis szerint), azonban a koncepció ugyanaz marad. Ha bármilyen más módszer/koncepció, akkor szívesen ossza meg itt! 🙂
frissítés: a maxEmbedded egyik olvasója, a “coolpales” írta ezt a kódot, és működött neki.
Felhívjuk figyelmét, hogy ez a kód még nincs tesztelve! Tehát, ha bármelyikőtök kipróbálja, tegye közzé itt az eredményeit, örülnék, ha látnám őket! 🙂
módszertan – PWM mód
Oké, tehát most megismerhetjük a PWM módot. Az AVR PWM módja hardveres vezérlésű. Ez azt jelenti, hogy mindent, mindent, amit “mindent” értek, az AVR CPU végzi. Mindössze annyit kell tennie, hogy inicializálja és indítsa el az időzítőt, és állítsa be a munkaciklust! Király, mi?! Tanuljuk meg, hogyan!
itt az Atmega32 Timer0-jét használtam demonstrációra. Választhat bármilyen más időzítőt vagy AVR mikrokontrollert is. Most vessünk egy pillantást a nyilvántartásokra.
TCCR0 – Timer/Counter0 vezérlő regiszter
találkoztunk ezzel a regiszterrel a Timer0 oktatóanyagomban. Itt megtanuljuk, hogyan állítsunk be megfelelő biteket az időzítő PWM módban történő futtatásához.
TCCR0 regiszter
csak azokat a biteket fogjuk megvitatni, amelyek most érdekesek számunkra.
- Bit 6,3 – WGM01:0 – Waveform Generation Mode – ezek a bitek “00” vagy “01” – re állíthatók a generálni kívánt PWM típusától függően. Itt a felnéző asztal.
hullámforma generációs mód Bit leírása
- Bit 5,4-COM01: 0-összehasonlítás mérkőzés kimeneti mód – ezek a bitek vannak beállítva annak érdekében, hogy ellenőrizzék a viselkedését kimeneti összehasonlítani pin (OC0, pin 4 atmega32) szerint a WGM01:0 bit. Az alábbi keresési táblázat meghatározza az OC0 pin működését a gyors PWM módhoz.
hasonlítsa össze a kimeneti módot, a gyors PWM módot
most vessünk egy pillantást a gyors PWM hullámformákra. Részletes magyarázat megtalálható az előző bemutatómban.
gyors PWM
most hadd emlékeztessem önöket, hogy az AVR PWM teljesen hardveres vezérlésű, ami azt jelenti, hogy még az időzítő összehasonlítási műveletet is az AVR CPU végzi. Csak annyit kell tennünk, hogy megmondjuk a CPU-nak, mit kell tennie, ha egy mérkőzés bekövetkezik. A COM01: 0 csapok itt játszanak szerepet. Látjuk, hogy “10” vagy “11” értékre állítva az OC0 kimeneti csap be van állítva vagy törlődik (más szóval meghatározza, hogy a PWM fordított vagy nem fordított módban van-e).
hasonlóan a Phase Correct PWM-hez, a look up táblázat és a hullámformák így mennek.
kimeneti mód összehasonlítása, fázis helyes PWM mód
Phase Correct PWM
még itt is a COM01:0 “10” vagy “11” beállítása határozza meg az OC0 tű viselkedését. Amint az a hullámformákban látható, két példány létezik – az egyik a felszámlálás során, a másik a leszámlálás során. A viselkedést egyértelműen leírja a keresési táblázat.
kérjük, vegye figyelembe, hogy az OC0 egy kimeneti tű. Így a WGM és a COM hatásai csak akkor lépnek életbe, ha a DDRx regiszter megfelelően van beállítva. További információkért olvassa el ezt az oktatóanyagot.
- Bit 2:0 – CS02:0 – Clock Select Bits – ezek a bitek már tárgyalt Timer0 bemutató.
OCR0 – Output összehasonlítása regiszter
találkoztunk még ezt a nyilvántartást az én Timer0 bemutató. Ezt a regisztert használjuk az összehasonlítási érték tárolására. De amikor a Timer0-t PWM módban használjuk, a benne tárolt érték a munkaciklusként működik (nyilvánvalóan!). A problémamegállapításban az, hogy az üzemi ciklus 45%, ami azt jelenti, hogy
OCR0 = 45% of 255 = 114.75 = 115
és ennyi! Most készen állunk arra, hogy kódot írjunk hozzá! 🙂
Szerkesztés: Megjegyzés
a következő kód azt tárgyalja, hogyan lehet létrehozni egy kívánt terhelhetőségű PWM jelet. Ha meg akarja változtatni a frekvenciáját, meg kell változtatnia a felső értéket, amelyet az ICRx regiszter segítségével lehet megtenni (amelyet a 8 bites időzítők nem támogatnak). Az 16-bit Timer1 esetében az ICR1A használatával változtatható.hamarosan megvitatom ezt, amikor a szervo vezérlésről beszélünk.
Kód
tehát itt megy a kód. Ha többet szeretne megtudni az AVR I / O port műveleteiről, tekintse meg ezt. Ha tudni szeretne a bit manipulációkról, nézze meg ezt. Az AVR Studio 5 használatának megtanulásához tekintse meg ezt. A kód felépítésének megismeréséhez tekintse meg az előző TIMER0 bejegyzést.
#include <avr/io.h>#include <util/delay.h>void pwm_init(){ // initialize TCCR0 as per requirement, say as follows TCCR0 |= (1<<WGM00)|(1<<COM01)|(1<<WGM01)|(1<<CS00); // make sure to make OC0 pin (pin PB3 for atmega32) as output pin DDRB |= (1<<PB3);} void main(){ uint8_t duty; duty = 115; // duty cycle = 45% of 255 = 114.75 = 115 // initialize timer in PWM mode pwm_init(); // run forever while(1) { OCR0 = duty; }}
Problémamegállapítás
tehát most vegyünk egy másik problémamegállapítást. Ez egy lesz egy praktikus dolog, ellentétben az előzővel!
vegyük a hagyományos LED-es villogót, ahol egy adott frekvencián villogni kell egy LED-et. De Hé, várj, nem vitattuk meg sokáig ebben a bejegyzésben (görgessen lefelé a vége felé)? Hmm, tehát módosítsuk úgy, hogy beépítsük a PWM-et. A hagyományos LED-es villogóval ellentétben (ahol a LED-ek be vannak kapcsolva vagy ki vannak kapcsolva) lehetővé teszi, hogy a maximális fényerő mellett ragyogjon, majd lassan csökkentse fényerejét, amíg el nem éri a nullát, majd lassan növelje fényerejét, amíg maximálissá nem válik.
elemzés és kód
tehát hogyan csináljuk? Igen, jól kitaláltad! Csökkentse lassan a munkaciklust 255-ről nullára, majd növelje nulláról 255-re. A munkaciklustól függően a LED-re alkalmazott feszültség változik, így a fényerő is. A következő képlet adja meg a feszültség és a munkaciklus közötti kapcsolatot.
tehát itt megy a kódot. Nem fogom elmagyarázni, maga is dekódolhatja. Ha többet szeretne megtudni az AVR I / O port műveleteiről, tekintse meg ezt. Ha tudni szeretne a bit manipulációkról, nézze meg ezt. Az AVR Studio 5 használatának megtanulásához tekintse meg ezt. A kód felépítésének megismeréséhez tekintse meg az előző TIMER0 bejegyzést.
// program to change brightness of an LED// demonstration of PWM #include <avr/io.h>#include <util/delay.h> // initialize PWMvoid pwm_init(){ // initialize timer0 in PWM mode TCCR0 |= (1<<WGM00)|(1<<COM01)|(1<<WGM01)|(1<<CS00); // make sure to make OC0 pin (pin PB3 for atmega32) as output pin DDRB |= (1<<PB3);} void main(){ uint8_t brightness; // initialize timer0 in PWM mode pwm_init(); // run forever while(1) { // increasing brightness for (brightness = 0; brightness < 255; ++brightness) { // set the brightness as duty cycle OCR0 = brightness; // delay so as to make the user "see" the change in brightness _delay_ms(10); } // decreasing brightness for (brightness = 255; brightness > 0; --brightness) { // set the brightness as duty cycle OCR0 = brightness; // delay so as to make the user "see" the change in brightness _delay_ms(10); } // repeat this forever }}
tehát itt ér véget a másik sokat várt és hosszú bemutató! Következő.. Soros Kommunikáció! Még találkozunk!! 🙂
és igen, ha bármilyen javaslata, kétsége, konstruktív kritika, stb, akkor szívesen csepp egy megjegyzés alatt! Iratkozzon fel a blogomra, vagy ragadja meg az RSS-hírcsatornákat, hogy naprakész legyen!