搜索
bottom↓
回复: 63

利用PCA捕获捕获红外发射脉冲高、低电平时间,送串口显示( 含NEC、RC5解码 )

  [复制链接]

出0入0汤圆

发表于 2011-8-27 13:55:37 | 显示全部楼层 |阅读模式
直接上图

(原文件名:TP3.jpg)


(原文件名:TP0.jpg)


(原文件名:TP1.jpg)


(原文件名:TP2.jpg)


程序如下:
/***************************************************************
        作品:捕获红外发射脉冲高、低电平时间,送串口显示
  单片机:STC12C5410
    晶振:12M
编译环境:Keil uVision4 V9.00
***************************************************************/
//  说明:1、适用于:1T系列含有PCA捕获的STC单片机
//        2、捕获引脚PCA2(也就是P2.0),3字节存放一个电平时间数据。
//        3、串口显示脉冲高低电平时间数据(串口:字符 57600bps 校验位N 数据位8 停止位1),
//        4、含NEC、RC5解码,如需其它解码请自己加入。
//
//  NEC码:(芯片有 市场上用量最大的HT6121/6122及其兼容的IC芯片等)
//        RC5码:(芯片有 SAA3006、SAA3010、SAA3027、PCA8521、PT2210 等)

#define uchar unsigned char   
#define uint  unsigned int
#define ulong unsigned long
#include <STC12C5410AD.h>
#include <CKA.H>

sbit IR = P2^0;                        //捕获引脚PCA2

uchar xdata v[486];               
uchar N[4];
uint  t;
ulong nn;

bit   VT;                                //捕获完成标志
bit   B_Z;                                //丢弃第一次捕获标志

void  ChuanKou();            //串口发送主程序
void  IR_RC5();                        //RC5解码



/********************************************
函数:10ms × n 延时程序   STC 1T@12MHz
*********************************************/
void YS10ms(uchar n)
{
  uchar i,j,k;
  for(i=n;i!=0;i--)
  for(j=198;j!=0;j--)
  for(k=150;k!=0;k--);
}
/********************************************
函数:接收初始化
*********************************************/
void JS_Init(void)
{
  uint i;
  
  B_Z = 1;
  t   = 0;
  for(i=0;i<486;i++)v=0; //存储区清0
                         
  EPCA_LVD = 1;                        //PCA模块中断和低压检测中断允许位
  CCAPM2  |= 0x31;                 //PCA模块2:16位捕获模式,由CCP2的跳变触发。ECCF2=1,使能CCF2中断。
  CMOD     = 0x01;                    //ECF=1(CMOD.0=1)使能CF(CCON.7)位产生中断
  EA       = 1;

  P21      = 0;                            //开始接收,指示灯打开
}
/********************************************
函数:主程序
*********************************************/
void main(void)
{
  UartInit(12,1);
  JS_Init();
  YS10ms(10);

  ZIFUC("\r\n\r\n\r\n                ****** 开始接收,请按遥控 ******\r\n");

  while(1)
  {  
        if(VT)
        {
          VT  = 0;
          P21 = 1;                        //接收完成,指示灯关闭
          ChuanKou();                        //串口显示

          YS10ms(200);
          YS10ms(200);
          YS10ms(200);                    //6秒后重新开始
      
          JS_Init();

          ZIFUC("\r\n\r\n\r\n                ****** 可以重新接收,请按遥控 ******\r\n");
        }  
  }
}

/***************************************************************
函数:PCA中断捕获程序(电位跳变捕获模式)
***************************************************************/
void PCA_isr(void) interrupt 6 using 1
{
         if(CF)                                           //是否是PCA定时器溢出
         {
            CF = 0;                       //必须软件清0 (PCA 定时器标志)
                v[t]++;                //PCA定时器溢出计数,保存数据最高字节
                if(v[t]>1)                            //设置允许溢出次数,>131ms 终止捕获
                { CR = 0;   
                  CF = 0;
                  CCAPM2 = 0;
              CCF2=0;
                  VT=1;                       //捕获完成标志
                  v[t]=0;
                  return;
                }
         }

         if(CCF2)                                   //是否是电位跳变
         {
                   CCF2 = 0;              //必须软件清0 (PCA 模块2标志)
                CL   = 0;                     //先赋值低位
        CH   = 0;            

        if(B_Z){ CR =1;                   //启动PCA定时器
                         B_Z=0;
                                 return; }     //丢弃第一次捕获数据
                t++;
                v[t]=CCAP2H;               //保存数据高字节
            t++;
        v[t]=CCAP2L;               //保存数据低字节
            t++;               
         }

     if(t >= 486)                   //捕获162个数据(1个电平时间3字节存放)
         {
                 CCAPM2 = 0;
                 CCF2=0;
                 CR = 0;
                 CF = 0;
                 VT = 1;                           //捕获完成标志
         }
}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:串口发送主程序
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void ChuanKou()
{
          uchar i;
          uint        j,T;
          
          ZIFUC("\r\n\r\n                ****** 接收完成 ******");
          ZIFUC("\r\n\r\n ( 以下是遥控器发射脉冲的波形数据 )");
          ZIFUC("\r\n\r\n  序号  高电平时间(us)  低电平时间(us)\r\n\r\n");

          i=0;

          for(j=0;j<486;)
          {
                          ((uchar *)&nn)[0] = 0;
                          ((uchar *)&nn)[1] = v[j++];
                          ((uchar *)&nn)[2] = v[j++];
                          ((uchar *)&nn)[3] = v[j++];

                          ZIFUC("  ");
                          JZ(i,10,2);                                //序号
                          ZIFUC("   ");                                    
                          JZ(nn,10,8);                            //高电平时间

                          ((uchar *)&nn)[0] = 0;
                          ((uchar *)&nn)[1] = v[j++];
                          ((uchar *)&nn)[2] = v[j++];
                          ((uchar *)&nn)[3] = v[j++];

                          ZIFUC("        ");                                                              
                          JZ(nn,10,8);                             //低电平时间

                      if( (i%8)==0 )ZIFUC("\r\n\r\n");
                          else ZIFUC("\r\n");
                          i++;
          }
                          
        ///////////////// NEC解码 ////////////////          
          j=9;                                                                                 //引导码丢弃
          for(i=0;i<32;i++)
          {
                          j++;
                          ((uchar *)&T)[0] = v[j++];
                          ((uchar *)&T)[1] = v[j++];
                          j += 3;
                             
                          N[i/8] >>= 1;
                           if((T<1900) && (T>1000))N[i/8] |= 0x80;
          }

          if(N[2] == ~N[3])         //校验NEC操作码。错误则尝试RC5解码
          {                      
                             ZIFUC("\r\n 【 NEC通用编码格式:引导码 + 32位编码(16位用户码+操作码正反码) 】\r\n");
                             ZIFUC("\r\n 用户码(高8位):0x");
                             JZ(N[0],16,1);      
                             ZIFUC("\r\n 用户码(低8位):0x");
                             JZ(N[1],16,1);
                                 
                                 ZIFUC("\r\n\r\n 操作码正码     :0x");
                             JZ(N[2],16,1);     
                                 ZIFUC("\r\n");

                                 if(N[0] == ~N[1])
                                 {
                                          ZIFUC("\r\n\r\n 经对比,16位用户码是正反码,用户码正码:0x");
                                          JZ(N[0],16,1);
                                 }

                                 return;                                                 
          }           
                    
        ///////////////// 初略分析是否是RC5编码 ////////////////
          j=0;
          for(i=0;i<20;i++)                                         
          {
               j++;                                                                         //最高位丢弃(1个数据3字节);
                   ((uchar *)&T)[0] = v[j++];
                   ((uchar *)&T)[1] = v[j++];

              if(T<600 || T>1800)                                 //RC5码前20个脉冲数据600<nn<1800
                  {
                                  ZIFUC("\r\n 【 解码失败,再试一试或者分析波形数据 】");
                            return;
                  }
          }
        ///////////////// 将波形数据绘成图像 ////////////////
          ZIFUC("\r\n 【 RC5编码发射波形 】    发射顺序:(低位)<--(高位)\r\n");
          ZIFUC("\r\n___");
          
                j=0;
                for(i=0;i<26;i++)
                    {
                      j++;                                                                         //最高位丢弃(1个数据3字节);
                         ((uchar *)&T)[0] = v[j++];
                         ((uchar *)&T)[1] = v[j++];
                          if(T>2000)break;

                      if(i%2 != 1)                                                 //如果i是偶数
                          {
                                   if(T<1000)ZIFUC("▉");
                                   else       ZIFUC("▉▉");
                              }
                          else
                          {
                               if(T<950)ZIFUC("__");
                                   else       ZIFUC("____");
                              }
                    }

      ZIFUC("_____________");       
      ZIFUC("\r\n┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊\r\n");
          IR_RC5();                                                                       //RC5解码
      ZIFUC("\r\n┃起始位┃空┃      系统位      ┃        数据位        ┃\r\n");
          ZIFUC("\r\n\r\n 【 RC5通用编码格式:14位编码 】\r\n");

          ZIFUC("\r\n 起始位(2位):0x");
          JZ(N[0],16,1);      
          ZIFUC("    二进制:    ");
          JZ(N[0],2,2);
          
          ZIFUC("\r\n 控制位(1位):");
      if(N[1])ZIFUC("   1");
          else           ZIFUC("   0");

          ZIFUC("\r\n 系统位(5位):0x");
          JZ(N[2],16,1);      
          ZIFUC("    二进制: ");
          JZ(N[2],2,5);

          ZIFUC("\r\n 数据位(6位):0x");
          JZ(N[3],16,1);      
          ZIFUC("    二进制:");
          JZ(N[3],2,6);
}
/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:根据收集的脉冲数据进行RC5解码
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void IR_RC5()
{         
         bit  B_v,BV;
         uchar x;
         uchar n;
         uint  t;
                                                                        
         BV = 1;                                //BV=1时检测(接收端)低电平时间,BV=0时检测(接收端)高电平时间。
         x  = 0;
         t  = 0;
         N[0]=N[1]=N[2]=N[3]=0;

         for(n=0;n<14;n++)            //14位位码解码
         {
                   x++;                            //最高位丢弃(1个数据3字节);
                ((uchar *)&t)[0] = v[x++];
                ((uchar *)&t)[1] = v[x++];

                /*┈┈┈ 确认位码值 ┈┈┈*/
                if(BV){ if(t < 950){B_v=1;x+=3;  } //BV=1时,如果t<950uS,下次还是检测(接收端)低电平时间,且跳过高电平时间。
                            else       {B_v=1;BV=0;} } //BV=1时,如果t>950uS,下次检测(接收端)高电平时间
                else  { if(t < 950){B_v=0;x+=3;}
                            else       {B_v=0;BV=1;} }

                /*┈┈┈ 装载位码值 ┈┈┈*/
                if(n < 2)    { N[0] >>= 1;
                           if(B_v)N[0] |= 0x02; }
                else if(n==2)  N[1] = B_v;
                else if(n<8) { N[2] >>= 1;
                               if(B_v)N[2] |= 0x10; }
                else if(n<15){ N[3] >>= 1;
                               if(B_v)N[3] |= 0x20; }
                                                  
                /*┈┈┈ 发射位码值 ┈┈┈*/                          
                ZIFUC("   ");   
                if(B_v)ZIFUC("1");
                else   ZIFUC("0");                                               
     }
}

出0入0汤圆

发表于 2011-8-29 14:36:44 | 显示全部楼层
前排mark

出0入0汤圆

发表于 2011-8-29 15:03:58 | 显示全部楼层
这个很强大~~~

出0入0汤圆

发表于 2011-8-29 15:51:42 | 显示全部楼层
方法好,显示调试

出0入0汤圆

发表于 2011-8-29 16:14:57 | 显示全部楼层
这个很牛逼!我都没有想起来!

出0入0汤圆

发表于 2011-9-7 14:11:44 | 显示全部楼层
很好很强大,就是看不懂(脸红)
要学习的还很多很多呀(拍肩)

出0入0汤圆

发表于 2011-9-7 15:22:46 | 显示全部楼层
顶一下,不错

出0入0汤圆

发表于 2011-10-6 12:21:46 | 显示全部楼层
正好我在搞这一块!  可是我的是STC89系列的呀   表示看不懂(脸红)

出0入0汤圆

 楼主| 发表于 2011-10-6 12:34:06 | 显示全部楼层
回复【7楼】jxauzhongkewen
-----------------------------------------------------------------------

STC89系列没PCA,但利用定时器也是可以的

出0入0汤圆

发表于 2011-10-6 19:24:15 | 显示全部楼层
#include <CKA.H>是什么呀?为什么我的keil编译不了  还有AIFUC是起什么作用的 我的编译器报错了

出0入4汤圆

发表于 2011-10-6 19:58:51 | 显示全部楼层
想学习一下PCA捕获!做个记号!

出0入0汤圆

发表于 2011-10-6 20:58:47 | 显示全部楼层
mk

出0入0汤圆

发表于 2011-10-6 21:23:48 | 显示全部楼层
我也在搞这个,用的是89c52定时,但是有个问题,程序会陷在红外触发的中断里面跑不出来,而且通过串口输出的数据会把编码中0与1共同的那部分0.56ms的高电平漏掉,楼主能不能指点一下,中断程序如下:
void to() interrupt 0//解码输出 外部中断0
{
    uchar t,i;
        uint temp;
        EX0 = 0;
        while(1)//直到输出完毕
        {
            LED = ~LED;//输出指示灯
                t = IR;
                TH0 = 0;
                TL0 = 0;
                TR0 = 1;//开启定时器0,开始计时
                while(t == IR);//记录电平持续时间
                TR0 = 0;
                temp = TH0;
                temp = (temp<<8)|TL0;
                if((t == 1)&&(temp>50000))//如果高电平持续时间较长,则解码完毕
                break;
                dateSend(t);//输出高低电平状态
                dateSend(TH0);
                dateSend(TL0);//输出电平持续时间
        }
     dateSend(a);//判断
         EX0 = 1;
}
接收的结果:
(原文件名:QQ截图20111006094315.png)
每个接受代表按了一下遥控器,可以看到按了好几次遥控器后才跑到输出0xff,实在是想的头疼,望楼主指点一下,谢谢

出0入0汤圆

发表于 2011-10-6 21:47:48 | 显示全部楼层
补充说明一下:
接收数据 3位一组,如打头的00 20 D3 ,说明是低电平,持续时间为0x20d3*1.085约等于9ms,11.0592的晶振,但是问题是仔细看后面就发现输出结果只有01的持续时间,就是只有高电平持续时间,由于红外一体化接收输出与发送反相,因此就是说数据0与1中的高电平没有记录输出,而这两者都是0.56ms,因此我觉得是不是因为单片发送数据的时间要大于这段时间,因此导致不能检测出来?还有上面括号中有5个接受最后才是FF,说明我按了5次遥控器才最后输出FF跳出中断,每次解出的长度都不一样,这是为什么?新手,望高手指点一下,谢谢。

出0入0汤圆

 楼主| 发表于 2011-10-6 21:52:17 | 显示全部楼层
回复【9楼】jxauzhongkewen
-----------------------------------------------------------------------

//*******************************************************
// 实验调试助手,串口字符显示(版本:2011/08/06)
//
// 串口说明:使用定时器1,字符发送,N,8,1
//
// (      6MHz @ 1T) 28800bps
// (11.0592MHz @ 1T)115200bps
// (     12MHz @ 1T) 57600bps
// (22.1184MHz @ 1T)256000bps
//
// (      6MHz @12T)  2400bps
// (11.0592MHz @12T) 57600bps
// (     12MHz @12T)  4800bps
//
// 【供用户调用的3个函数】
// void   Uart_Init(uint8 M,uint8 T);             //串口初始化
// void   JZ(uint32 tem,uint8 num,uint8 i);         //整形数据送串口显示
// void   ZIFUC(uint8 code *p);                     //字符串发送                                                                  
//*******************************************************

#ifndef  __CKA_H__
#define  __CKA_H__

#include  <intrins.h>
#define uint8   unsigned char     
#define uint16  unsigned int
#define uint32  unsigned long

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:串口初始化
入口:(MHz,12T/1T)

举例:如使用  22.1184MHz晶振,STC 1T系列,
      那么初始化时应为:  Uart_Init(22,1),
      与PC的串口助手通讯:波特率256000bps,字符,校验位N,数据位8,停止位1
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void Uart_Init(uint8 M,uint8 T)               
{
bit    BS,XT;
uint16 MT;

MT = M*100+T;
switch(MT)
{
   //////////////////////////////////////////////【1T系列】
   case 601:                         //28800bps@6MHz
                      BS  = 1;         //倍速
                     XT  = 1;         //1T模式
                 TL1 = 0xF3; //初值
             break;
   case 1101:                         //115200bps@11.0592MHz
             BS  = 0;         //不倍速
                         XT         = 1;         //1T模式
                 TL1 = 0xFD; //初值
             break;
   case 1201:                         //57600bps@12MHz
                     BS  = 1;         //倍速
                         XT         = 1;         //1T模式
                 TL1 = 0xF3; //初值       
             break;
   case 2201:                         //256000bps@22.1184MHz
                     BS  = 1;         //倍速
                         XT         = 1;         //1T模式
                 TL1 = 0xFB; //初值       
             break;       
   //////////////////////////////////////////////【12T系列】
   case 612:                         //2400bps@6MHz
             BS  = 1;         //倍速
                     XT  = 0;         //12T模式
                 TL1 = 0xF3; //初值
             break;
   case 1112:                         //57600bps@11.0592MHz
             BS  = 1;         //倍速
                         XT  = 0;         //12T模式
                 TL1 = 0xFF; //初值
             break;
   case 1212:                         //4800bps@12MHz
             BS  = 1;         //倍速
                         XT         = 0;         //12T模式
                 TL1 = 0xF3; //初值       
             break;                                                                                    
  }

if(BS)PCON |= 0x80;            //使能波特率倍速位SMOD
else  PCON &= 0x7f;            //波特率不倍速

      SCON  = 0x50;                //8位数据,可变波特率

if(XT)AUXR |= 0x40;            //定时器1时钟为Fosc,即1T
else  AUXR &= 0xbf;            //定时器1时钟为Fosc/12,即12T

      AUXR &= 0xfe;                //串口1选择定时器1为波特率发生器
      TMOD &= 0x0f;                //清除定时器1模式位
      TMOD |= 0x20;                //设定定时器1为8位自动重装方式
      TH1   = TL1;                //重装值
      ET1   = 0;                //禁止定时器1中断
      TR1   = 1;                //启动定时器1
}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:HEX转ASCII
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
uint8 HEX2ASCII(uint8 dat)
{
        dat &= 0x0f;
        if(dat <= 9) return(dat+'0');        //数字0~9  ('0' 0x30)
        return (dat-10+'A');                        //字母A~F  ('A' 0x41,'a' 0x61)
}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:串口发送
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void TxS(uint8 i)
{
   SBUF=i;
   while(!TI);
   TI=0;
}
/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:字符串发送
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void ZIFUC(uint8 code *p)                    //发送一串字符串
{
    for(; *p != 0; p++) TxS(*p);         //遇到停止符0结束
}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:整形数据送串口显示
入口:tem = 整形数据(送入1~4字节整形数据)
          num = 以什么进制显示,2:二进制,10:十进制,16:十六进制
          i   = 显示低几位          (以二进制显示时)
                  = 显示个位算起几位数  (以十进制显示时)
                  = 显示几字节          (以十六进制显示时)
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void JZ(uint32 tem,uint8 num,uint8 i)
{
   uint8 j,z[10];
   bit   BT=0;

   switch(num)
   {
       case  2: tem = _lror_(tem,i-1); //以二进制显示
                    while(i--)
                    {
                      if(tem & 1)ZIFUC("1");
                                  else                  ZIFUC("0");
                      tem = _lrol_(tem,1);
                    }
                                /*        【 另一种算法 】
                                tem <<= (32-i);
                                while(i--)
                                {
                                  if(tem & 0x80000000)ZIFUC("1");
                                  else                           ZIFUC("0");
                                  tem <<= 1;
                                }  */
                                break;

           case 10: for(j=0;j<i;j++)//以十进制显示
                    {
                      z[j] = tem%10;                                        //nv[0]=个位,nv[1]=十位,······
                      tem /= 10;
                    }
               
                        while(i--)
                    {
                          if(z || (i==0))BT=1;                //数据有效标志
                          if(BT)TxS(HEX2ASCII(z));             //数据有效前的“0”不显示,
                          else  ZIFUC(" ");                                    //用空格替换。
                    }
                                break;

           case 16: for(j=4-i;j<4;j++)//十六进制显示
                {
                  z[j] = ((uint8 *)&tem)[j];
                                  TxS(HEX2ASCII(z[j]>>4));                        //发送高4位
                  TxS(HEX2ASCII(z[j]));                                //发送低4位
                }
                                break;
   }
}


#endif





////////////////////////////////////////////////////////////////////////////////////////////

                           头文件 CKA.H 应用示例

////////////////////////////////////////////////////////////////////////////////////////////


#define uint8   unsigned char      
#define uint16  unsigned int  
#define uint32  unsigned long  
#include "STC89C52RC.H"
#include "intrins.h"
#include "CKA.H"


/********************************************
函数:10ms × n 延时程序   STC 12T@12MHz
*********************************************/
void YS10ms(uint8 n)
{
  uint8 i,j,k;
  for(i=n;i!=0;i--)
  for(j=30;j!=0;j--)
  for(k=165;k!=0;k--);
}


void main(void)
{
  uint32 a = 1234567890;
  uint32 b = 0xABCE1234;       
  uint8         c = 0x33;

  Uart_Init(11,12);                   //串口初始化(11.0592MHz晶振,STC 12T系列),57600bps,字符,校验位N,数据位8,停止位1
  YS10ms(60);

  ZIFUC("\r\n****** 串口显示实验 ******\r\n\r\n");

  ZIFUC(" a = ");
  JZ(a,10,10);                  //以十进制显示a
  ZIFUC("     a的低2位 = ");
  JZ(a,10,2);                  //以十进制显示a的低2位

  ZIFUC("\r\n b = 0x");
  JZ(b,16,4);                  //以十六进制显示b
  ZIFUC("     b低3字节 = ");             
  JZ(b,16,3);                  //以十六进制显示b的低3字节
  ZIFUC("\r\n b = ");             
  JZ(b,2,32);                  //以二进制显示b
  ZIFUC("(二进制)\r\n c = ");             

  JZ(c,2,8);                  //以二进制显示c
  ZIFUC("(二进制)\r\n");   

  ZIFUC("\r\n\r\n****** c自加1显示 ******\r\n\r\n");
  while(1)
  {  
          c++;
          ZIFUC("十六进制:c = 0x");
          JZ(c,16,1);          //以十六进制显示c
          YS10ms(200);
          ZIFUC("\r\n");
  }
}


(原文件名:TP1.jpg)

出0入0汤圆

发表于 2011-10-6 22:55:25 | 显示全部楼层
马如龙

出0入0汤圆

发表于 2011-10-6 23:10:26 | 显示全部楼层
mark
!

出0入0汤圆

发表于 2011-10-7 07:21:36 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-8 13:36:38 | 显示全部楼层
NB东西   记号1

出0入0汤圆

发表于 2011-10-8 16:34:41 | 显示全部楼层
为什么我的审核还没有通过啊~

出0入0汤圆

发表于 2011-10-20 19:03:19 | 显示全部楼层
很牛!楼主强人!

出0入0汤圆

 楼主| 发表于 2011-10-20 23:59:14 | 显示全部楼层
回复【12楼】zspzwal
-----------------------------------------------------------------------

回复【13楼】zspzwal
-----------------------------------------------------------------------
【1】
t = IR;
while(t == IR);//记录电平持续时间

这个语句存在隐患:
当t=1时,你恰好松开遥控停止发射,这时IR保持=1,岂不是一直t == IR,死循环就产生了

  




建议你
先捕捉一定数量(由你定义)连续高低电平时间,
再在主函数里统一发送捕捉到的数据

出0入0汤圆

发表于 2011-10-21 11:50:22 | 显示全部楼层
回复【21楼】BXAK  
-----------------------------------------------------------------------

嗯,确实考虑不周啊,多谢了,现在改过了

出0入0汤圆

发表于 2011-12-22 08:46:14 | 显示全部楼层
请问楼主,那个程序可以用C52制作。

出0入0汤圆

发表于 2011-12-24 00:17:23 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-24 00:32:08 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-4 21:33:13 | 显示全部楼层
正好在玩红外相关,谢谢楼主。

出0入0汤圆

发表于 2012-2-4 21:41:54 | 显示全部楼层
mark!

出0入134汤圆

发表于 2012-2-15 22:29:26 | 显示全部楼层
好东西

出0入0汤圆

发表于 2012-2-19 00:29:41 | 显示全部楼层
楼主强大。


学习pca

出0入0汤圆

发表于 2012-2-19 22:22:18 | 显示全部楼层
没看见上位机的代码~~~~~~~~~~~~

出0入0汤圆

 楼主| 发表于 2012-2-20 00:22:43 | 显示全部楼层
回复 30楼

没必要编写专门的上位机,网上的各种串口调试工具都可以,比如:STC—ISP烧写软件都自带串口助手、电脑XP系统也有自带串口调试工具

出0入0汤圆

发表于 2012-2-20 00:50:36 | 显示全部楼层
很好的思路,学习了

出0入0汤圆

发表于 2012-2-20 08:53:00 | 显示全部楼层
很好很强大

出0入0汤圆

发表于 2012-2-20 23:12:53 | 显示全部楼层
牛叉

出0入0汤圆

发表于 2012-2-22 10:19:50 | 显示全部楼层
楼主好牛

出0入0汤圆

发表于 2012-4-11 18:49:59 | 显示全部楼层
   牛×啊

出0入0汤圆

发表于 2012-9-27 14:02:38 | 显示全部楼层
我用STC12C5A60S2的芯片跑了这个程序,程序跑成功了,用的是该芯片的PCA模块1,头文件改成了PCA1.主函数和头文件改了下,CKA文件不变!我在研究楼主这个程序,想红外发射出来,还想压缩数据,保存到eeprom中去!


/***************************************************************
    作品:捕获红外发射脉冲高、低电平时间,送串口显示
  单片机:STC12C5410
    晶振:12M
编译环境:Keil uVision4 V9.00
***************************************************************/
//  说明:1、适用于:1T系列含有PCA捕获的STC单片机
//        2、捕获引脚PCA2(也就是P2.0),3字节存放一个电平时间数据。
//        3、串口显示脉冲高低电平时间数据(串口:字符 57600bps 校验位N 数据位8 停止位1),
//        4、含NEC、RC5解码,如需其它解码请自己加入。
//
//  NEC码:(芯片有 市场上用量最大的HT6121/6122及其兼容的IC芯片等)
//  RC5码:(芯片有 SAA3006、SAA3010、SAA3027、PCA8521、PT2210 等)

#include <STC12C5A60S2.h>
#include <CKA.H>
#define uchar unsigned char   
#define uint  unsigned int
#define ulong unsigned long


sbit IR = P1^4;                        //捕获引脚PCA2           即红外接收端口
sbit P21=P2^1;

uchar xdata v[486];               
uchar N[4];
uint  t;
ulong nn;

bit   VT;                                //捕获完成标志
bit   B_Z;                               //丢弃第一次捕获标志

void  ChuanKou();                        //串口发送主程序
void  IR_RC5();                          //RC5解码



/********************************************
函数:10ms × n 延时程序   STC 1T@12MHz
*********************************************/
void YS10ms(uchar n)
{
  uchar i,j,k;
  for(i=n;i!=0;i--)
    for(j=198;j!=0;j--)
        for(k=150;k!=0;k--);
}




/********************************************
函数:接收初始化
*********************************************/
void JS_Init(void)
{
  uint i;
  
  B_Z = 1;
  t   = 0;
  for(i=0;i<486;i++)
  {
      v[t]=0;                           //存储区清0
  }                       
  EPCA_LVD = 1;                         //PCA模块中断和低压检测中断允许位
  CCAPM1|= 0x31;                        //PCA模块1:16位捕获模式,由CCP2的跳变触发。ECCF2=1,使能CCF2中断。
  CMOD = 0x01;                          //ECF=1(CMOD.0=1)使能CF(CCON.7)位产生中断
  EA = 1;
  P21 = 0;                              //开始接收,指示灯打开
}
/********************************************
函数:主程序
*********************************************/
void main()
{

  Uart_Init(12,1);
  JS_Init();
  YS10ms(10);

  ZIFUC("\r\n\r\n\r\n                ****** 开始接收,请按遥控 ******\r\n");

  while(1)
  {  
        if(VT)
        {
          VT  = 0;
          P21 = 1;                        //接收完成,指示灯关闭
          ChuanKou();                     //串口显示

          YS10ms(200);                    //1秒后重新开始
      
          JS_Init();

          ZIFUC("\r\n\r\n\r\n                ****** 可以重新接收,请按遥控 ******\r\n");
        }  
  }
}

/***************************************************************
函数:PCA中断捕获程序(电位跳变捕获模式)
***************************************************************/
void PCA_isr(void) interrupt 6 using 1
{
     if(CF)                               //是否是PCA定时器溢出
     {
            CF = 0;                        //必须软件清0 (PCA 定时器标志)
            v[t]++;                        //PCA定时器溢出计数,保存数据最高字节
            if(v[t]>1)                     //设置允许溢出次数,>131ms 终止捕获
            {
                           CR = 0;   
               CF = 0;
               CCAPM1 = 0;
               CCF1=0;
               VT=1;                       //捕获完成标志
               v[t]=0;
               return;

            }
      }
     if(CCF1)                               //是否是电位跳变
     {
               CCF1 = 0;                   //必须软件清0 (PCA 模块1标志)
               CL   = 0;                   //先赋值低位
               CH   = 0;            
               if(B_Z)
                           {
                               CR =1;                  //启动PCA定时器
                   B_Z=0;
                   return;                          
                           }                           //丢弃第一次捕获数据
               t++;
               v[t]=CCAP1H;                //保存数据高字节
               t++;
               v[t]=CCAP1L;                //保存数据低字节
               t++;               
     }

     if(t >= 486)                          //捕获162个数据(1个电平时间3字节存放)
         {
                 CCAPM1 = 0;
                 CCF1=0;
                 CR = 0;
                 CF = 0;
                 VT = 1;                           //捕获完成标志
         }
}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:串口发送主程序
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void ChuanKou()
{
          uchar i;
          uint j,T;
         
          ZIFUC("\r\n\r\n                ****** 接收完成 ******");
          ZIFUC("\r\n\r\n ( 以下是遥控器发射脉冲的波形数据 )");
          ZIFUC("\r\n\r\n  序号  高电平时间(us)  低电平时间(us)\r\n\r\n");

          i=0;

          for(j=0;j<486;)
          {
                          ((uchar *)&nn)[0] = 0;
                          ((uchar *)&nn)[1] = v[j++];
                          ((uchar *)&nn)[2] = v[j++];
                          ((uchar *)&nn)[3] = v[j++];

                          ZIFUC("  ");
                          JZ(i,10,2);                             //序号
                          ZIFUC("   ");                                    
                          JZ(nn,10,8);                            //高电平时间

                          ((uchar *)&nn)[0] = 0;
                          ((uchar *)&nn)[1] = v[j++];
                          ((uchar *)&nn)[2] = v[j++];
                          ((uchar *)&nn)[3] = v[j++];

                          ZIFUC("        ");                                                               
                          JZ(nn,10,8);                             //低电平时间

                          if( (i%8)==0 )

                                                 ZIFUC("\r\n\r\n");

                          else
                                                  
                                                     ZIFUC("\r\n");

                          i++;
          }
                           
        ///////////////// NEC解码 ////////////////         
          j=9;                                                    //引导码丢弃
          for(i=0;i<32;i++)
          {
                          j++;
                          ((uchar *)&T)[0] = v[j++];
                          ((uchar *)&T)[1] = v[j++];
                          j += 3;                        
                          N[i/8] >>= 1;
                          if((T<1900) && (T>1000))
                                                  {
                                                     N[i/8] |= 0x80;
                                                  }          
          }

          if(N[2] == ~N[3])         //校验NEC操作码。错误则尝试RC5解码
          {                     
                          ZIFUC("\r\n 【 NEC通用编码格式:引导码 + 32位编码(16位用户码+操作码正反码) 】\r\n");
                          ZIFUC("\r\n 用户码(高8位):0x");
                          JZ(N[0],16,1);      
                          ZIFUC("\r\n 用户码(低8位):0x");
                          JZ(N[1],16,1);
                                 
                          ZIFUC("\r\n\r\n 操作码正码 :0x");
                          JZ(N[2],16,1);     
                          ZIFUC("\r\n");

                          if(N[0] == ~N[1])
                          {
                               ZIFUC("\r\n\r\n 经对比,16位用户码是正反码,用户码正码:0x");
                               JZ(N[0],16,1);
                          }

                          return;                                                
          }           
                    
        ///////////////// 初略分析是否是RC5编码 ////////////////
         j=0;
         for(i=0;i<20;i++)                                         
         {
               j++;                                                //最高位丢弃(1个数据3字节);
               ((uchar *)&T)[0] = v[j++];
               ((uchar *)&T)[1] = v[j++];

               if(T<600 || T>1800)                                 //RC5码前20个脉冲数据600<nn<1800
               {
                        ZIFUC("\r\n 【 解码失败,再试一试或者分析波形数据 】");
                        return;
               }
         }
        ///////////////// 将波形数据绘成图像 ////////////////
        ZIFUC("\r\n 【 RC5编码发射波形 】    发射顺序:(低位)<--(高位)\r\n");
        ZIFUC("\r\n___");
         
        j=0;
        for(i=0;i<26;i++)
        {
               j++;                                                       //最高位丢弃(1个数据3字节);
               ((uchar *)&T)[0] = v[j++];
               ((uchar *)&T)[1] = v[j++];
               if(T>2000)
                           {
                               break;
                           }
               if(i%2 != 1)                                                 //如果i是偶数
               {
                      if(T<1000)

                                               ZIFUC("▉");

                      else      
                                          
                                               ZIFUC("▉▉");
               }
               else
               {
                      if(T<950)
                                          
                                                ZIFUC("__");

                       else      
                                          
                                                ZIFUC("____");
               }
       }
      ZIFUC("_____________");        
      ZIFUC("\r\n┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊  ┊\r\n");
      IR_RC5();                                                                          //RC5解码
      ZIFUC("\r\n┃起始位┃空┃      系统位      ┃        数据位        ┃\r\n");
      ZIFUC("\r\n\r\n 【 RC5通用编码格式:14位编码 】\r\n");
      ZIFUC("\r\n 起始位(2位):0x");
      JZ(N[0],16,1);      
      ZIFUC("    二进制:    ");
      JZ(N[0],2,2);         
      ZIFUC("\r\n 控制位(1位):");
      if(N[1])
          
              ZIFUC("   1");

      else         
          
              ZIFUC("   0");

      ZIFUC("\r\n 系统位(5位):0x");
      JZ(N[2],16,1);      
      ZIFUC("    二进制: ");
      JZ(N[2],2,5);
      ZIFUC("\r\n 数据位(6位):0x");
      JZ(N[3],16,1);      
      ZIFUC("    二进制:");
      JZ(N[3],2,6);

}
/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:根据收集的脉冲数据进行RC5解码
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void IR_RC5()
{         
         bit  B_v,BV;
         uchar x;
         uchar n;
         uint  t;
                                                                        
         BV = 1;                                //BV=1时检测(接收端)低电平时间,BV=0时检测(接收端)高电平时间。
         x  = 0;
         t  = 0;
         N[0]=N[1]=N[2]=N[3]=0;

         for(n=0;n<14;n++)                     //14位位码解码
         {
                x++;                           //最高位丢弃(1个数据3字节);
                ((uchar *)&t)[0] = v[x++];
                ((uchar *)&t)[1] = v[x++];

                /*┈┈┈ 确认位码值 ┈┈┈*/
                if(BV)                                                       
                                {
                                    if(t < 950)                                         //BV=1时,如果t<950uS,下次还是检测(接收端)低电平时间,且跳过高电平时间。
                                    {
                                       B_v=1;
                                           x+=3;
                    }
                    else                                                //BV=1时,如果t>950uS,下次检测(接收端)高电平时间
                                    {
                                       B_v=1;
                                           BV=0;
                                    }
                                }
                else
                                {
                                       if(t < 950)
                                           {
                                              B_v=0;
                                                  x+=3;
                                           }
                       else      
                                           {
                                               B_v=0;
                                                   BV=1;
                                           }
                            }

                /*┈┈┈ 装载位码值 ┈┈┈*/
                if(n < 2)   
                                {
                                       N[0] >>= 1;
                       if(B_v)N[0] |= 0x02;
                            }
                else if        (n==2)

                                        N[1] = B_v;       
                                                         
                else if(n<8)
                                {
                                        N[2] >>= 1;
                        if(B_v)N[2] |= 0x10;
                                }
                else if(n<15)
                                {
                                        N[3] >>= 1;
                        if(B_v)N[3] |= 0x20;
                            }
                                                   
                /*┈┈┈ 发射位码值 ┈┈┈*/                           
                ZIFUC("   ");   
                if(B_v)
                                 
                                   ZIFUC("1");

                else   
                               
                                   ZIFUC("0");                                                
     }
}



//--------------------------------------------------------------------------------
//新一代 1T 8051系列 单片机内核特殊功能寄存器 C51 Core SFRs
//                                          7     6      5       4     3    2    1     0   Reset Value
sfr ACC  = 0xE0; //Accumulator                                                              0000,0000
sfr B    = 0xF0; //B Register                                                               0000,0000
sfr PSW  = 0xD0; //Program Status Word      CY    AC    F0    RS1   RS0    OV    F1    P    0000,0000
//-----------------------------------
sbit CY  = PSW^7;
sbit AC  = PSW^6;
sbit F0  = PSW^5;
sbit RS1 = PSW^4;
sbit RS0 = PSW^3;
sbit OV  = PSW^2;
sbit P   = PSW^0;
//-----------------------------------
sfr SP   = 0x81; //Stack Pointer                                                            0000,0111
sfr DPL  = 0x82; //Data Pointer Low Byte                                                    0000,0000
sfr DPH  = 0x83; //Data Pointer High Byte                                                   0000,0000
//--------------------------------------------------------------------------------
//新一代 1T 8051系列 单片机系统管理特殊功能寄存器
//                                          7     6      5    4     3      2    1     0     Reset Value
sfr PCON   = 0x87; //Power Control        SMOD  SMOD0  LVDF  POF   GF1    GF0   PD   IDL    0001,0000
//                                        7     6       5      4     3      2      1      0   Reset Value
sfr AUXR  = 0x8E; //Auxiliary Register  T0x12 T1x12 UART_M0x6 BRTR S2SMOD BRTx12 EXTRAM S1BRS  0000,0000
//-----------------------------------
sfr AUXR1 = 0xA2; //Auxiliary Register 1  -  PCA_P4  SPI_P4  S2_P4  GF2    ADRJ   -    DPS  0000,0000
/*
PCA_P4:
    0, 缺省PCA 在P1 口
    1,PCA/PWM 从P1 口切换到P4 口: ECI 从P1.2 切换到P4.1 口,
                                   PCA0/PWM0 从P1.3 切换到P4.2 口
                                   PCA1/PWM1 从P1.4 切换到P4.3 口
SPI_P4:
    0, 缺省SPI 在P1 口
    1,SPI 从P1 口切换到P4 口: SPICLK 从P1.7 切换到P4.3 口
                               MISO 从P1.6 切换到P4.2 口
                               MOSI 从P1.5 切换到P4.1 口
                               SS 从P1.4 切换到P4.0 口
S2_P4:
    0, 缺省UART2 在P1 口
    1,UART2 从P1 口切换到P4 口: TxD2 从P1.3 切换到P4.3 口
                                 RxD2 从P1.2 切换到P4.2 口
GF2: 通用标志位

ADRJ:
    0, 10 位A/D 转换结果的高8 位放在ADC_RES 寄存器, 低2 位放在ADC_RESL 寄存器
    1,10 位A/D 转换结果的最高2 位放在ADC_RES 寄存器的低2 位, 低8 位放在ADC_RESL 寄存器

DPS: 0, 使用缺省数据指针DPTR0
     1,使用另一个数据指针DPTR1
*/
//-----------------------------------
sfr WAKE_CLKO = 0x8F; //附加的 SFR WAK1_CLKO
/*
      7            6          5          4          3       2       1      0         Reset Value
   PCAWAKEUP  RXD_PIN_IE  T1_PIN_IE  T0_PIN_IE  LVD_WAKE    _    T1CLKO  T0CLKO      0000,0000B

b7 - PCAWAKEUP : PCA 中断可唤醒 powerdown。
b6 - RXD_PIN_IE : 当 P3.0(RXD) 下降沿置位 RI 时可唤醒 powerdown(必须打开相应中断)。
b5 - T1_PIN_IE : 当 T1 脚下降沿置位 T1 中断标志时可唤醒 powerdown(必须打开相应中断)。
b4 - T0_PIN_IE : 当 T0 脚下降沿置位 T0 中断标志时可唤醒 powerdown(必须打开相应中断)。
b3 - LVD_WAKE : 当 CMPIN 脚低电平置位 LVD 中断标志时可唤醒 powerdown(必须打开相应中断)。
b2 -
b1 - T1CLKO : 允许 T1CKO(P3.5) 脚输出 T1 溢出脉冲,Fck1 = 1/2 T1 溢出率
b0 - T0CLKO : 允许 T0CKO(P3.4) 脚输出 T0 溢出脉冲,Fck0 = 1/2 T1 溢出率
*/
//-----------------------------------
sfr CLK_DIV = 0x97; //Clock Divder          -     -      -       -     -  CLKS2 CLKS1 CLKS0 xxxx,x000
//-----------------------------------
sfr BUS_SPEED = 0xA1; //Stretch register      -     -    ALES1   ALES0   -   RWS2  RWS1  RWS0 xx10,x011
/*
ALES1 and ALES0:
00 : The P0 address setup time and hold time to ALE negative edge is one clock cycle
01 : The P0 address setup time and hold time to ALE negative edge is two clock cycles.
10 : The P0 address setup time and hold time to ALE negative edge is three clock cycles. (default)
11 : The P0 address setup time and hold time to ALE negative edge is four clock cycles.

RWS2,RWS1,RWS0:
  000 : The MOVX read/write pulse is 1 clock cycle.
  001 : The MOVX read/write pulse is 2 clock cycles.
  010 : The MOVX read/write pulse is 3 clock cycles.
  011 : The MOVX read/write pulse is 4 clock cycles. (default)
  100 : The MOVX read/write pulse is 5 clock cycles.
  101 : The MOVX read/write pulse is 6 clock cycles.
  110 : The MOVX read/write pulse is 7 clock cycles.
  111 : The MOVX read/write pulse is 8 clock cycles.
*/
//--------------------------------------------------------------------------------
//新一代 1T 8051系列 单片机中断特殊功能寄存器
//有的中断控制、中断标志位散布在其它特殊功能寄存器中,这些位在位地址中定义
//其中有的位无位寻址能力,请参阅 新一代 1T 8051系列 单片机中文指南
//                                           7     6     5    4     3    2    1    0   Reset Value
sfr IE      = 0xA8;  //中断控制寄存器        EA  ELVD  EADC   ES   ET1  EX1  ET0  EX0  0x00,0000
//-----------------------
sbit EA       = IE^7;
sbit EPCA_LVD    = IE^6; //低压监测中断允许位
sbit EADC     = IE^5; //ADC 中断允许位
sbit ES       = IE^4;
sbit ET1      = IE^3;
sbit EX1      = IE^2;
sbit ET0      = IE^1;
sbit EX0      = IE^0;
//-----------------------
sfr IE2       = 0xAF;  //Auxiliary Interrupt   -     -     -    -     -    -  ESPI  ES2  0000,0000B
//-----------------------
//                                          7     6     5    4    3    2    1    0    Reset Value
sfr IP      = 0xB8; //中断优先级低位      PPCA  PLVD  PADC  PS   PT1  PX1  PT0  PX0   0000,0000
//--------
sbit PPCA     = IP^7;  //PCA 模块中断优先级
sbit PLVD     = IP^6;  //低压监测中断优先级
sbit PADC     = IP^5;  //ADC 中断优先级
sbit PS       = IP^4;
sbit PT1      = IP^3;
sbit PX1      = IP^2;
sbit PT0      = IP^1;
sbit PX0      = IP^0;
//-----------------------
//                                         7      6      5     4     3     2     1     0    Reset Value
sfr IPH   = 0xB7; //中断优先级高位       PPCAH  PLVDH  PADCH  PSH  PT1H  PX1H  PT0H  PX0H   0000,0000
sfr IP2   = 0xB5; //                       -      -      -     -     -     -   PSPI   PS2   xxxx,xx00
sfr IPH2  = 0xB6; //                       -      -      -     -     -     -   PSPIH  PS2H  xxxx,xx00
//-----------------------
//新一代 1T 8051系列 单片机I/O 口特殊功能寄存器
//                                      7     6     5     4     3     2     1     0         Reset Value
sfr P0   = 0x80; //8 bitPort0          P0.7  P0.6  P0.5  P0.4  P0.3  P0.2  P0.1  P0.0       1111,1111
sfr P0M0 = 0x94; //                                                                         0000,0000
sfr P0M1 = 0x93; //                                                                         0000,0000
sfr P1   = 0x90; //8 bitPort1          P1.7  P1.6  P1.5  P1.4  P1.3  P1.2  P1.1  P1.0       1111,1111
sfr P1M0 = 0x92; //                                                                         0000,0000
sfr P1M1 = 0x91; //                                                                         0000,0000
sfr P1ASF = 0x9D; //P1 analog special function
sfr P2   = 0xA0; //8 bitPort2          P2.7  P2.6  P2.5  P2.4  P2.3  P2.2  P2.1  P2.0       1111,1111
sfr P2M0 = 0x96; //                                                                         0000,0000
sfr P2M1 = 0x95; //                                                                         0000,0000
sfr P3   = 0xB0; //8 bitPort3          P3.7  P3.6  P3.5  P3.4  P3.3  P3.2  P3.1  P3.0       1111,1111
sfr P3M0 = 0xB2; //                                                                         0000,0000
sfr P3M1 = 0xB1; //                                                                         0000,0000
sfr P4   = 0xC0; //8 bitPort4          P4.7  P4.6  P4.5  P4.4  P4.3  P4.2  P4.1  P4.0       1111,1111
sfr P4M0 = 0xB4; //                                                                         0000,0000
sfr P4M1 = 0xB3; //                                                                         0000,0000
//                                      7      6         5         4      3     2     1     0     Reset Value
sfr P4SW = 0xBB; //Port-4 switch            -   LVD_P4.6  ALE_P4.5  NA_P4.4   -     -     -     -            x000,xxxx

sfr P5   = 0xC8; //8 bitPort5           -     -       -      -    P5.3  P5.2  P5.1  P5.0    xxxx,1111
sfr P5M0 = 0xCA; //                                                                         0000,0000
sfr P5M1 = 0xC9; //                                                                         0000,0000
//--------------------------------------------------------------------------------
//新一代 1T 8051系列 单片机定时器特殊功能寄存器
//                                          7     6     5     4     3     2     1     0     Reset Value
sfr TCON = 0x88; //T0/T1 Control           TF1   TR1   TF0   TR0   IE1   IT1   IE0   IT0    0000,0000
//-----------------------------------
sbit TF1 = TCON^7;
sbit TR1 = TCON^6;
sbit TF0 = TCON^5;
sbit TR0 = TCON^4;
sbit IE1 = TCON^3;
sbit IT1 = TCON^2;
sbit IE0 = TCON^1;
sbit IT0 = TCON^0;
//-----------------------------------
sfr TMOD = 0x89; //T0/T1 Modes             GATE1 C/T1  M1_1  M1_0  GATE0 C/T0  M0_1  M0_0   0000,0000
sfr TL0  = 0x8A; //T0 Low Byte                                                              0000,0000
sfr TH0  = 0x8C; //T0 High Byte                                                             0000,0000
sfr TL1  = 0x8B; //T1 Low Byte                                                              0000,0000
sfr TH1  = 0x8D; //T1 High Byte                                                             0000,0000
//--------------------------------------------------------------------------------
//新一代 1T 8051系列 单片机串行口特殊功能寄存器
//                                          7     6     5     4     3     2     1     0     Reset Value
sfr SCON = 0x98; //Serial Control         SM0/FE SM1   SM2   REN   TB8   RB8    TI    RI    0000,0000
//-----------------------------------
sbit SM0 = SCON^7;  //SM0/FE
sbit SM1 = SCON^6;
sbit SM2 = SCON^5;
sbit REN = SCON^4;
sbit TB8 = SCON^3;
sbit RB8 = SCON^2;
sbit TI  = SCON^1;
sbit RI  = SCON^0;
//-----------------------------------
sfr SBUF = 0x99; //Serial Data Buffer                                                     xxxx,xxxx
sfr SADEN = 0xB9; //Slave Address Mask                                                    0000,0000
sfr SADDR = 0xA9; //Slave Address                                                         0000,0000
//-----------------------------------
//                                7      6      5      4      3      2     1     0        Reset Value
sfr S2CON = 0x9A; //S2 Control  S2SM0  S2SM1  S2SM2  S2REN  S2TB8  S2RB8  S2TI  S2RI      00000000B
sfr S2BUF = 0x9B; //S2 Serial Buffer                                                      xxxx,xxxx
sfr BRT = 0x9C; //S2 Baud-Rate Timer                                                    0000,0000
//--------------------------------------------------------------------------------
//新一代 1T 8051系列 单片机看门狗定时器特殊功能寄存器
sfr WDT_CONTR = 0xC1; //Watch-Dog-Timer Control register
//                                      7     6     5      4       3      2   1   0     Reset Value
//                                  WDT_FLAG  -  EN_WDT CLR_WDT IDLE_WDT PS2 PS1 PS0    xx00,0000
//-----------------------

//--------------------------------------------------------------------------------
//新一代 1T 8051系列 单片机PCA/PWM 特殊功能寄存器
//                                         7     6     5     4     3     2     1     0     Reset Value
sfr CCON   = 0xD8;   //PCA 控制寄存器。    CF    CR    -     -     -     -    CCF1  CCF0   00xx,xx00
//-----------------------
sbit CF     = CCON^7; //PCA计数器溢出标志,由硬件或软件置位,必须由软件清0。
sbit CR     = CCON^6; //1:允许 PCA 计数器计数, 必须由软件清0。
//-
//-
sbit CCF1   = CCON^1; //PCA 模块1 中断标志, 由硬件置位, 必须由软件清0。
sbit CCF0   = CCON^0; //PCA 模块0 中断标志, 由硬件置位, 必须由软件清0。
//-----------------------
sfr CMOD  = 0xD9; //PCA 工作模式寄存器。   CIDL   -     -     -   CPS2   CPS1  CPS0  ECF   0xxx,x000
/*
CIDL: idle 状态时 PCA 计数器是否继续计数, 0: 继续计数, 1: 停止计数。

CPS2: PCA 计数器脉冲源选择位 2。
CPS1: PCA 计数器脉冲源选择位 1。
CPS0: PCA 计数器脉冲源选择位 0。
   CPS2   CPS1   CPS0
    0      0      0    系统时钟频率 fosc/12。
    0      0      1    系统时钟频率 fosc/2。
    0      1      0    Timer0 溢出。
    0      1      1    由 ECI/P3.4 脚输入的外部时钟,最大 fosc/2。
    1      0      0    系统时钟频率,  Fosc/1
    1      0      1    系统时钟频率/4,Fosc/4
    1      1      0    系统时钟频率/6,Fosc/6
    1      1      1    系统时钟频率/8,Fosc/8

ECF: PCA计数器溢出中断允许位, 1--允许 CF(CCON.7) 产生中断。
*/
//-----------------------
sfr CL     = 0xE9; //PCA 计数器低位                                                        0000,0000
sfr CH     = 0xF9; //PCA 计数器高位                                                        0000,0000
//-----------------------
//                                         7     6      5      4     3     2     1     0     Reset Value
sfr CCAPM0 = 0xDA; //PCA 模块0 PWM 寄存器  -   ECOM0  CAPP0  CAPN0  MAT0  TOG0  PWM0  ECCF0   x000,0000
sfr CCAPM1 = 0xDB; //PCA 模块1 PWM 寄存器  -   ECOM1  CAPP1  CAPN1  MAT1  TOG1  PWM1  ECCF1   x000,0000

//ECOMn = 1:允许比较功能。
//CAPPn = 1:允许上升沿触发捕捉功能。
//CAPNn = 1:允许下降沿触发捕捉功能。
//MATn  = 1:当匹配情况发生时, 允许 CCON 中的 CCFn 置位。
//TOGn  = 1:当匹配情况发生时, CEXn 将翻转。
//PWMn  = 1:将 CEXn 设置为 PWM 输出。
//ECCFn = 1:允许 CCON 中的 CCFn 触发中断。

//ECOMn  CAPPn  CAPNn  MATn  TOGn  PWMn  ECCFn
//  0      0      0     0     0     0     0   0x00   未启用任何功能。
//  x      1      0     0     0     0     x   0x21   16位CEXn上升沿触发捕捉功能。
//  x      0      1     0     0     0     x   0x11   16位CEXn下降沿触发捕捉功能。
//  x      1      1     0     0     0     x   0x31   16位CEXn边沿(上、下沿)触发捕捉功能。
//  1      0      0     1     0     0     x   0x49   16位软件定时器。
//  1      0      0     1     1     0     x   0x4d   16位高速脉冲输出。
//  1      0      0     0     0     1     0   0x42   8位 PWM。

//ECOMn  CAPPn  CAPNn  MATn  TOGn  PWMn  ECCFn
//  0      0      0     0     0     0     0   0x00   无此操作
//  1      0      0     0     0     1     0   0x42   普通8位PWM, 无中断
//  1      1      0     0     0     1     1   0x63   PWM输出由低变高可产生中断
//  1      0      1     0     0     1     1   0x53   PWM输出由高变低可产生中断
//  1      1      1     0     0     1     1   0x73   PWM输出由低变高或由高变低都可产生中断

//-----------------------
sfr CCAP0L = 0xEA; //PCA 模块 0 的捕捉/比较寄存器低 8 位。                                    0000,0000
sfr CCAP0H = 0xFA; //PCA 模块 0 的捕捉/比较寄存器高 8 位。                                    0000,0000
sfr CCAP1L = 0xEB; //PCA 模块 1 的捕捉/比较寄存器低 8 位。                                    0000,0000
sfr CCAP1H = 0xFB; //PCA 模块 1 的捕捉/比较寄存器高 8 位。                                    0000,0000
//-----------------------
//                                                       7   6   5   4   3   2    1     0    Reset Value
sfr PCA_PWM0 = 0xF2; //PCA 模块0 PWM 寄存器。            -   -   -   -   -   -  EPC0H EPC0L   xxxx,xx00
sfr PCA_PWM1 = 0xF3; //PCA 模块1 PWM 寄存器。            -   -   -   -   -   -  EPC1H EPC1L   xxxx,xx00
//PCA_PWMn:    7      6      5      4      3      2      1      0
//             -      -      -      -      -      -    EPCnH  EPCnL
//B7-B2: 保留
//B1(EPCnH): 在 PWM 模式下,与 CCAPnH 组成 9 位数。
//B0(EPCnL): 在 PWM 模式下,与 CCAPnL 组成 9 位数。
//--------------------------------------------------------------------------------
//新一代 1T 8051系列 单片机 ADC 特殊功能寄存器
//                                            7        6      5       4         3      2    1    0   Reset Value
sfr ADC_CONTR = 0xBC; //A/D 转换控制寄存器 ADC_POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0 0000,0000
sfr ADC_RES  = 0xBD;  //A/D 转换结果高8位 ADCV.9 ADCV.8 ADCV.7 ADCV.6 ADCV.5 ADCV.4 ADCV.3 ADCV.2         0000,0000
sfr ADC_RESL = 0xBE;  //A/D 转换结果低2位                                           ADCV.1 ADCV.0         0000,0000
//--------------------------------------------------------------------------------
//新一代 1T 8051系列 单片机 SPI 特殊功能寄存器
//                                      7     6     5     4     3     2     1     0    Reset Value
sfr SPCTL  = 0xCE; //SPI Control Register  SSIG  SPEN  DORD  MSTR  CPOL  CPHA  SPR1  SPR0  0000,0100
sfr SPSTAT = 0xCD; //SPI Status Register   SPIF  WCOL   -     -     -     -     -     -    00xx,xxxx
sfr SPDAT  = 0xCF; //SPI Data Register                                                     0000,0000
//--------------------------------------------------------------------------------
//新一代 1T 8051系列 单片机 IAP/ISP 特殊功能寄存器
sfr IAP_DATA    = 0xC2;
sfr IAP_ADDRH   = 0xC3;
sfr IAP_ADDRL   = 0xC4;
//                                                7    6    5      4    3    2    1     0    Reset Value
sfr IAP_CMD     = 0xC5; //IAP Mode Table          0    -    -      -    -    -   MS1   MS0   0xxx,xx00
sfr IAP_TRIG    = 0xC6;
sfr IAP_CONTR   = 0xC7; //IAP Control Register  IAPEN SWBS SWRST CFAIL  -   WT2  WT1   WT0   0000,x000
//--------------------------------------------------------------------------------


//*******************************************************
// 实验调试助手,串口字符显示(版本:2011/08/06)
//
// 串口说明:使用定时器1,字符发送,N,8,1
//
// (      6MHz @ 1T) 28800bps
// (11.0592MHz @ 1T)115200bps
// (     12MHz @ 1T) 57600bps
// (22.1184MHz @ 1T)256000bps
//
// (      6MHz @12T)  2400bps
// (11.0592MHz @12T) 57600bps
// (     12MHz @12T)  4800bps
//
// 【供用户调用的3个函数】
// void   Uart_Init(uint8 M,uint8 T);             //串口初始化
// void   JZ(uint32 tem,uint8 num,uint8 i);         //整形数据送串口显示
// void   ZIFUC(uint8 code *p);                     //字符串发送                                                                  
//*******************************************************

#ifndef  _CKA_H_
#define  _CKA_H_
#include <intrins.h>
#define uint8   unsigned char     
#define uint16  unsigned int
#define uint32  unsigned long

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:串口初始化
入口:(MHz,12T/1T)

举例:如使用  22.1184MHz晶振,STC 1T系列,
      那么初始化时应为:  Uart_Init(22,1),
      与PC的串口助手通讯:波特率256000bps,字符,校验位N,数据位8,停止位1
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void Uart_Init(uint8 M,uint8 T)               
{
   bit BS,XT;
   uint16 MT;
   MT = M*100+T;
   switch(MT)
   {
       //////////////////////////////////////////////【1T系列】
      case 601:                         //28800bps@6MHz
                BS  = 1;                //倍速
                XT  = 1;                //1T模式
                TL1 = 0xF3;             //初值
                break;
      case 1101:                        //115200bps@11.0592MHz
                BS  = 0;                //不倍速
                XT         = 1;         //1T模式
                TL1 = 0xFD;             //初值
                break;
       case 1201:                       //57600bps@12MHz
                BS  = 1;                //倍速
                XT  = 1;                //1T模式
                TL1 = 0xF3;             //初值        
                break;
       case 2201:                       //256000bps@22.1184MHz
                BS = 1;                 //倍速
                XT = 1;                 //1T模式
                TL1 = 0xFB;             //初值        
             break;        
   //////////////////////////////////////////////【12T系列】
       case 612:                        //2400bps@6MHz
                BS  = 1;                //倍速
                XT  = 0;                //12T模式
                TL1 = 0xF3;             //初值
                break;
       case 1112:                       //57600bps@11.0592MHz
                BS  = 1;                //倍速
                XT  = 0;                //12T模式
                TL1 = 0xFF;             //初值
                break;
       case 1212:                       //4800bps@12MHz
                BS = 1;                 //倍速
                XT = 0;                 //12T模式
                TL1 = 0xF3;             //初值        
                break;                                                                                    
  }

  if(BS)

     PCON |= 0x80;                     //使能波特率倍速位SMOD

  else  

     PCON &= 0x7f;                     //波特率不倍速

  SCON  = 0x50;                         //8位数据,可变波特率

  if(XT)

      AUXR |= 0x40;                     //定时器1时钟为Fosc,即1T
  else
      AUXR &= 0xbf;                     //定时器1时钟为Fosc/12,即12T

  AUXR &= 0xfe;                         //串口1选择定时器1为波特率发生器
  TMOD &= 0x0f;                         //清除定时器1模式位
  TMOD |= 0x20;                         //设定定时器1为8位自动重装方式
  TH1 = TL1;                            //重装值
  ET1 = 0;                              //禁止定时器1中断
  TR1 = 1;                              //启动定时器1

}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:HEX转ASCII
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
uint8 HEX2ASCII(uint8 dat)
{
        dat &= 0x0f;
        if(dat <= 9) return(dat+'0');               //数字0~9  ('0' 0x30)
        return (dat-10+'A');                        //字母A~F  ('A' 0x41,'a' 0x61)
}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:串口发送
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void TxS(uint8 i)
{
   SBUF=i;
   while(!TI);
   TI=0;
}
/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:字符串发送
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void ZIFUC(uint8 code *p)                             //发送一串字符串
{
    for(; *p != 0; p++) TxS(*p);                      //遇到停止符0结束
}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:整形数据送串口显示
入口:tem = 整形数据(送入1~4字节整形数据)
      num = 以什么进制显示,2:二进制,10:十进制,16:十六进制
      i   = 显示低几位          (以二进制显示时)
          = 显示个位算起几位数  (以十进制显示时)
          = 显示几字节          (以十六进制显示时)
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void JZ(uint32 tem,uint8 num,uint8 i)
{
   uint8 j,z[10];
   bit   BT=0;
   switch(num)
   {
       case  2: tem = _lror_(tem,i-1);               //以二进制显示                 长整数循环右移
                while(i--)
                {
                        if(tem & 1)
                                                
                                                         ZIFUC("1");

                         else   
                                                                
                                                      ZIFUC("0");        

                         tem = _lrol_(tem,1);
                 }
                /*        【 另一种算法 】
                 tem <<= (32-i);
                 while(i--)
                 {
                     if(tem & 0x80000000)
                                               ZIFUC("1");
                      else                    
                                               ZIFUC("0");
                      tem <<= 1;
                              
                                  }
                                 */
                  break;

       case 10: for(j=0;j<i;j++)                          //以十进制显示
                {
                      z[j] = tem%10;                      //nv[0]=个位,nv[1]=十位,······
                      tem /= 10;
                 }
               
                 while(i--)
                 {
                    if(z || (i==0))
                                            BT=1;                            //数据有效标志
                    if(BT)

                                            TxS(HEX2ASCII(z[i]));            //数据有效前的“0”不显示,                z  z[i]

                    else  

                                            ZIFUC(" ");                      //用空格替换。
                 }
                 break;

       case 16: for(j=4-i;j<4;j++)                        //十六进制显示
                {
                  z[j] = ((uint8 *)&tem)[j];
                  TxS(HEX2ASCII(z[j]>>4));                //发送高4位
                  TxS(HEX2ASCII(z[j]));                   //发送低4位
                }
                break;
   }
}

#endif

出0入0汤圆

发表于 2012-9-28 14:02:14 | 显示全部楼层
BXAK楼主!
希望您有空可以回答下我这几个问题好么?
第一个问题:
           我要将捕获到高低电平,有什么办法可以把数据压缩一下啊,存到eeprom中去?
第二个问题:
           捕获的16位计数器,CH和CL,因为是1T的单片机,晶振为 12MHZ,当计数最大到65536,时间为: 1/12 *65536 us 约等于5461us,也就是5.641ms.   那么在记录9ms的引导码中的高电平的时候,PCA不就产生中断了嘛?

第三个问题:
         是在捕获中断的程序中,为什么1个电平接收时间3个字节存放呢? 当捕获到有跳变的时候就是PCA计数器阵列寄存器(CL和CH)的值装载到模块的捕获寄存器中(假设用到模块1:CCAP1L 和 CCAP2H)。电平时间只用了两个字节存放,为什么说一个电平时间三个字节存放呢?真的不明白,这点!研究了一个上午了这里!

/***************************************************************
函数:PCA中断捕获程序(电位跳变捕获模式)
***************************************************************/
void PCA_isr(void) interrupt 6 using 1
{
     if(CF)                                         //是否是PCA定时器溢出
     {
            CF = 0;                         //必须软件清0 (PCA 定时器标志)
        v[t]++;                        //PCA定时器溢出计数,保存数据最高字节
        if(v[t]>1)                     //设置允许溢出次数,>131ms 终止捕获    这个131ms是怎么算出来的呢?
                                                                                  溢出的时间为5.4ms.
        
        {
               CR = 0;   
               CF = 0;
               CCAPM1 = 0;
               CCF1=0;
               VT=1;                       //捕获完成标志
          v[t]=0;
               return;

            }
      }
     if(CCF1)                               //是否是电位跳变
     {
               CCF1 = 0;                      //必须软件清0 (PCA 模块1标志)
          CL   = 0;                       //先赋值低位
          CH   = 0;            
               if(B_Z)
              {
           CR =1;                      //启动PCA定时器
             B_Z=0;
                   return;                          
              }                                  //丢弃第一次捕获数据
          t++;
               v[t]=CCAP1H;                //保存数据高字节     这里每跳变一次,分别保存了数据高字节和低字节!
                                                      就用到两个字,要是三个字节,那第三个字节呢?   
   
          t++;
               v[t]=CCAP1L;                //保存数据低字节
          t++;               
     }

     if(t >= 486)                          //捕获162个数据(1个电平时间3字节存放),    程序中没有出一个电平三个字节存放哇?                                                                                         {                                                                                                                    
              CCAPM1 = 0;
                CCF1=0;
                CR = 0;
                CF = 0;
                VT = 1;                           //捕获完成标志
       }
}

第三个问题:
          是NEC解码这里!按照上面所说的一个电平三个字节保存,引导码一个低电平接着一个高电平共6个字节,那么接下来判断用户码高八位,低八位,操作码高八位,低八位,应该是从数组V的第7元素个判断吧?然而下面的判断完全不是?不解?
          还有从数组中读出来也不是三个字节三个字节的读,前面不是说一个电平用来三个字节来保存嘛?为什么现在读,显然只读出来两个字节,来判断!感觉好矛盾!

///////////////// NEC解码 ////////////////         
          j=9;                                                    //引导码丢弃
      for(i=0;i<32;i++)
          {
                          j++;                                                //j=10;                 
                         ((uchar *)&T)[0] = v[j++];                //V[10]
                          ((uchar *)&T)[1] = v[j++];               //V[11]
                          j += 3;                                          //j=12+3=15
                          N[i/8] >>= 1;
                          if((T<1900) && (T>1000))
                  {
                 N[i/8] |= 0x80;
                  }          
          }            


楼主:我把这几个问题提出来,并不是抱怨,只是这几个问题,困扰着我,楼主的帖子我看了好几个,让我学到了好多,看到楼主这个帖子,我最近在做一个学习型的遥控器,所以很认真的研究了下这个程序,以上这几个问题是我还没弄明白的,希望楼主有空解答我一下,谢谢,楼主!

下面,我把我改进的发上来,用STC12C5A60S2实现的,用来PCA模块1,也就是红外接收端口接P1.4,用来STC12C5A60S2的头文件!

出0入0汤圆

发表于 2012-9-28 14:13:56 | 显示全部楼层
这是我更改的程序,换成STC12C5A60S2的单片机,压缩文件里面有STC125A60S2的数据手册和STC12C5410AD的数据手册。
楼主的程序中还有细节的几个地方没弄好,我也改过来了!
比如:
for(i=0;i<486;i++)
  {
      v=0;                           //存储区清0                        v=0   改成  v[t]=0;      
  }  

又比如:

void JZ(uint32 tem,uint8 num,uint8 i) 函数中的

case 10:
for(j=0;j<i;j++)                          //以十进制显示
{
               z[j] = tem%10;                      //nv[0]=个位,nv[1]=十位,······
               tem /= 10;
}

while(i--)
{
                  
      if(z || (i==0))                                           z 改成 z[i]
                                          
       BT=1;                                                              
    if(BT)

           TxS(HEX2ASCII( z) );                  z 改成 z[i]

      else  

               ZIFUC(" ");                  
}

break;

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-9-28 14:17:10 | 显示全部楼层
C:\Documents and Settings\Administrator\桌面\1.png这是实验后的结果图:

C:\Documents and Settings\Administrator\桌面\2.png

出0入0汤圆

发表于 2012-9-28 14:18:18 | 显示全部楼层





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-9-28 14:42:16 | 显示全部楼层


  1.                 ****** 开始接收,请按遥控 ******


  2.                 ****** 接收完成 ******

  3. ( 以下是遥控器发射脉冲的波形示?)

  4.   序号  高电平时间(us)  低电平时间(us)

  5.    0       9018            4410

  6.    1    1245772         3277322
  7.    2    3998331             517
  8.    3    3211878         3211780
  9.    4     524901         2098768
  10.    5   16253541         3473925
  11.    6   11600486         3867141
  12.    7    3670624             518
  13.    8    3736162         3146246

  14.    9    7930465            1615
  15.   10    7275109         3212880
  16.   11    3211877         8126980
  17.   12    1114725        11600388
  18.   13    3146340        12125775
  19.   14    2163300         3342851
  20.   15    5833316         3736068
  21.   16    1114725         3736069

  22.   17    3277414         3211782
  23.   18    3342945             518
  24.   19    3146337         1312337
  25.   20    3211878         1638917
  26.   21    3211873         9765382
  27.   22    9831010         7733767
  28.   23    9831010        10879495
  29.   24    1507938         9700945

  30.   25   11993696         9307727
  31.   26    7799396         3540558
  32.   27    3539555         1442305
  33.   28    5702242         1181265
  34.   29   13763170         9832015
  35.   30    9896548         5506637
  36.   31    1507938         9832013
  37.   32    1442402        11928062

  38.   33    9699941        10267556
  39.   34   12460863         9832574
  40.   35   16122441           38423
  41.   36    1446956        11769428
  42.   37    9450516         9753652
  43.   38    1447542         9901573
  44.   39    9934518        11966358
  45.   40   14031543          431254

  46.   41   12048019         9835670
  47.   42   13932046         9704609
  48.   43   11805880        14955760
  49.   44   10528180        11579541
  50.   45    9743520         2106528
  51.   46   10495028         2400388
  52.   47    9708193        15787142
  53.   48   10792996        12754976

  54.   49    3945632         2374785
  55.   50    2158756         3187872
  56.   51   11580592        11592372
  57.   52    2560740         6389796
  58.   53    1482788         1942706
  59.   54   12103908         3187872
  60.   55    3584036         8533664
  61.   56   10498096        11313184

  62.   57    3281068        13672886
  63.   58    3186853         2497152
  64.   59   14721136         3155476
  65.   60    2143232         9449602
  66.   61   11861344        11805832
  67.   62    3467444        11567664
  68.   63   10757281        10809572
  69.   64       5168        14816018

  70.   65   15734627         7827601
  71.   66   13647985         1127705
  72.   67    7352401           65793
  73.   68    3821858         8392976
  74.   69    7377177        15882608
  75.   70     210994         1060976
  76.   71    3229330            4625
  77.   72    2118224         5247040

  78.   73    9506898          151552
  79.   74    7340049            8288
  80.   75    5706035         7417873
  81.   76   13649183         5328913
  82.   77    5263736          152064
  83.   78    3756296         4211120
  84.   79    5771544         1123668
  85.   80    3330417         5255252


  86. 【 NEC通用编码格式:业悸?+ 32位编码(16位用户码+操作码辗绰耄?】

  87. 用户码(高8位):0x08
  88. 用户码(低8位):0x13

  89. 操作码章?:0x84
复制代码
实验结果表明 解码正确,我用另外一个程序解码,此解码是正确的。说明楼主的这个程序没有问题,但是那几问题真的不懂!

出0入0汤圆

 楼主| 发表于 2012-9-28 19:27:41 | 显示全部楼层
yihui184 发表于 2012-9-28 14:02
BXAK楼主!
希望您有空可以回答下我这几个问题好么?
第一个问题:


第一个问题:我要将捕获到高低电平,有什么办法可以把数据压缩一下啊,存到eeprom中去?

       你要做那种 可以学习大部分固定编码的“学习型遥控器”,还是只学习单一固定编码的“学习型遥控器”?
       前者非压缩方式,学习一个按键要存储一定连续数量的高、低电平时间,所需的存储空间很大。比如常用的NEC,大概要存储68个电平时间,需要 68*2 字节存储。16个按键就要2176字节。STC12C5A32S2有28K的eeprom(data Flash),足够使用。
       后者只需解码后存储键值就行,学习一个按键只用几个字节来保存数据。

第二个问题:捕获的16位计数器,CH和CL,因为是1T的单片机,晶振为 12MHZ,当计数最大到65536,时间为: 1/12 *65536 us 约等于5461us,也就是5.641ms.   那么在记录9ms的引导码中的高电平的时候,PCA不就产生中断了嘛?

       STC 1T系列单片机的各种定时器默认的时钟源模式都是 12t的,程序中用的也是默认设置,所以12MHZ最大计数到65.535 ms,所以9ms不会溢出。
  
第三个问题:是在捕获中断的程序中,为什么1个电平接收时间3个字节存放呢? 当捕获到有跳变的时候就是PCA计数器阵列寄存器(CL和CH)的值装载到模块的捕获寄存器中(假设用到模块1:CCAP1L 和 CCAP2H)。电平时间只用了两个字节存放,为什么说一个电平时间三个字节存放呢?真的不明白,这点!研究了一个上午了这里!

       这个程序主要是用来捕获及显示红外遥控的电平时间,所以要考虑到允许捕获电平时间的最大值,12MHZ 2个字节只能记录65.535 ms,而像NEC的重复码里面有约96ms的低电平、长虹遥控RC5连续发射时的间隔有约86ms低电平……这些我都想捕获显示,就需要3字节存储,也就必须考虑定时器溢出,3个字节的高字节就是用来记录定时器溢出次数的,如程序中:
v[t]++;                //PCA定时器溢出计数,保存数据最高字节
if(v[t]>1)             //设置允许溢出次数,>131ms 终止捕获

出0入0汤圆

 楼主| 发表于 2012-9-28 19:38:31 | 显示全部楼层
还有,如果你想用存储电平时间方式来做“学习型遥控器”,没必要12MHz,可以用6MHz,这样12t模式计数1就相当于2us,65535就可表示130ms,用2个字节来存储一个电平时间

出0入0汤圆

发表于 2012-11-18 15:48:05 | 显示全部楼层
  不错,学习了! 希望能移植到8051F340芯片上去运行!

出0入0汤圆

发表于 2013-1-6 18:01:21 | 显示全部楼层
太不像话了,做这么强大的东西,不是打击我们菜鸟学习的心吗!!

出0入0汤圆

发表于 2013-3-18 15:49:47 | 显示全部楼层
mark,学习,

出0入0汤圆

发表于 2013-3-18 17:16:30 | 显示全部楼层
牛,,,试试。

出0入0汤圆

发表于 2013-3-19 09:41:22 来自手机 | 显示全部楼层
不错,顶一下

出0入0汤圆

发表于 2013-5-9 13:19:44 | 显示全部楼层
本帖最后由 wolfbeard 于 2013-5-9 13:23 编辑
yihui184 发表于 2012-9-27 14:02
我用STC12C5A60S2的芯片跑了这个程序,程序跑成功了,用的是该芯片的PCA模块1,头文件改成了PCA1.主函数和 ...


谢谢楼主分享!
38楼改用STC12C5A60S2跑这个程序的话,捕获中断应该用中断 7,不能用这个:
/***************************************************************
函数:PCA中断捕获程序(电位跳变捕获模式)
***************************************************************/
void PCA_isr(void) interrupt 6 using 1

出0入0汤圆

发表于 2013-5-9 16:48:39 | 显示全部楼层
mark,thanks.

出0入0汤圆

发表于 2013-7-5 10:42:43 | 显示全部楼层
不错 谢谢 ~~~

出0入0汤圆

发表于 2013-8-4 15:53:45 | 显示全部楼层
lz思路有借鉴意义,感谢分享!

出0入4汤圆

发表于 2014-4-4 15:17:29 | 显示全部楼层
mark 牛人!!!!!!!!!!!!!

出0入0汤圆

发表于 2014-4-4 22:16:58 | 显示全部楼层
MARK.学习型遥控器。

出0入0汤圆

发表于 2014-4-4 22:26:20 | 显示全部楼层
不错!!收藏。

出0入0汤圆

发表于 2014-5-26 21:39:00 | 显示全部楼层
很不错,必须收藏!

出0入0汤圆

发表于 2014-9-25 09:36:10 | 显示全部楼层
这个要收藏啊

出0入0汤圆

发表于 2014-12-4 10:57:47 | 显示全部楼层
好文章,学习一下!

出0入0汤圆

发表于 2016-4-5 21:09:13 | 显示全部楼层
感觉好牛B的样子啊,学习一下

出0入0汤圆

发表于 2016-6-15 07:58:54 来自手机 | 显示全部楼层
好思路,顶一下

出0入0汤圆

发表于 2016-11-22 12:02:09 | 显示全部楼层
一直用定时器中断查询,好思路私藏

出0入0汤圆

发表于 2016-12-7 11:09:26 | 显示全部楼层
在中断里面用 return 会不会有问题
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 10:17

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表