4012|4

3238

帖子

5

TA的资源

五彩晶圆(中级)

楼主
 

有关红外解码的问题 [复制链接]

我用延时的方法已经实现了红外解码,但是不知为何用TIMER1计数却得到的脉冲数串口输出分析后,感觉有问题。我使用的主频是32M,计数器分频到128。也就是1/4M.也就是说每次计数加1就是4us。不知道输出的脉冲计数值都很大,按理来说应该就是脉冲应该基本在一千左右的数。但是我的计数值竟然上万了,请问是什么原因呢?希望搞过的一起相互讨论学习。现在我把代码贴出来以供大伙一起研究分析
//本解码程序适用于NEC的upd6121及其兼容芯片的解码,支持大多数遥控器 实验板采用32M晶振
#include       //包含单片机寄存器的头文件
#define  IR    P1_0      //将IR位定义为P1.0引脚
#define  bool  char
#define  unint   unsigned int
#define  unchar  unsigned  char
unsigned char flag;
unsigned char a[4];    //储存用户码、用户反码与键数据码、键数据反码
unsigned int LowTime,HighTime; //储存高、低电平的宽度
/*****************************************************
函数功能:延时1ms
***************************************************/
void delay1ms()
{
  unsigned char i,j;
  for(i=0;i<10;i++)
   for(j=0;j<33;j++);   
}
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
void delay(unsigned char n)
{
   unsigned char i;
  for(i=0;i     delay1ms();
}
/************************************************************
函数功能:对4个字节的用户码和键数据码进行解码
说明:解码正确,返回1,否则返回0
出口参数:dat
*************************************************************/
bool DeCode(void)        
{   
unsigned char  i,j;
unsigned char temp;    //储存解码出的数据
for(i=0;i<4;i++)      //连续读取4个用户码和键数据码
   {
   for(j=0;j<8;j++)  //每个码有8位数字
    {
      temp=temp>>1;  //temp中的各数据位右移一位,因为先读出的是高位数据         
      T1CNTL=0;      //定时器清0
      T1CNTH=0;      //定时器清0
      T1CTL=0x01;    //打开定时器T1
      while(IR==0);  //如果是低电平就等待  //低电平计时
      T1CTL=0x00;    //关闭定时器T1
      LowTime=T1CNTH*256+T1CNTL;    //保存低电平宽度
      T1CNTL=0;      //定时器清0
      T1CNTH=0;      //定时器清0
      T1CTL=0x01;    //打开定时器T1
      while(IR==1);   //如果是高电平就等待  
      T1CTL=0x00;    //关闭定时器T1
      HighTime=T1CNTH*256+T1CNTL;   //保存高电平宽度
      if((LowTime*4<520)||(LowTime*4>680))
           return 0;        //如果低电平长度不在合理范围,则认为出错,停止解码   
      if((HighTime*4>550)&&(HighTime*4<660))   //如果高电平时间在560微秒左右,即计数560/1=560次
              temp=temp&0x7f;       //(560-100=550, 560+100=660),则该位是0
      if((HighTime*4>1350)&&(HighTime*4<1930)) //如果高电平时间在1680微秒左右,即计数1680/1=1680次
              temp=temp|0x80;       //(1680-250=1350,1680+250=1930),则该位是1
       }                 
    a=temp; //将解码出的字节值储存在a                     
    }         
  if(a[2]=~a[3])  //验证键数据码和其反码是否相等,一般情况下不必验证用户码
  return 1;     //解码正确,返回1
  else
  return 0;  //解码失败,返回0
}
/*******************************************************************
函数功能:整形转化为ascii
函数参数:参数pulse为要转化的红外脉冲,参数str为转化后的脉冲字符串
函数返回值:void
********************************************************************/
void inttoasc(unint pulse, unchar * str )
{
*str=pulse/10000+'0'; //保存脉冲的万位
*(str+1)=(pulse%10000)/1000+'0';//保存脉冲的千位
*(str+2)=(pulse%1000)/100+'0';//保存脉冲的百位
*(str+3)=(pulse%100)/10+'0';//保存脉冲的十位
*(str+4)=pulse%10+'0';//保存脉冲的个位
*(str+5)='\n';      //换行
}
/****************************************************************
   串口初始化函数   
****************************************************************/
void initUARTSEND(void)
{
    CLKCONCMD &= ~0x40;                          //设置系统时钟源为32MHZ晶振
    while(CLKCONSTA & 0x40);                     //等待晶振稳定
    CLKCONCMD &= ~0x47;                          //设置系统主时钟频率为32MHZ 定时器分频为1/4M
    PERCFG = 0x00;    //位置1 P0口
    P0SEL = 0x3c;    //P0_2,P0_3,P0_4,P0_5用作串口
    P2DIR &= ~0XC0;                             //P0优先作为UART0
    U0CSR |= 0x80;    //UART方式
    U0GCR |= 9;           
    U0BAUD |= 59;    //波特率设为19200
    UTX0IF = 0;                                 //UART0 TX中断标志初始置位0
}
/****************************************************************
串口发送字符串函数   
****************************************************************/
void UartTX_Send_String(char *Data,int len)
{
  int j;
  for(j=0;j   {
    U0DBUF = *Data++;
    while(UTX0IF == 0);
    UTX0IF = 0;
  }
}
void IRDecode_init(void)
{
  IEN2 |= 0X10;   // 允许P1口中断使能;
  P1IEN |= 0X1;  //P10设置为中断使能位;
  PICTL |= 0X2; // 下降沿触发   
  P1IFG = 0x00;   // 初始化中断标志位
  T1CTL=0x00;    //关闭定时器T1
  EA=1;        //开启总中断
}
/************************************************************
函数功能:主函数
*************************************************************/
void main()
{
initUARTSEND();
IRDecode_init();
while(1);   //等待红外信号产生的中断   
}
/************************************************************
函数功能:红外线触发的外中断处理函数
*************************************************************/
#pragma vector = P1INT_VECTOR    //格式:#pragma vector = 中断向量,紧接着是中断处理程序
__interrupt void P1_ISR(void)
  {
static  unchar str[6];
   //EX0=0;      //关闭外中断0,不再接收二次红外信号的中断,只解码当前红外信号
  P1IEN &=~0X1;  //P10设置为中断使能位失效;
  T1CNTL=0;      //定时器清0
  T1CNTH=0;      //定时器清0
  T1CTL=0x01;    //打开定时器T1
  while(IR==0);          //如果是低电平就等待,给引导码低电平计时  
  T1CTL=0x00;    //关闭定时器T1
  LowTime=T1CNTH*256+T1CNTL;  //保存低电平时间
  T1CNTL=0;      //定时器清0
  T1CNTH=0;      //定时器清0
  T1CTL=0x01;    //打开定时器T1
  while(IR==1);  //如果是高电平就等待,给引导码高电平计时
  T1CTL=0x00;    //关闭定时器T1
  HighTime=T1CNTH*256+T1CNTL; //保存引导码的高电平长度
  UartTX_Send_String("LOW:",sizeof("LOW:"));
  inttoasc(LowTime,str);
  UartTX_Send_String(str,sizeof(str));
  UartTX_Send_String("HIGH:",sizeof("HIGH:"));
  inttoasc(HighTime,str);
  UartTX_Send_String(str,sizeof(str));
  //if((LowTime*4>8500)&&(LowTime*4<9500)&&(HighTime*4>4000)&&(HighTime*4<5000))
  if((LowTime*4>8500)&&(LowTime*4<9500))
  {
   //如果是引导码,就开始解码,否则放弃,引导码的低电平计时
    //次数=9000us/1us=9000, 判断区间:9000-500=8500,9000+500=9500.
   UartTX_Send_String("oye",sizeof("oye"));
  if(DeCode()==1) // 执行遥控解码功能
   {
     UartTX_Send_String("OK",sizeof("OK"));
   }
   }
P1IEN |=0X1;  //P10设置为中断使能位;
}
此帖出自无线连接论坛

最新回复

在中断入口设置断点,看是不是代码无法进入中断呀  详情 回复 发表于 2013-4-3 13:24

点评

在中断入口设置断点,看是不是代码无法进入中断呀  详情 回复 发表于 2013-4-3 13:24
点赞 关注
个人签名淘宝:https://viiot.taobao.com/Q群243090717
多年专业物联网行业经验,个人承接各类物联网外包项目
 

回复
举报

7815

帖子

57

TA的资源

裸片初长成(中级)

沙发
 
都快看晕了.....

无关的子程序贴出来干什么?
TIMER1在哪,为什么我找了半天没找到这个宏或者变量
此帖出自无线连接论坛
 
 

回复

3238

帖子

5

TA的资源

五彩晶圆(中级)

板凳
 
你最好看英文的datasheet。就是在定时器那章节。
此帖出自无线连接论坛
个人签名淘宝:https://viiot.taobao.com/Q群243090717
多年专业物联网行业经验,个人承接各类物联网外包项目
 
 
 

回复

986

帖子

0

TA的资源

五彩晶圆(初级)

4
 

回复 楼主 wateras1 的帖子

在中断入口设置断点,看是不是代码无法进入中断呀
此帖出自无线连接论坛
个人签名电子工程师技术交流QQ群:12425841,专注于自动控制、数字电源等
 
 
 

回复

3238

帖子

5

TA的资源

五彩晶圆(中级)

5
 
进入了中断,我后来发现那个定时器有问题,貌似直接把T1CNTL=0;     无法把计数器值置为0,可是数据手册说,只要给它任何值就可以把这个计数器清到0.搞不懂为什么。那样导致计的高低电平的高八位不会清到。导致计数出错,我也是找了好久才发现。
此帖出自无线连接论坛
个人签名淘宝:https://viiot.taobao.com/Q群243090717
多年专业物联网行业经验,个人承接各类物联网外包项目
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
快速回复 返回顶部 返回列表