Điều Chế Độ Rộng Xung (PWM) Trong Vi Điều Khiển AVR Atmega16 / 32 - CodeVisionAVR
Tín hiệu PWM là gì?
Điều chế độ rộng xung (PWM) là tín hiệu kỹ thuật số được sử dụng phổ biến nhất trong mạch điều khiển. Thời gian tín hiệu duy trì ở mức cao được gọi là “thời gian mở” và thời gian tín hiệu ở mức thấp được gọi là “thời gian tắt”. Có hai tham số quan trọng đối với PWM như được thảo luận dưới đây:Chu kỳ hoạt động của PWM
Phần trăm thời gian mà tín hiệu PWM vẫn ở mức CAO (thời gian mở) được gọi là chu kỳ nhiệm vụ.Giống như trong tín hiệu xung 100ms, nếu tín hiệu CAO trong 50ms và THẤP trong 50ms, điều đó có nghĩa là xung có nửa thời gian CAO và nửa thời gian THẤP. Vì vậy, chúng ta có thể nói rằng chu kỳ nhiệm vụ là 50%. Tương tự nếu xung ở trạng thái CAO 25ms và 75ms ở trạng thái THẤP trong số 100ms, thì chu kỳ nhiệm vụ sẽ là 25%. Lưu ý rằng chúng tôi chỉ tính toán thời gian của trạng thái CAO. Bạn có thể tham khảo hình ảnh dưới đây để hiểu trực quan. Sau đó, công thức cho chu kỳ nhiệm vụ là,
Duty Cycle (%) = On Time/(On Time + Off Time)
Vì vậy, bằng cách thay đổi chu kỳ nhiệm vụ, chúng ta có thể thay đổi độ rộng của PWM, do đó dẫn đến thay đổi độ sáng của đèn LED. Chúng tôi sẽ có bản demo về việc sử dụng các chu kỳ nhiệm vụ khác nhau trong việc kiểm soát độ sáng của đèn LED. Kiểm tra Video demo ở cuối hướng dẫn này.
Sau khi chọn chu kỳ nhiệm vụ, bước tiếp theo sẽ là chọn chế độ PWM. Chế độ PWM chỉ định rằng bạn muốn PWM hoạt động như thế nào. Chủ yếu có 3 loại chế độ PWM.
- Fast PWM
- Phase Correct PWM
- Phase and Frequency Correct PWM
for(duty=255; duty>0; duty++)
{
OCR0=duty; //tăng từ từ độ sáng LED
_delay_ms(10);
}
for(duty=0; duty>255; duty--)
{
OCR0=duty; //giảm từ từ độ sáng LED
_delay_ms(10);
}
![]() |
Các chân ngõ ra PWM trên atmega 16/32 |
Cấu hình Timer0 để tạo PWM
Thật đơn giản để cấu hình chế độ PWM trong Bộ timer. Chúng ta chỉ cần thiết lập một số bit trong thanh ghi TCCR0.TCCR0: Thanh ghi điều khiển timer/counter 0
Chế độ Fast PWM
VD1. Viết chương trình sử dụng Timer 0 ở chế độ Fast PWM để điều khiển độ sáng của LED tăng dần và giảm dần bằng nút nhấn UP và DN.
Các bước thực hiện:
- Bước 1: Chọn chế độ hoạt động, để chọn được mode Fast PWM các bạn phải set bit WGM00 và WGM01 lên mức 1.
- Bước 2: Chọn chế độ so sánh, Non-inverted hoặc Inverted ở đây mình sẽ chọn chế độ Non-inverted => đưa bit COM01 lên 1.
- Bước 3: Chọn precaler, mình chọn bộ chia 8 nên chỉ cần set bit CS01 lên mức 1.
- Bước 4: Viết code điều khiển LED sáng dần tắt dần, Chân OC0 ở PORTB và là chân PB3 nhé các bạn.
Sơ đồ mô phỏng
Code
#include <mega16.h>
#include <delay.h>
#define UP PINB.0
#define DN PINB.1
unsigned char duty=0;
void PWM_init()
{
DDRB |= (1<<DDB3); //set OC0 pin as output
/*set Fast PWM mode with Non-inverted output, no precaling*/
TCCR0 = (1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00);
}
void PWM_write(unsigned char duty)
{
OCR0 = duty;
}
void main(void)
{
DDRB |= (0<<DDB1)|(0<<DDB0);
PWM_init();
PORTB = (1<<PORTB1)|(1<<PORTB0);
while (1)
{
if(UP==0)
{
duty+=5;
PWM_write(duty);
if(duty>255)duty=0;
while(UP==0);
}
if(DN==0)
{
duty-=5;
PWM_write(duty);
if(duty==255)duty=255;
while(DN==0);
}
}
}
Chế độ Phase Correct PWM
TCCR0 = (1<<WGM00)|(1<<COM01)|(1<<CS00)
Code
#include <mega16.h>
#include <delay.h>
unsigned char duty=0;
void PWM_init()
{
DDRB |= (1<<DDB3); //set OC0 pin as output
/*set Phase correct PWM mode with Non-inverted output,no precaler*/
TCCR0 = (1<<WGM00)|(1<<COM01)|(1<<CS00);
}
void main(void)
{
PWM_init();
while (1)
{
for(duty=0;duty<255;duty++)
{
OCR0 = duty;
delay_ms(10);
}
}
}
Đăng nhận xét