Tôi đang cố gắng tạo ra đèn LED RGB điều khiển từ xa bằng ATtiny13A.
Tôi biết ATtiny85 phù hợp hơn cho mục đích này và tôi biết cuối cùng tôi có thể không phù hợp với toàn bộ mã, nhưng bây giờ mối quan tâm chính của tôi là tạo ra một phần mềm PWM sử dụng các ngắt trong chế độ CTC.
Tôi không thể hoạt động trong bất kỳ chế độ khác (trừ PWM nhanh với OCR0A
như TOP
đó là cơ bản điều tương tự) vì mã máy thu IR Tôi đang sử dụng cần có một tần số 38 kHz mà nó tạo ra sử dụng CTC và OCR0A=122
.
Vì vậy, tôi đang cố gắng (và tôi đã thấy mọi người đề cập đến vấn đề này trên Internet) sử dụng Output Compare A
và Output Compare B
ngắt để tạo ra một phần mềm PWM.
OCR0A
, cũng được sử dụng bởi mã IR, xác định tần suất mà tôi không quan tâm. Và OCR0B
, xác định chu kỳ hoạt động của PWM mà tôi sẽ sử dụng để thay đổi màu LED.
Tôi hy vọng có thể có được một PWM với chu kỳ nhiệm vụ 0-100% bằng cách thay đổi OCR0B
giá trị từ 0
sang OCR0A
. Đây là sự hiểu biết của tôi về những gì sẽ xảy ra:
Nhưng những gì thực sự đang xảy ra là điều này (đây là từ mô phỏng Proteus ISIS):
Như bạn có thể thấy bên dưới, tôi có thể nhận được khoảng 25% -75% chu kỳ thuế nhưng với ~ 0-25% và ~ 75-100% dạng sóng chỉ bị kẹt và không thay đổi.
Dòng VÀNG: Phần cứng PWM
Dòng RED: Phần mềm PWM với chu kỳ nhiệm vụ cố định
Dòng XANH: Phần mềm PWM với chu kỳ nhiệm vụ khác nhau
Và đây là mã của tôi:
#ifndef F_CPU
#define F_CPU (9600000UL) // 9.6 MHz
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
int main(void)
{
cli();
TCCR0A = 0x00; // Init to zero
TCCR0B = 0x00;
TCCR0A |= (1<<WGM01); // CTC mode
TCCR0A |= (1<<COM0A0); // Toggle OC0A on compare match (50% PWM on PINB0)
// => YELLOW line on oscilloscope
TIMSK0 |= (1<<OCIE0A) | (1<<OCIE0B); // Compare match A and compare match B interrupt enabled
TCCR0B |= (1<<CS00); // Prescalar 1
sei();
DDRB = 0xFF; // All ports output
while (1)
{
OCR0A = 122; // This is the value I'll be using in my main program
for(int i=0; i<OCR0A; i++)
{
OCR0B = i; // Should change the duty cycle
_delay_ms(2);
}
}
}
ISR(TIM0_COMPA_vect){
PORTB ^= (1<<PINB3); // Toggle PINB3 on compare match (50% <SOFTWARE> PWM on PINB3)
// =>RED line on oscilloscope
PORTB &= ~(1<<PINB4); // PINB4 LOW
// =>GREEN line on oscilloscope
}
ISR(TIM0_COMPB_vect){
PORTB |= (1<<PINB4); // PINB4 HIGH
}
OCR0A
được sử dụng bởi mã IR nên tôi chỉ có OCR0B
. Tôi đang cố gắng sử dụng nó để tạo ra phần mềm PWM trên 3 chân không phải là PWM.