denne artikel er i fortsættelse med det forrige PM-indlæg. Lær hvordan du programmerer timerne til at fungere i PMM-tilstand! Så lad os begynde!
Hej folkens! Lang tid ikke se! 🙂
i mit tidligere indlæg har vi diskuteret de grundlæggende begreber i PVM. Lad os opsummere det først:
- pulsbreddemodulation står for pulsbreddemodulation.
- det kan genereres ved at sammenligne forudbestemt bølgeform med et referencespændingsniveau eller ved at lave enkle analoge kredsløb.
- arbejdscyklus for en bølgeform for MVM er givet ved følgende forhold.
- der er tre tilstande til drift af PMV – hurtig PMV, Fasekorrekt PMV og frekvens og Fasekorrekt PMV
- Sådan vælges timer, driftstilstand og sammenlign outputtilstand til generering af den ønskede PMV.
lad os tage en problemstilling. Vi er nødt til at generere et 50 HS-signal med 45% arbejdscyklus.
analyse
i betragtning af at
Frequency = 50 Hz
med andre ord tidsperioden, T
T = T(on) + T(off) = 1/50 = 0.02 s = 20 ms
også, i betragtning af at
Duty Cycle = 45%
således løser vi i henhold til ligning givet ovenfor, vi får
T(on) = 9 msT(off) = 11 ms
nu kan dette være opnået på to måder:
- Brug Timer i CTC – tilstand
- Brug Timer i PMM-tilstand
metode-CTC-tilstand
Okay, så jeg skriver ikke nogen kode her (bare pseudokoden). Jeg antager, at efter at have læst mine tidligere indlæg, du er smart nok til at skrive en selv! Vi vil kun diskutere begreberne.
Vælg først en passende timer. Til denne applikation kan vi vælge en af de tre timere, der er tilgængelige i atmega32. Vælg en passende prescaler. Indstil derefter timeren og fortsæt som normalt. Fangsten ligger her er, at du skal opdatere sammenligningsværdien af registeret hver gang. En sådan måde diskuteres i pseudokoden nedenfor.
dette er analogt med den traditionelle LED-flasher, bortset fra det faktum, at tænd-og slukketiderne er forskellige.
pseudokode
#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 }}
nu er dette en metode. Og det er meget ineffektivt. Du kan øge dens effektivitet ved at skrive en bedre C-kode (syntaksmæssigt), men konceptet forbliver det samme. Hvis du har en anden metode / koncept, er du meget velkommen til at dele det her! 🙂
opdatering: en af læserne af maksembedded, “coolpales” har skrevet denne kode, og det fungerede for ham.
bemærk, at denne kode ikke er testet endnu! Så hvis nogen af jer prøver det, skal du sende dine resultater her, jeg ville være glad for at se dem! 🙂
metodologi – PV-tilstand
Okay, så lad os nu lære om PV-tilstand. I AVR er der styr på udstyret. Dette betyder, at alt, med alt hvad jeg mener “alt”, udføres af AVR CPU. Alt du skal gøre er at initialisere og starte timeren, og indstille arbejdscyklus! Sejt, ikke?! Lad os lære hvordan!
her har jeg brugt Timer0 af ATMEGA32 til demonstration. Du kan også vælge en hvilken som helst anden timer eller AVR-mikrocontroller. Lad os nu se på registre.
TCCR0 – Timer/Counter0 kontrol Register
vi er stødt på dette register i min Timer0 tutorial. Her lærer vi, hvordan du indstiller passende bits til at køre timeren i PMM-tilstand.
TCCR0 Register
vi vil kun diskutere de bits, der er af interesse for os nu.
- Bit 6,3 – BGM01:0 – Bølgeformgenereringstilstand – disse bits kan indstilles til enten “00” eller “01” afhængigt af den type PV, du vil generere. Her er opslagstabellen.
bølgeform Generation tilstand Bit beskrivelse
- Bit 5,4-COM01: 0 – Sammenlign Matchudgangstilstand-disse bits er indstillet til at kontrollere opførslen af Output Sammenlign pin (OC0, pin 4 i ATMEGA32) i overensstemmelse med VGM01:0 bits. Følgende opslagstabel bestemmer operationerne for OC0-pin for hurtig PM-tilstand.
Sammenlign Outputtilstand, hurtig PV-tilstand
lad os nu se på de hurtige PV-bølgeformer. Detaljeret forklaring kan findes i min tidligere tutorial.
hurtig PCM
lad mig nu minde dig om, at AVR-PCM ‘en er fuldt styret, hvilket betyder, at selv timer-sammenligningsoperationen udføres af AVR-CPU’ en. Alt, hvad vi skal gøre, er at fortælle CPU ‘ en, hvad vi skal gøre, når en kamp opstår. COM01: 0-stifterne kommer i spil her. Vi ser, at ved at indstille den til “10” eller “11”, er outputstiften OC0 enten indstillet eller ryddet (med andre ord bestemmer den, om PVM er i omvendt tilstand eller i ikke-omvendt tilstand).
tilsvarende for Fasekorrekt PVM går opslagstabellen og bølgeformerne sådan.
Sammenlign Outputtilstand, Fasekorrekt PV-tilstand
Phase Correct PV
selv her bestemmer indstilling af COM01:0 til “10” eller “11” opførsel af OC0-pin. Som vist i bølgeformerne er der to tilfælde – en under optælling og andre under nedtælling. Adfærden er tydeligt beskrevet i opslagstabellen.
bemærk, at OC0 er en output pin. Derfor vil virkningerne af VVM og COM ikke komme i spil, medmindre ddrc-registret er indstillet korrekt. Se denne vejledning for mere info.
- Bit 2:0 – CS02:0 – Clock Select Bits – disse bits er allerede diskuteret i Timer0 tutorial.
OCR0 – Output Sammenlign Register
vi er stødt på selv dette register i min Timer0 tutorial. Vi bruger dette register til at gemme sammenligningsværdien. Men når vi bruger Timer0 i PMM-tilstand, fungerer den værdi, der er gemt i den, som arbejdscyklussen (naturligvis!). I problemstillingen er det givet, at arbejdscyklussen er 45%, hvilket betyder
OCR0 = 45% of 255 = 114.75 = 115
og det er det! Nu er vi klar til at skrive en kode til det! 🙂
Rediger: Bemærk
følgende kode diskuterer, hvordan du opretter et PV-signal for en ønsket arbejdscyklus. Hvis du ønsker at ændre frekvensen, skal du ændre den øverste værdi, hvilket kan gøres ved hjælp af Icrk-registret (som ikke understøttes af 8-bit timere). For 16-bit Timer1 kan det varieres ved hjælp af ICR1A.jeg vil diskutere om dette snart, når vi diskuterer om servostyring.
kode
så her går koden. Hvis du vil vide mere om I/O-portoperationer i AVR, skal du se dette. At vide om bit manipulationer, se dette. For at lære at bruge AVR Studio 5, Se dette. Hvis du vil vide, hvordan denne kode er struktureret, skal du se det forrige TIMER0-indlæg.
#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; }}
problemstilling
så nu, lad os tage en anden problemstilling. Denne ene vil være en mere af en praktisk ting i modsætning til den foregående!
lad os tage den traditionelle LED-flasher, hvor vi skal blinke en LED med en bestemt frekvens. Men hej, vent, diskuterede vi det ikke længe tilbage i dette indlæg (rul ned mod slutningen)? Hmm, så lad os ændre det for at indarbejde PMV. I modsætning til den traditionelle LED-flasher (hvor lysdioder enten er tændt eller slukket), lad os få det til at lyse ved den maksimale lysstyrke, og sænk derefter langsomt lysstyrken, indtil den når nul, og øg derefter lysstyrken langsomt, indtil den bliver maksimal.
analyse og kode
så hvordan gør vi det? Ja, du gættede det rigtigt! Sænk arbejdscyklussen langsomt fra 255 til nul, og øg den derefter fra nul til 255. Afhængig af driftscyklussen varierer spændingen på LED ‘ en og dermed lysstyrken. Følgende formel giver forholdet mellem spænding og driftscyklus.
så her går koden. Jeg vil ikke forklare det, du kan afkode det selv. Hvis du vil vide mere om I/O-portoperationer i AVR, skal du se dette. At vide om bit manipulationer, se dette. For at lære at bruge AVR Studio 5, Se dette. Hvis du vil vide, hvordan denne kode er struktureret, skal du se det forrige TIMER0-indlæg.
// 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 }}
så her slutter min anden meget ventede og lange tutorial! Næste op.. Seriel Kommunikation! Vi ses!! 🙂
og ja, hvis du har forslag, tvivl, konstruktiv kritik osv., er du meget velkommen til at droppe en note nedenfor! Abonner på min blog eller tag RSS-Feeds for at holde dig opdateret!