我正在尝试使用ATtiny13A制作遥控RGB LED灯。
我知道ATtiny85更适合于此目的,并且我知道我最终可能无法适应整个代码,但是现在我主要关心的是使用CTC模式下的中断生成软件PWM。
我不能在任何其它模式中操作(除了用快速PWM OCR0A
作为TOP
这基本上是相同的东西),因为我使用的IR接收器的代码需要它产生使用四氯化碳和38 kHz的频率OCR0A=122
。
因此,我试图(并且我已经在互联网上看到人们提到了这一点)使用Output Compare A
和Output Compare B
中断来生成软件PWM。
OCR0A
,IR代码也使用,它确定频率,我不在乎。并且OCR0B
,确定将用于更改LED颜色的PWM的占空比。
我期待能够通过改变来获得具有0-100%占空比的PWM OCR0B
从价值0
到OCR0A
。这是我对应该发生的事情的理解:
但是实际上是这样的(这是来自Proteus ISIS仿真):
正如您在下面看到的那样,我能够获得大约25%-75%的占空比,但是对于〜0-25%和〜75-100%,波形只是被卡住了并且不会改变。
黄线:硬件PWM
红线:具有固定占空比的软件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。