ATtiny13Aを使ってリモコンのRGB LEDライトを作ろうとしています。
私はATtiny85がこの目的により適していることを知っており、最終的にコード全体に適合できない可能性があることを知っていますが、今のところ私の主な関心事はCTCモードで割り込みを使用してソフトウェアPWMを生成することです。
私は(と高速PWM以外の他のモードで動作することができないOCR0A
ようにTOP
、私が使用していたIR受信コードは、それがCTCを使用して生成する38 kHzの周波数を必要とするため、基本的に同じものです)OCR0A=122
。
だから私は(そしてインターネットでこれが言及されているのを見たことがあります)、ソフトウェアPWMを生成するために割り込みOutput Compare A
とOutput Compare B
割り込みを使用しようとしています。
OCR0A
IRコードでも使用されるは、周波数を決定しますが、これは気にしません。そしてOCR0B
、LEDの色を変更するために使用するPWMのデューティサイクルを決定します。
OCR0B
値をから0
に変更することで、デューティサイクルが0〜100%のPWMが得られると期待していますOCR0A
。これは何が起こるべきかについての私の理解です:
しかし実際に起こっていることはこれです(これはProteus ISISシミュレーションからです):
以下を見るとわかるように、約25%〜75%のデューティサイクルを取得できますが、〜0-25%および〜75-100%の場合、波形はスタックし、変化しません。
黄色の線:ハードウェアPWM
REDライン:固定デューティサイクルのソフトウェアPWM
緑のライン:デューティサイクルが変化するソフトウェアPWM
そして、これが私のコードです:
#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
私は持っているので、IRコードで使用されますOCR0B
。3つの非PWMピンでソフトウェアPWMを生成するためにそれを使用しようとしています。