问题描述
我正在尝试在 atmega328p 中使用 TIMER1(16 位)创建 10 秒延迟,我不知道是否已创建延迟,因为它需要的持续时间超过 10 秒和预期输出(即创建 pwm 波)未获得。这里我创建了一个 1 秒的延迟并循环了 10 次,TIMER0 用于创建 pwm 波。
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "interrupt.h"
#define SET_BIT(PORT,BIT) PORT |= (1<<BIT)
#define CLR_BIT(PORT,BIT) PORT &= ~(1<<BIT)
struct {
volatile unsigned int BIT: 1;
}
FLAG_TIMER;
void timer_configuration() //16 bit timer
{
TCCR1A = 0x00; // normal mode of operation
TCNT1 = 0xC2F8;
TCCR1B |= ((1 << CS10) | (1 << CS12));
TCCR1B &= ~(1 << CS11); //101
sei(); // Global interrupt
}
void timer_on()
{
TimsK1 |= (1 << TOIE1);
}
void pwm_configuration() //TIMER0 - 8 bit
{
TCCR0A |= ((1<<WGM00) | (1<<WGM01)); //setting it to fast PWM mode
TCCR0A |= (1<<COM0A1);
TCCR0A &= ~(1<<COM0A0);
TCNT0 = 0x00;
TCCR0B |= ((1<<CS00) | (1<<CS02)); //Prescaler setting 1024
TCCR0B &= ~(1<<CS01);
sei();
}
ISR(TIMER1_OVF_vect)
{
static unsigned int counter;
counter++;
if(counter >= 10)
{
FLAG_TIMER.BIT=1;
counter = 0;
TCNT1 = 0xC2F8;
TimsK &= ~(1<< TOIE1);
}
else
{
FLAG_TIMER.BIT=0;
}
}
int main(void)
{
SET_BIT(DDRD,PD6); //CRO
timer_configuration();
pwm_configuration();
while(1)
{
timer_on();
if(FLAG_TIMER.BIT == 1)
{
OCR0A = 128; //50% dutycycle
}
}
解决方法
您在初始化时将计数器设置为 49912 并在它溢出时增加您的计数,但它随后将从 0 开始,因此如果 15624 个计数 = 1 秒,那么您的计数器将在 15624 + 9 x 216 计数或大约 38.75 秒。
在 ISR 中移动 TCNT1 = 0xC2F8;
行:
ISR(TIMER1_OVF_vect)
{
static unsigned int counter;
TCNT1 = 0xC2F8;
counter++;
if(counter >= 10)
{
FLAG_TIMER.BIT=1;
counter = 0;
TIMSK &= ~(1<< TOIE1);
}
else
{
FLAG_TIMER.BIT=0;
}
}
我不熟悉 ATmega,但我不相信这是使用计时器的合适方式。通常,您会向上计数到一个比较值并自动重置为零,或者从自动重新加载值向下计数到零并让硬件重新加载计数器。