AVR Timers-PWM Mode-Part II

AVR Seriesdit artikel is in vervolg op de vorige PWM post. Leer hoe u de timers programmeert om in PWM-modus te werken! Dus laten we beginnen!

Hallo mensen! Lang niet gezien! 🙂

in mijn vorige post hebben we de basisconcepten van PWM besproken. Laten we het eerst samenvatten:

  • PWM staat voor Pulse Width Modulation.
  • het kan worden gegenereerd door vooraf bepaalde golfvormen te vergelijken met een referentiespanningsniveau of door eenvoudige analoge circuits te maken.
  • de Duty Cycle van een PWM-golfvorm wordt gegeven door de volgende relatie.
Duty Cycle
  • er zijn drie modi van PWM – werking-Fast PWM, Phase Correct PWM en Frequency and Phase Correct PWM
  • hoe timer, operatiemodus en vergelijk outputmodus te kiezen voor het genereren van de gewenste PWM.
dus nu, zonder veel gedoe, laten we eens kijken hoe het te implementeren met behulp van de AVR microcontrollers. Voordat we verder gaan, stel ik voor dat je door mijn vorige berichten op Timers en PWM gaat.

laten we een probleemstelling nemen. We moeten een 50 Hz PWM signaal genereren met 45% inschakelduur.

analyse

gegeven dat

Frequency = 50 Hz

met andere woorden, de tijdsperiode, T

T = T(on) + T(off) = 1/50 = 0.02 s = 20 ms

ook, gegeven dat

Duty Cycle = 45%

dus, oplossend volgens bovenstaande vergelijking, krijgen we

T(on) = 9 msT(off) = 11 ms

nu, kan dit op twee manieren worden bereikt:

  1. gebruik Timer in CTC-modus
  2. gebruik Timer in PWM-modus

methodologie-CTC-modus

Oké, dus ik schrijf hier geen code (alleen de pseudo-code). Ik neem aan dat na het lezen van mijn vorige berichten, Je bent slim genoeg om er zelf een te schrijven! We zullen alleen de concepten bespreken.

kies eerst een geschikte timer. Voor deze toepassing, kunnen wij om het even welk van de drie beschikbare timers in ATMEGA32 kiezen. Kies een geschikte prescaler. Stel vervolgens de timer in en ga verder zoals gewoonlijk. De vangst ligt hier is dat je nodig hebt om de vergelijkingswaarde van ocrx register elke keer bij te werken. Een dergelijke manier wordt besproken in de pseudo-code hieronder gegeven.

dit is analoog aan de traditionele LED-flitser, behalve dat de aan-en uittijden verschillen.

pseudocode

#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 }}

Dit is één methode. En het is erg inefficiënt. U kunt de efficiëntie verhogen door het schrijven van een betere C-code (syntaxis-wise), maar het concept blijft hetzelfde. Als u een andere methode/concept, bent u van harte welkom om het hier te delen! 🙂

UPDATE: een van de lezers van maxEmbedded, “coolpales” heeft deze code geschreven, en het werkte voor hem.

houd er rekening mee dat deze code nog niet getest is! Dus, als een van jullie probeert het uit, post uw resultaten hier, Ik zou blij zijn om ze te zien! 🙂

methodologie – PWM Mode

ok, dus laten we nu leren over de PWM mode. De PWM-modus in AVR is hardwaregestuurd. Dit betekent dat alles, met alles bedoel ik “alles”, wordt gedaan door de AVR CPU. Alles wat u hoeft te doen is te initialiseren en start de timer, en stel de duty cycle! Cool, hè?! Laten we leren hoe!

hier heb ik Timer0 van ATMEGA32 gebruikt voor demonstratie. U kunt ook kiezen voor een andere timer of AVR microcontroller. Laten we nu eens kijken naar de registers.

TCCR0-Timer / Counter0 Control Register

dit register zijn we tegengekomen in mijn Timer0 tutorial. Hier leren we hoe je de juiste bits kunt instellen om de timer in PWM-modus te laten draaien.

Tccr0 Register

Tccr0 Register

we zullen alleen die bits bespreken die ons nu interesseren.

  • Bit 6,3-WGM01: 0 – Golfvormgeneratiemodus-deze bits kunnen worden ingesteld op “00” of “01”, afhankelijk van het type PWM dat u wilt genereren. Hier is de uitkijk tafel.
    Bit-beschrijving voor Golfvormgeneratie

    Bit-beschrijving voor Golfvormgeneratie

  • Bit 5,4-COM01: 0-vergelijk Match Outputmodus-deze bits worden geplaatst om het gedrag van Output te controleren vergelijk speld (OC0, speld 4 in ATMEGA32) in overeenstemming met de bits WGM01:0. De volgende opzoektabel bepaalt de verrichtingen van OC0 speld voor snelle PWM wijze.
    vergelijk uitvoermodus, snelle PWM-modus

    vergelijk uitvoermodus, snelle PWM-modus

    laten we nu eens kijken naar de snelle PWM-golfvormen. Gedetailleerde uitleg is te vinden in mijn vorige tutorial.

    Fast PWM

    Fast PWM

    nu wil ik u eraan herinneren dat de AVR PWM volledig hardwaregestuurd is, wat betekent dat zelfs de timervergelijking wordt uitgevoerd door de AVR CPU. Het enige wat we moeten doen is de CPU vertellen wat te doen zodra een match plaatsvindt. De com01: 0 pinnen komen hier in het spel. We zien dat door het in te stellen op “10” of “11”, de uitgangspin OC0 is ofwel ingesteld of gewist (met andere woorden, het bepaalt of de PWM is in omgekeerde modus, of in niet-omgekeerde modus).

    voor fase correcte PWM gaan de opzoektabel en de golfvormen als volgt.

    vergelijk uitvoermodus, fase Correct PWM-modus

    vergelijk uitvoermodus, fase Correct PWM-modus

    Phase Correct PWM

    Phase Correct PWM

    zelfs hier bepaalt het instellen van COM01:0 op “10” of “11” het gedrag van de OC0-pin. Zoals getoond in de golfvormen, zijn er twee gevallen – een tijdens het op-tellen, en andere tijdens het op-tellen. Het gedrag wordt duidelijk beschreven in de opzoektabel.

    merk op dat OC0 een uitgangspin is. Zo zullen de effecten van WGM en COM niet in het spel komen tenzij het ddrx register goed is ingesteld. Raadpleeg deze tutorial voor meer informatie.

  • Bit 2:0 – CS02: 0 – Klokkenselect Bits – deze bits worden al besproken in de timer0 tutorial.

Ocr0-Output vergelijk Register

we zijn zelfs dit register tegengekomen in mijn timer0 tutorial. We gebruiken dit register om de vergelijkingswaarde op te slaan. Maar wanneer we Timer0 in PWM-modus gebruiken, fungeert de waarde die erin is opgeslagen als de duty cycle (uiteraard!). In de probleemstelling is het gegeven dat de duty cycle 45% is, wat betekent

OCR0 = 45% of 255 = 114.75 = 115

en dat is het! Nu zijn we klaar om er een code voor te schrijven! 🙂

Edit: Note

de volgende code bespreekt hoe een PWM-signaal van een gewenste duty cycle kan worden gemaakt. Als u de frequentie wilt wijzigen, moet u de TOP waarde wijzigen, wat kan worden gedaan met behulp van het icrx register (dat niet wordt ondersteund door 8-bit timers). Voor 16-bit Timer1, kan het worden gevarieerd met behulp van ICR1A.

Code

dus hier gaat de code. Bekijk dit om meer te weten te komen over I/O-portbewerkingen in AVR. Om te weten over bit manipulaties, Bekijk dit. Bekijk dit om te leren hoe u AVR Studio 5 gebruikt. Om te leren hoe deze code is gestructureerd, bekijk de vorige TIMER0 post.

#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; }}

probleemstelling

laten we nu een ander probleemstelling nemen. Deze gaat een meer van een praktische dingen in tegenstelling tot de vorige!

laten we de traditionele LED-flasher nemen waar we een LED met een bepaalde frequentie moeten knipperen. Maar hey, wacht, hebben we het niet lang terug in deze post besproken (scroll naar beneden naar het einde)? Hmm, dus laten we het aanpassen om PWM op te nemen. In tegenstelling tot de traditionele LED-flitser (waar LED ‘ s aan of uit zijn), laten we het gloeien bij de maximale helderheid, en dan langzaam de helderheid verlagen tot het nul bereikt, en dan weer de helderheid langzaam verhogen tot het maximaal wordt.

analyse en Code

dus hoe doen we het? Ja, je hebt het goed geraden! Verlaag de duty cycle langzaam van 255 naar nul, en verhoog het dan van nul naar 255. Afhankelijk van de duty cycle, de spanning toegepast op de LED varieert, en dus de helderheid. De volgende formule geeft de relatie tussen spanning en duty cycle.

v_out vergelijking

dus hier gaat de code. Ik leg het niet uit, je kunt het zelf decoderen. Bekijk dit om meer te weten te komen over I/O-portbewerkingen in AVR. Om te weten over bit manipulaties, Bekijk dit. Bekijk dit om te leren hoe u AVR Studio 5 gebruikt. Om te leren hoe deze code is gestructureerd, bekijk de vorige TIMER0 post.

// 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 }}

dus hier eindigt mijn andere langverwachte en lange tutorial! De volgende.. Seriële Communicatie. Tot ziens!! 🙂

en ja, als je suggesties, twijfels, constructieve kritiek, enz. hebt, ben je van harte welkom om hieronder een opmerking te plaatsen! Abonneer je op mijn blog of pak de RSS-Feeds om op de hoogte te blijven!

Write a Comment

Het e-mailadres wordt niet gepubliceerd.