starsky0816 发表于 2012-1-24 20:59:55

求助,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;
      }
   }   
}

   }
}

JZcrystalwlh888 发表于 2014-8-31 22:47:37

楼主的程序不成功

szyxyhy 发表于 2014-9-1 00:27:52

你也可以收到中断之后开定时器, 反正目的都是为了计算IR的信号长度。

例程里这句
    if(irtime<63&&irtime>=33)//引导码 9ms+4.5ms
               i=0;

会将收到中断之前的无效计数去掉,相当于收到中断之后开定时器。

JZcrystalwlh888 发表于 2014-9-5 23:17:10

不对呀,楼主烧进去试一下可以遥控吗,不要拿网上的转过来哦。

JZcrystalwlh888 发表于 2014-9-6 14:45:33

楼主的程序有问题,编译出错啊
页: [1]
查看完整版本: 求助,avr单片机用定时器实现的红外