求助,avr单片机用定时器实现的红外
以下是在本论坛找的一个程序,试了试能工作,但有些地方不明白,定时器为什么一开始就打开,而不是产生了中断之后再打开,哪位高手能讲讲啊#include <iom16v.h>
#include <macros.h>
#include "74595_8LED.h"
//蜂鸣器定义
#define BUZZ_ON PORTB &= ~(1 << PB7) //输出低电平
#define BUZZ_OFF PORTB |= (1 << PB7) //输出高电平
unsigned charirtime;//红外用全局变量
unsigned char irpro_ok,irok;
unsigned char IRcord;
unsigned char irdata;
//延时函数
void delayms(int i) // 1MS* I
{
int j,k;
for(j=0;j<i;j++)
{for(k=0;k<1300;k++);}
}
/********蜂鸣器鸣叫***************/
void buzzer(void)
{
BUZZ_ON;
delayms(50);
BUZZ_OFF;
}
/******************************************************************/
/* 定时器1中断服务函数 */
/******************************************************************/
#pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
void timer1_ovf_isr(void)
{
//TIMER1 has overflowed
TCNT1H = 0xFF; //reload counter high value
TCNT1L = 0x07; //reload counter low value
irtime++;
display();//数码管驱动函数扫描
}
/******************************************************************/
/* 外部中断0函数 */
/******************************************************************/
#pragma interrupt_handler ex0_isr: 2
void ex0_isr (void)//外部中断0服务函数
{
static unsigned chari; //接收红外信号处理
if(irtime<63&&irtime>=33)//引导码 9ms+4.5ms
i=0;
irdata=irtime;//存储每个电平的持续时间,用于以后判断是0还是1
irtime=0;
i++;
if(i==33)
{
irok=1;
i=0;
}
}
/**************内部晶振8MHZ 8分频定时250US**********************/
//TIMER1 initialize - prescale:8
// WGM: 4) CTC, TOP=OCRnA
// desired value: 250uSec
// actual value: 250.000uSec (0.0%)
/*******************************************************************/
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0xFF; //setup
TCNT1L = 0x07;
TCCR1A = 0x00;
TCCR1B = 0x0A; //start Timer
}
void Ircordpro(void)//红外码值处理函数
{
unsigned char i, j, k;
unsigned char cord,value;
k=1;
for(i=0;i<4;i++) //处理4个字节
{
for(j=1;j<=8;j++) //处理1个字节8位
{
cord=irdata;
if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
{
value=value|0x80;
}
else
{
value=value;
}
if(j<8)
{
value=value>>1;
}
k++;
}
IRcord=value;
value=0;
}
irpro_ok=1;//处理完毕标志位置1
}
/******************************************************************/
/* 红外解码主函数处理 */
/******************************************************************/
void main(void)
{
DDRA= 0x38; //PA3/PA4/PA5为输出,其它的I/O为输入
DDRB= 0x80; //PB7为输出驱动蜂鸣器
DDRC= 0x00;
DDRD= 0x00;
PORTB = 0x80; //PB6输出高
timer1_init();
MCUCR = 0x02;
GICR= 0x40;
TIMSK = 0x04; //timer interrupt sources
SEI(); //re-enable interrupts
while(1)//主循环
{
if(irok) //如果接收好了进行红外处理
{
Ircordpro();
irok=0;
if(irpro_ok) //如果处理好后进行工作处理,如按对应的按键后显示对应的数字等
{
if (IRcord)
{
buzzer();
Led1 = IRcord/1000;
Led2 = IRcord%1000/100;
Led3 = IRcord%100/10;
Led4 = IRcord%10;
}
}
}
}
} 楼主的程序不成功 你也可以收到中断之后开定时器, 反正目的都是为了计算IR的信号长度。
例程里这句
if(irtime<63&&irtime>=33)//引导码 9ms+4.5ms
i=0;
会将收到中断之前的无效计数去掉,相当于收到中断之后开定时器。 不对呀,楼主烧进去试一下可以遥控吗,不要拿网上的转过来哦。 楼主的程序有问题,编译出错啊
页:
[1]