[HỌC AVR] Bài 5: TẠO XUNG ĐIỀU RỘNG PWM VỚI AVR

XIN CHÀO CÁC BẠN!
Trong bài viết này, tôi xin hướng dẫn cho các bạn sử dụng một chế độ mới trong các bộ TIMER của AVR, đó là tạo xung điều rộng PWM. Ở đây tôi dùng Timer1 của Atmega8, trình biên dịch CodeVisionAVR.

I.CÁC KHÁI NIỆM TRONG ĐIỀU CHẾ PWM.

1.Điều chế PWM là gì?
Các bạn có thể hiểu đơn giản điều chế PWM là thay đổi duty cycle (khoảng thời gian tín hiệu ở mức cao) trong một chu kỳ (Time period) cố định, qua đó làm thay đổi điện áp trung bình cấp ra tải (sử dụng để thay đổi vận tốc động cơ DC,…).

Ta có:
T: chu kỳ của xung.
T1: là thời gian xung ở mức cao.
Hệ số điều chỉnh D(%): D = T1/T.
-Điện áp lớn nhất cấp cho tải: Udmax
-Điện áp trung bình cấp cho tải khi có PWM: Ud = Udmax.D

2.Điều chế PWM với Atmega8.

Bộ Timer1 của Atmega8 cung cấp cho chúng ta 2 kênh tạo xung điều rộng PWM:
-Kênh A: tín hiệu ra ở OC1A (PORTB.1)
-Kênh B: tín hiệu ra ở OC1B (PORTB.2)
Cùng nhiều chế độ tạo PWM (các bạn tham khảo thêm ở Datasheet) ở đây tôi sẽ nói rõ cho các bạn chế độ Fast PWM, mode 14 (Kênh A).
ØCác bạn thiết lập dạng tín hiệu PWM ra trên thanh ghi TCCR1A .
ØKhi hoạt động, ban đầu chân OC1A ở mức cao (tùy vào dạng tín hiệu PWM ra bạn chọn ở trên), TCNT1 tăng giá trị từ 0 cho đến khi bằng giá trị trên thanh ghi OCR1A thì chân OC1A được xóa về 0. TCNT1 vẫn tiếp tục tăng đến khi bằng giá trị trong thanh ghi ICR1 thì TCNT1 reset về 0 và chân OC1A được kéo lên mức cao.

Vì vậy ở đây, các bạn có thể thiết lập:
ØGiá trị của ICR1: là chu kỳ xung.
ØGiá trị của OCR1A: là thời gian xung ở mức cao.
Như vậy các bạn đã tạo ra được xung điều rông PWM với hệ số điều chỉnh tùy ý.

II.BÀI TOÁN VÍ DỤ

Để các bạn hiểu rõ hơn, tôi xin đưa ra bài toán:

Tạo PWM trên kênh A của vi điều khiển Atmega8 có chu kỳ 20ms, D1 = 50%:
ØKhi có ngắt ngoài 0, PWM có D2 = 75%.
ØKhi có ngắt ngoài 1, PWM có D3 =25%.
Với bài toán này, tôi cấu hình tần số Timer1 để sau 1us thì TCNT1 tăng 1 đơn vị:
ØChu kỳ T = 20ms = 20000us à ICR1 = 20000.
ØD1 = 50% à Thời gian trên mức 1 là 10us à OCR1A = 10000.
ØD2 = 25% à OCR1A = 5000.
ØD3 = 75% à OCR1A = 15000.

-Cấu hình tạo PWM với CodeVision:
Tạo Project mới à chọn CodeWizardAVR à chọn Timers à Chọn Timer1

Các bạn chọn:
-Chế độ tạo PWM ở Mode
-Dạng xung PWM xuất ra ở Out. A
-Giá trị của OCR1A ở Comp.A
-Giá trị của ICR1 ở Inp Capture

Code:

#include <main.h>
 
// TRINH PHUC VU NGAT CHO NGAT NGOAI 0             
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
    OCR1A = 15000; // 5ms, D =75%
}
 
// TRINH PHUC VU NGAT CHO NGAT NGOAI 1
interrupt [EXT_INT1] void ext_int1_isr(void)
{
    OCR1A = 5000; // 5ms, D =25%
// Place your code here
 
}
 
// Declare your global variables here
 
void main(void)
{
// Declare your local variables here
 
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=Out Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=0 State0=T
PORTB=0x00;
DDRB=0x02;
 
// KHOI TAO TIMER1
// Clock source: System Clock
// Clock value: 1000.000 kHz
// Mode: Fast PWM top=ICR1
// OC1A output: Non-Inv.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x82;  // CAU HINH CHO CAC CHE DO CHO TIMER
TCCR1B=0x1A;
TCNT1H=0x00;
TCNT1L=0x00;
// PWM KENH A =====================================================
//ICR1H=0x00;
//ICR1L=0x00;
ICR1 = 20000;
/*
    Bo chia Timer: sau 1us, TCNT1 tang 1 don vi
    ICR1 = 20000 --> CHU KY cua xung tin hieu T = 20000us = 20ms
*/
//OCR1AH=0x00;
//OCR1AL=0x00;
OCR1A = 10000;
/*
    OCR1 = 10000 --> Thoi gian tin hieu o muc 1 T1 = 10000us =10000ms
    Vay D = T1/T = 50%
*/
// PWM KENH B =====================================================
OCR1BH=0x00;
OCR1BL=0x00;
 
 
// KHOI TAO NGAT NGOAI
// INT0: On
// INT0 Mode: Rising Edge    // Ngat canh xuong
// INT1: On
// INT1 Mode: Rising Edge
GICR|=0xC0;
MCUCR=0x0F;
GIFR=0xC0;
 
// Global enable interrupts
#asm("sei")    // Cho phep ngat toan cuc
 
while (1)
      {
      // Place your code here
 
      }
}
// ------------------END OF FILE-------------------
// ------------------------------------------------

Các bạn có thể tham khảo code mẫu và mô phỏng Tại đây:

 

LEAVE A REPLY

Please enter your comment!
Please enter your name here