Saya mencoba membuat remote control RGB LED menggunakan ATtiny13A.
Saya tahu ATtiny85 lebih cocok untuk tujuan ini, dan saya tahu saya mungkin pada akhirnya tidak dapat memenuhi seluruh kode, tetapi untuk saat ini perhatian utama saya adalah untuk menghasilkan PWM perangkat lunak menggunakan interupsi dalam mode CTC.
Saya tidak dapat beroperasi dalam mode lain (kecuali untuk PWM cepat dengan OCR0A
seperti TOP
yang pada dasarnya adalah hal yang sama) karena kode penerima IR Saya menggunakan membutuhkan frekuensi 38 kHz yang menghasilkan menggunakan CTC dan OCR0A=122
.
Jadi saya mencoba (dan saya telah melihat orang-orang menyebutkan ini di Internet) menggunakan Output Compare A
dan Output Compare B
memotong untuk menghasilkan PWM perangkat lunak.
OCR0A
, yang juga digunakan oleh kode IR, menentukan frekuensi, yang tidak saya pedulikan. Dan OCR0B
, menentukan siklus tugas PWM yang akan saya gunakan untuk mengubah warna LED.
Saya berharap bisa mendapatkan PWM dengan siklus tugas 0-100% dengan mengubah OCR0B
nilai dari 0
menjadi OCR0A
. Inilah pemahaman saya tentang apa yang harus terjadi:
Tapi yang sebenarnya terjadi adalah ini (ini dari simulasi Proteus ISIS):
Seperti yang Anda lihat di bawah, saya bisa mendapatkan sekitar 25% -75% siklus tugas tetapi untuk ~ 0-25% dan ~ 75-100% bentuk gelombang hanya macet dan tidak berubah.
Baris KUNING: Perangkat Keras PWM
Garis merah: Perangkat lunak PWM dengan siklus tugas tetap
Garis HIJAU: Perangkat lunak PWM dengan berbagai siklus tugas
Dan ini kode saya:
#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
digunakan oleh kode IR jadi saya hanya punya OCR0B
. Saya mencoba menggunakannya untuk menghasilkan perangkat lunak PWM pada 3 pin non-PWM.