我为Atmega128编写了一个pwm代码。我在比较匹配时使用具有非反相脉冲的快速pwm模式,我需要在特定时间更改OCR0值。但它并没有改变。谁知道这里有什么问题?
#include <avr/interrupt.h>
#include <avr/io.h>
uint8_t tick_1sec;
void timer1_init(void) // 1 second timer
{
OCR1A = 15624;
TIMSK |= (1<<OCIE1A);
TCCR1B = (1<<WGM12); //CTC mode
TCCR1B |= (1<<CS12)|(0<<CS11)|(1<<CS10);
}
ISR(TIMER1_COMPA_vect) //1 second interrupt
{
cli();
tick_1sec = 1;
sei();
}
void timer0_init(void) // fast pwm with OC0 non-inverting mode
{
TCCR0 = (1<<FOC0)|(1<<WGM01)|(1<<WGM00);
TCCR0 |= (1<<COM01)|(0<<COM00);
TCCR0 |= (1<<CS02)|(1<<CS01)|(1<<CS00);
OCR0 = 63;
TIMSK |= (1<<OCIE0);
}
int main(void)
{
uint8_t t = 0;
DDRB = 0xFF;
timer0_init();
timer1_init();
sei();
while(1){
if (tick_1sec)
{
tick_1sec = 0;
t++;
if (t == 10){
OCR0 = 127;
}
else if (t == 20){
OCR0 = 191;
}
else if (t == 30){
OCR0 = 63;
t = 0;
}
}
}
return 0;
}
答案 0 :(得分:2)
要检查的事项:
我建议将tick_1sec
声明为volatile
,以防止编译器对该寄存器进行超优化。
你的时钟频率是多少?只有当您的CPU频率为16MHz(==> 16.000.000 / 1024/15624)时,您的ISR才能提供1次通话
您的硬件中可能有一个LED,您可以在ISR
中的if ()
内的main
b)内反转,看看是否已达到此目的。
更新:“易变”
@skyrift在评论中提供的链接非常值得一读。
使用Atmel Studio时,使用/不使用volatile
关键字编译代码一次,并比较编译器正在执行的操作==&gt;解决方案资源管理器/输出文件/ * .lss ...您将看到每个C语句以及编译器如何将其转换为机器代码...在使用微处理器时偶尔进行一次练习......