我调试这个程式用来做NEC协议的红外遥控解码,但是有问题,我找不到,请给位大神帮帮忙看看是哪里有问题。或者谁有已经调试好的PIC单片机程序红外线解码程序 给我参考一下也可以,先谢谢各位了!!!
我调试时候的现象是没有 解出code_data的值。
#include <pic.h> //调用PIC16F87XA单片机的头文件
__CONFIG(HS&WDTDIS&LVPDIS);
//---------------------------------------
//1602液晶相关I/O设置
//---------------------------------------
//红外解码寄存器设置
unsigned char tmr_times;
unsigned char code_data;
unsigned char code;
unsigned char int_times;
unsigned char buf1;
bit head_ok;
bit code_ok;
//---------------------------------------
//---------------------------------------
//名称:解码错误处理函数
//---------------------------------------
void wrong(void) //如果有错误,将相应寄存器清零,准备下一次接收
{
int_times=0;
tmr_times=0;
head_ok=0;
code_data=0;
code_ok=0;
}
//---------------------------------------
//名称:0或1判断函数
unsigned char one_zero(void)
{
//0编码的脉冲周期为1.12ms
//时间中断为0.25ms,所以我们判定取大于0.75ms小于1.5ms的脉冲均为0编码
if((tmr_times>3)&(tmr_times<6))
{
return 0;
}
//1编码的脉冲周期为2.24ms
//时间中断为0.25ms,所以我们判定取大于1.75ms小于2.75ms的脉冲均为0编码
else if((tmr_times>7)&(tmr_times<11))
{
return 1;
}
//如果脉冲周期不在0.75-1.5ms或者1.75-2.75ms区间的,我们认为是错码,返回2
return 2;
}
//---------------------------------------
//名称:中断服务程序
//---------------------------------------
void interrupt ISR(void) //PIC单片机的所有中断都是这一个入口
{
if(T0IF==1) //需要进一步判断是否是T0中断
{
TMR0=0x13; //定时器中断后,要重置初值,以备下次中断
T0IF=0; //清中断标志位,以备下次中断
//***此处用户自行添加定时器T0中断处理程序***
tmr_times++; //每250us计数一次
//******************************************
}
if(INTF==1) //需要进一步判断是否是INT中断
{
INTF=0; //清中断标志位,以备下次中断
GIE=0; //全局中断关掉,以避免解码过程进入其他中断
int_times++; //捕捉中断计次
if(head_ok==0) //如果还没接收到头码,那么先判断脉冲编码是否为头码
{
//参看遥控器芯片HT6221的说明书,发射代码的头码由一个9ms的起始码和一个4.5ms的结果码组成
//本例中,时间中断为0.25ms,所以我们判定大于12.5ms小于14.5ms的脉冲均为13.5ms的头码编码
if(tmr_times>50&tmr_times<58)
{
head_ok=1; //有效头码标志位置一,以示头码接收完成
int_times=0; //外部中断计次寄存器清零,以准备接收后面的4组共32个脉冲
tmr_times=0; //定时器中断计次寄存器清零,准备开始对后面的脉冲计时
}
else
{
wrong(); //如果不是有效的头码,转入错误处理程序
}
}
else //如果已经接收到头码,那么开始对后面的32个脉冲进行解码
{ //我调试的时候程序没有进入这个地方
code_data=code_data>>1; //将接收缓冲区右移一位,以准备接收下一位
buf1=one_zero(); //判断编码是0或1,或者是错码
tmr_times=0; //时间中断计次寄存器清零
if(buf1==1) //如果是编码1
{
code_data|=0x80; //将1移入code_data的最高位
}
else if(buf1==0) //如果是编码0
{
code_data&=0x7f; //将0移入code_data的最高位
}
else //编码非0非1,即为错码,
{
wrong(); //调用错误处理程序
return;
}
if(int_times==8) //如果收到了8个编码脉冲,意味着低8位地址码已经接收完
{
//本遥控器的低8位地址码为0X00,这个是遥控器厂家决定的,如果要订做,可以随便改
if(code_data!=0x00) //如果不是0x00 ,说明不是我们提供的遥控器,我们不予识别
{
wrong(); //调用错误处理程序
return;
}
}
else if(int_times==16) //如果收到了16个编码脉冲,意味着高8位地址码已经接收完
{
//本遥控器的低高8位地址码为0XFF
if(code_data!=0xFF) //如果不是0xff ,说明不是我们提供的遥控器,我们不予识别
{
wrong(); //调用错误处理程序
return;
}
}
else if(int_times==24) //收到的第三组8位字节即为8位数据码
{
code=code_data; //将这个8位数据码暂存至code_data1
}
else if(int_times==32) //收到的第四组8位字节即为8位数据码的反码
{
int_times=0; //清零中断次数寄存器,以便下次从头开始
head_ok=0; //将头码标志位清零,以便下次再接收时,从头码开始
if((code+code_data)==0xff) //判断第三组数据和第四组数据是否互为反码
{
code_ok=1; //如果互为反码,说明接收来的编码为正确,置位标志位,以通知液晶显示
}
}
}
GIE=1; //开放全局中断
}
}
//---------------------------------------
//名称: 主函数
//---------------------------------------
void main(void) //主函数,单片机开机后就是从这个函数开始运行
{
TRISB=0B11111111; //初始化RB7-RB0的输入输出方向
TRISD=0B00000000; //初始化RD7-RD0的输入输出方向
PORTB=0B00000000; //初始化RB7-RB0的数值
PORTD=0B00000000; //初始化RD7-RD0的数值
//***定时器TMR0初始化***
T0CS=0; //TMRO时钟源选择内部指令周期时钟(Fosc/4)
PSA=1; //预分频器分配给WDT
TMR0=0x13; //定时250微秒,置初值为256-250+13
T0IF=0; //清除TMR0的中断标志
T0IE=1; //TMR0中断允许
//**********************
//***外部中断RB0/INT初始化***
INTEDG=0; //设置RB0/INT为下降沿触发
INTF=0; //清除RB0/INT的中断标志
INTE=1; //设置RB0/INT中断允许
//***************************
//***开全局中断设置****
//外部中断RB0/INT设置了中断允许,此处要开全局中断
GIE=1; //开全局中断
//外部中断RB0/INT设置了中断允许,此处要允许所有未被屏蔽的外设中断
PEIE=1; //允许外设中断
//*********************
while(1) //死循环,单片机初始化后,将一直运行这个死循环
{
if(code_ok==1) //如果接收到了有效地的遥控器按键码
{
code_ok=0; //清掉该标志位
if(code==0x16) PORTD=0B00000001;
if(code==0x0c) PORTD=0B00000010;
if(code==0x18) PORTD=0B00000100;
if(code==0x5e) PORTD=0B00001000;
if(code==0x08) PORTD=0B00010000;
if(code==0x1c) PORTD=0B00100000;
if(code==0x5a) PORTD=0B01000000;
if(code==0x42) PORTD=0B10000000;
}
} |