AVR MCU Tutorial - PWM Dimming

Publisher:SereneDreamerLatest update time:2020-09-09 Source: eefocusKeywords:AVR Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

PWM

The driving mode of the two-digit digital tube is dynamic scanning, and each bit is only lit for 50% of the time. We call this value its duty cycle. Let the pin output high level to light up the LED, and the duty cycle is 100%.


When driving the digital tube, we have to make the duty cycle 50% because we cannot let the two digits display different numbers at the same time. However, we can also intentionally make the duty cycle of the LED less than 100% to reduce its brightness.


The duty cycle can be adjusted by program. The following program allows the user to adjust the duty cycle of the blue LED by pressing buttons and display it through the digital tube.


#include


#define DUTY_MAX 9


int main()

{

    led_heat();

    button_init(PIN_NULL, PIN_NULL);

    segment_init(PIN_NULL, PIN_8);

    uint8_t duty = 0;

    while (1)

    {

        if (button_pressed(BUTTON_0) && duty > 0)

            --duty;

        if (button_pressed(BUTTON_1) && duty < DUTY_MAX)

            ++duty;

        segment_dec(duty);

        segment_display(SEGMENT_DIGIT_R);

        for (uint8_t i = 0; i != DUTY_MAX; ++i)

        {

            if (i < duty)

                led_set(LED_BLUE, true);

            else

                led_set(LED_BLUE, false);

            delay(1);

        }

    }

}

duty is an integer ranging from 0 to 9, which means the duty cycle of the LED is 0/9 to 9/9. For example, when the duty cycle is 4/9, in a 9 millisecond cycle, the LED is on for the first 4 milliseconds and off for the last 5 milliseconds.


It can be seen that the larger the duty cycle, the higher the LED brightness. It turns out that the LED has an intermediate state between bright and dark. We do this not by letting the pin output a voltage between 0V and 5V, but by letting the pin level change rapidly between high and low.


This technology, which achieves analog effects through rapid level changes, is called pulse width modulation, or PWM for short.


Timer

Most MCU timers can output PWM waves, and the AVR MCU with rich peripherals is no exception. In the previous lecture, we mentioned that Timer 0 has four working modes, the last two of which are fast PWM mode and phase correction PWM mode.


In fast PWM mode, the action of TCNT0 register is the same as that in normal mode, but OCR0A can also be used as the upper limit. For non-inverting output, after TCNT0 reaches the upper limit and is cleared, the pin will output a high level; when TCNT0 matches OCR0A or OCR0B, OC0A and OC0B will output a low level respectively; for inverting output, the former is low and the latter is high. Generally, non-inverting is used, and the frequency of the output PWM wave is fCPU/256N (for the case where the upper limit is 255; N is the frequency division coefficient), and the duty cycle is (OCR0x+1)/256. Since the denominator of the duty ratio 256 is 2 to the 8th power, this PWM output has an 8-bit resolution.


Phase correction PWM is mainly used in motor control and other occasions where the shape of the PWM wave is strictly required. I will not go into details here. Timer 1 has more working modes, and Timer 2 has a richer clock system. You can find out more in the data sheet.


Library

In the duty cycle formula (OCR0x+1)/256, OCR0x can take values ​​from 0 to 255, so the duty cycle can reach 1, and the LED can reach maximum brightness in PWM mode; the duty cycle cannot reach 0, so the LED controlled by PWM cannot be completely dark. This is a bit troublesome, and the PWM must be turned off to dim the LED, not just write a value to OCR0x. For future convenience, we use functions to wrap register operations (the entire library is doing this).


In Atmel Studio, static libraries and executable programs both belong to projects and can exist side by side in a solution. In the solution to which the PWM software program belongs, click the menu bar File->New->Project (or Ctrl+Shift+N), select "GCC C Static Library Project", name it "pwm", select "Add to solution" in "Solution:", select "OK" and select the MCU model, and the static library project will be created, with a library.c file by default.


In "Solution Explorer", rename library.c to oc0a.c. Select the "pwm" project, right-click -> Add -> New Item or menu bar -> Project -> Add New Item or Ctrl+Shift+A, select "Include File", and name it oc0a.h (usually the same name is used, but it is not necessary).


This library needs to provide two functions: oc0a_init is used to configure the OC0A pin as PWM output, and oc0a_pwm sets the output PWM duty cycle. The parameter is an unsigned 8-bit integer.


// oc0a.h


#ifndef OC0A_H

#define OC0A_H


#include


/*

 * Function: oc0a_init

 * Parameters: None

 * Return: void

 * Function: Configure OC0A pin as PWM output with a duty cycle of 0.

 */

void oc0a_init();


/*

 * Function: oc0a_pwm

 * Parameter: uint8_t _duty - integer representation of duty cycle

 * Return: void

 * Function: Set the duty cycle of the PWM wave output by the OC0A pin to (_duty / 256).

 */

void oc0a_pwm(uint8_t _duty);


#endif

In the header file oc0a.h, we define these two functions and provide descriptions in the form of comments, including parameters, return values, and functions.


Then, provide the implementation of these functions in oc0a.c.


// oc0a.c


#include "oc0a.h"

#include


void oc0a_init()

{

    PORTB &=   ~(1 << PORTB3); // PB3 low level

    DDRB  |=     1 << DDB3;    // PB3 output mode

    TCCR0A =  0b00 << COM0A0   // normal port operation

           |  0b11 << WGM00;   // fast PWM mode

    TCCR0B =   0b0 << WGM02    // fast PWM mode

           | 0b010 << CS00;    // divide by 8

}


void oc0a_pwm(uint8_t _duty)

{

#define COMA_MASK (~(0b11 << COM0A0)) // mask for COMnA bits

    if (_duty)                        // fast PWM mode

        TCCR0A = (TCCR0A & COMA_MASK) // protect other bits

               | 0b10 << COM0A0,      // non-inverting mode

        OCR0A  = _duty - 1;           // duty = (OCRnx + 1) / 256

    else                              // turn PWM off

        PORTB &= ~(1 << PORTB3);      // PB3 low level

        TCCR0A = (TCCR0A & COMA_MASK) // protect other bits

               | 0b00 << COM0A0;      // normal port operation

}

The implementation file should first include the corresponding header file to ensure consistent function interfaces.


As the encapsulation of the underlying operation, these functions involve many registers. The operation of the register is not written as a direct assignment of a number, but is a combination of multiple bit operations, which is unique to single-chip microcomputer programming. For example, the PORTB3 macro is defined in , and the value is 3, which means that the third bit of PORTB (the lowest bit is the 0th bit) controls the PB3 pin; 1 << PORTB3 generates a number with this bit as 1 and the rest as 0; take ~ from it, and get a number with only this bit as 0 and the rest as 1; let PORTB and this number perform &= operation, which can keep other bits unchanged and turn this bit into 0, because the result of "AND" of 0 and a bit is 0, and the result of "AND" of 1 and a bit is the value of that bit. For example, if COM0A0 is 6, 0b00 << COM0A0 fills COM0A1:0 with 00. Similarly, 0b11 << WGM00 fills WGM1:0 with 11. By performing the | operation on the two numbers, the two segments in TCCR0A are filled in at the same time (refer to the data manual for the bit definition).


Moreover, there are many reasons for writing like this: for registers such as PORTB, the function is only responsible for one bit, and the assignment statement will affect other bits; for registers such as OCR0A, clearly writing the name and value of each bit in the code can enhance readability.


If it is an open source library, the comments are for users who want to learn more about it; if it is a closed source library, published in the form of header files and library files, the comments are for future generations to read; in short, comments are needed. The purpose of comments is to eliminate the doubts of readers (including yourself). If the reader does not know the meaning of 0b010 << CS00, then "8 division" is noted, which is written in the data sheet; if the reader does not understand why -1 is required in the assignment statement of OCR0A, then the duty cycle formula is put there, which contains +1.


It is also worth noting that the above code is not very portable, because binary numbers with the 0b prefix are a GCC extension and are not part of the C language standard. The closest standard representation to binary is hexadecimal, but this requires manual conversion (creating a mapping between 0b0000 to 0b1111 and 0x0 to 0xF, just like F-AB to K-BD on a test paper), which is why the register assignments are written in expanded form.


Breathing light

To test this library, we create another new project, this time select "GCC C Executable Project". You must have done the following process many times. The difference is that the way to write the reference header file is a little different. The oc0a.h written before is located in the ../pwm/ directory, and ../ means the parent directory; and you need to manually add this library. In the "Solution Explorer", right-click on the "Libraries" of the project, click "Add Library", and check the "pwm" project in the "Project Libraries" page; now you can use the two functions you just wrote.


Let's achieve the effect of a breathing light, that is, the LED slowly changes from dark to bright and then dark again, like breathing.


#include

#include "../pwm/oc0a.h"


int main()

{

    oc0a_init();

    int brightness = 0, fadeAmount = 5;

    while (1)

    {

        oc0a_pwm(brightness);

        brightness = brightness + fadeAmount;

        if (brightness <= 0 || brightness >= 255)

            fadeAmount = -fadeAmount;

        delay(30);

    }

}

Connect the OC0A pin to any one of the RGBW on the left side of the development board, and you will see that the corresponding LED has a breathing light effect.

[1] [2]
Keywords:AVR Reference address:AVR MCU Tutorial - PWM Dimming

Previous article:AVR MCU Tutorial - LCD1602
Next article:Design of intelligent tracking vehicle model system based on ATMEGAl6 and graded steering module

Recommended ReadingLatest update time:2024-11-24 18:55

51单片机ADDA数模转换
概述 模拟量 模拟量是相对于数字量而言的。模拟量是对实际量的模拟,是连续变化的(比如用线圈的偏转来测电流或电压),测到的就是模拟量,指针可以指在两个数字中间的任何地方 从时间上来说,它是随时间连续变化的 从数值上来说,它的数值也是连续变化的。这种连续变化的物理量通称为模拟量 数字量 计算机中处理的是不连续变化的量,离散性的数字量 - 在自然界中,有一类物理量的变化在时间上和数量上都是离散的。也就是说,它们的变化在时间上是不连续的,总是发生在一系列离散的瞬间。同时,它们数值大小和每次的增减变化都是某一个最小数量单位的整数倍。我们把这一类的物理量叫做数字量。 当计算机用于数据采集和过程控制时,采集的对象往往是连续变化的物理量如
[Microcontroller]
51单片机ADDA数模转换
Installation of avr development environment under linux
(1) Install the development tool chain yum install avr-* The following tools will be installed avr-gcc-4.7.2-1.fc17.i686 avr-libc-1.8.0-2.fc17.noarch avr-binutils-2.23.1-1.fc17.i686 avr-gcc-c++-4.7.2-1.fc17.i686 avr-gdb-7.1-4.fc17.i686 avr-libc-doc-1.8.0-2.fc17.noarch (2) Installation (usbkey boot loader) yum install
[Microcontroller]
Design of intelligent fast charging system based on AT89C2051 single chip microcomputer
    1. Introduction   It has been 140 years since the French physicist Plante invented the lead-acid battery in 1859. Lead-acid batteries have the advantages of low cost, wide applicability, good reversibility, good high current discharge performance, high voltage of single cells, and can be made into sealed maintena
[Microcontroller]
Design of intelligent fast charging system based on AT89C2051 single chip microcomputer
Introduction to Misunderstandings in Software Anti-interference Technology of MCS51 Series Microcontrollers
There is a widespread misunderstanding in the microcontroller: in the MCS-51 series microcontroller, as long as the program is executed from the starting address with an instruction, the microcontroller can be reset to get rid of interference. Through a simple experiment, a reliable method of software reset is revea
[Microcontroller]
Realizing MCU Remote Communication with Pure Software
GMS972051 is a single-chip microcomputer with 2K E2PROM inside and compatible with MCS-51, produced by LG Corporation of South Korea. GMS97C2051 omits the P0 and P3 ports of MCS-51, but has an internal hardware comparator. Since the communication signal of the microcontroller is TTL level, if no other
[Microcontroller]
Realizing MCU Remote Communication with Pure Software
STC Monitor-51 MCU Online Simulation Debugging
introduction In many colleges and universities today, the teaching of single-chip microcomputers is still based on the classic 51 core single-chip microcomputer. The most important part of its experiments and application development is the comprehensive debugging of software and hardware. There are two main methods us
[Microcontroller]
STC Monitor-51 MCU Online Simulation Debugging
AVR microcontroller IIc bus programming
#define IIC_Start()          TWCR =(1 #define IIC_Stop()          TWCR =(1 TWINT)|(1 TWSTO)|(1 TWEN) #define IIC_Wait()           while(!(TWCR&(1 TWINT))) #define IIC_NoneAck()   TWCR =(1 TWINT)|(1 TWEN) #define IIC_Ack()           TWCR =(1 TWINT)|(1 TWEN)|(1 TWEA)   /*=========================================
[Microcontroller]
The main means to improve the anti-interference ability of single-chip microcomputer system
  1. Grounding   The grounding here refers to the earth, also known as the protective ground. Providing a good ground wire for the microcontroller system is extremely beneficial to improving the system's anti-interference ability. Especially for systems with lightning protection requirements, good grounding is essen
[Microcontroller]
Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号