阿飞7812 发表于 2025-5-28 09:35:00

15W408AS程序移植到STC8H1K08出现的问题

我在网上找了一个315解决码程序试了没问题 程序如下      //-----------------兼容2262 1527的解码实验程序----------------//

//测试单片机:STC15W408AS

//晶振:内部 11.0592mHZ

//复位方式:内部复位
                     
//串口通讯:波特率9600/数据位8/停止位1/无校验

//调试环境:KEIL3

//程序功能:实现2262解码,学习、自适应多阻值,片内EEPROM,存储60个遥控器数据
      
//          不依赖硬件,不占用硬件资源。移植更加方便

//                        学习遥控器:按一下学习键,学习灯点亮,松开学习键,按动要学习的遥控器按键,学习灯熄灭,学习成功。重复上述操作可学习多个遥控器.
//
//          清除:按住学习键不放,直到学习灯自动熄灭,擦除成功.

/**********************************************************/


#include <STC15W408AS.h>
#include <intrins.h>
#define uchar unsigned char
#define uintunsigned int
sbit RF                           =      P1^1;          //信号输入
sbit LED                =      P3^3;          //学习指示灯
sbit set               =      P1^2;          //学习键                                                         
sbit D0                        =      P3^4;          //1号继电器解码输出
sbit D1                        =      P3^5;   //2号继电器
sbit D2                        =      P3^6;          //3号继电器
sbit D3                        =      P3^7;          //4号继电器
sbit deng1      =      P1^7;          //K1指示灯
sbit deng2      =      P5^4;          //K2指示灯
sbit deng3      =      P5^5;          //K3指示灯
sbit deng4      =      P3^2;          //K4指示灯
sbit VT                        =      P1^0;   //接收指示灯                              
sbit aj1                =   P1^3;          //K1
sbit aj2                =   P1^4;          //K2
sbit aj3                =   P1^5;          //K3
sbit aj4                =   P1^6;          //K4
bitdecode_ok;               //解码成功
bit rf_ok;               //收到有效数据
bit study;         //学习标志
bit jmnx;//编码类型 0是2262,1是1527
bit m=0,ba=0,ca=0,da=0,ea=0,za=0,aa=0,hv=0,ff=0,ra=0,rb=0,rc=0,rd=0,g=0,hm=0,biao=0,kt=0;
bit biao_1=0,g_1=0,kt_1=0,hm_1=0;
bit biao_2=0,g_2=0,kt_2=0,hm_2=0;
bit biao_3=0,g_3=0,kt_3=0,hm_3=0;
uchar da1527;//解码过程中临时数组
uchar key_d;//遥控器按键码
uchar short_k;   //窄脉冲宽度
uchar ss=0,sn=0,h=0,yz=0,hh=0,yy=0,yk=0,yu=0;hk=0,sj=0,so=0,jk=0,hu=0,t1=0,t2=0,t3=0,t4=0;
uint dt=0,dr=0,dq=0,rv=0,rv_1=0,rv_2=0,rv_3=0;
uchar trg=0,trg_1=0,trg_2=0,trg_3=0,cont=0,cont_1=0,cont_2=0,cont_3=0;
uchar ReadData=0,ReadData_1=0,ReadData_2=0,ReadData_3=0;
static uint sk=0;
uchar xdata key_number;                //遥控器编码数组,存放60个遥控器


void delay_1ms(uint x)    //1毫秒延时
{
      uchar b,c;
      for(x;x>0;x--)
                {
                        for(b=3;b>0;b--)
                              {
                                        for(c=150;c>0;c--);
                              }
                }
}

void delay(uint ms)//
{
while(ms--)
    {
         ms++;

         ms--;
    }
}




//====================================================
/////////片内EEPROM读写驱动程序///////////////////////////
//====================================================


void IAP_Disable()         //关闭IAP
{
    //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
    //一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
    IAP_CONTR = 0;      //关闭IAP 功能
    IAP_CMD   = 0;      //清命令寄存器,使命令寄存器无命令,此句可不用
    IAP_TRIG = 0;      //清命令触发寄存器,使命令触发寄存器无触发,此句可不用
    IAP_ADDRH = 0;
    IAP_ADDRL = 0;
}//



//读一字节,调用前需打开IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节
uchar read_add(uint addr)         //读EEPROM
{
    IAP_DATA = 0x00;
    IAP_CONTR = 0x84;         //打开IAP 功能, 设置Flash 操作等待时间
    IAP_CMD = 0x01;               //IAP/ISP/EEPROM 字节读命令

    IAP_ADDRH = addr>>8;    //设置目标单元地址的高8 位地址
    IAP_ADDRL = addr&0xff;    //设置目标单元地址的低8 位地址

    EA = 0;
    IAP_TRIG = 0x5a;   //先送 46h,再送B9h 到ISP/IAP 触发寄存器,每次都需如此
    IAP_TRIG = 0xa5;   //送完 B9h 后,ISP/IAP 命令立即被触发起动
    _nop_();
    EA = 1;
    IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
                  //一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
    return (IAP_DATA);
}//------------------------------------------------------------------------------


//字节编程,调用前需打开IAP 功能,入口:DPTR = 字节地址, A= 须编程字节的数据
void write_add(uint addr,uchar ch)         //直接写EEPROM
{
    IAP_CONTR = 0x84;         //打开 IAP 功能, 设置Flash 操作等待时间
    IAP_CMD = 0x02;               //IAP/ISP/EEPROM 字节编程命令


    IAP_ADDRH = addr>>8;    //设置目标单元地址的高8 位地址
    IAP_ADDRL = addr&0xff;    //设置目标单元地址的低8 位地址

    IAP_DATA = ch;                  //要编程的数据先送进IAP_DATA 寄存器
    EA = 0;
    IAP_TRIG = 0x5a;   //先送 46h,再送B9h 到ISP/IAP 触发寄存器,每次都需如此
    IAP_TRIG = 0xa5;   //送完 B9h 后,ISP/IAP 命令立即被触发起动
    _nop_();
    EA = 1;
    IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
                  //一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
}//------------------------------------------------------------------------------
//擦除扇区, 入口:DPTR = 扇区地址


void Sector_Erase(uint addr)         //扇区擦除
{
   IAP_CONTR = 0x84;         //打开IAP 功能, 设置Flash 操作等待时间
    IAP_CMD = 0x03;               //IAP/ISP/EEPROM 扇区擦除命令

    IAP_ADDRH =addr>>8;    //设置目标单元地址的高8 位地址
    IAP_ADDRL =addr&0xff;    //设置目标单元地址的低8 位地址

    EA = 0;
    IAP_TRIG = 0x5a;   //先送 46h,再送B9h 到ISP/IAP 触发寄存器,每次都需如此
    IAP_TRIG = 0xa5;   //送完 B9h 后,ISP/IAP 命令立即被触发起动
    _nop_();
    EA = 1;
}//------------------------------------------------------------------------------



//============================接收解码部分========================================//

void RF_decode()         
{
         uchar ii=0,j=0,k=0,rep=0;
            uint head_k=0;         //短脉冲宽度
          uchar s;   
//-------------------------------数据接收-----------------------------------------
      short_k=0;
          while(RF && j<250)         //检测头信号前一个高脉冲的宽度
                   {
                         delay(1);      
                        short_k++;
               }
          while(!RF)
                   {
                         delay(1);
                        head_k++;
               } //检测头脉冲的宽度         
      if(((short_k*24)<head_k) && (head_k<(short_k*38)))   //引导码宽度是窄脉冲的32倍 24/38
         {                        
            for(rep=0;rep<2;rep++)         
               {
                           for(ii=0;ii<3;ii++)//3字节
                           {
                                 for(k=0;k<8;k++)//每个字节8位
                                    {                                    
                                                    j=0;
                                                      while(RF && j<245)
                                                                {
                                                                        delay(1);
                                                                        j++;
                                                                }//
                                             if(j>(short_k-short_k/2-short_k/3)&&j<(short_k*1.96))
                                                                {
                                                                        da1527&=~(1<<((7-k)));
                                                                }                                    
                                                      else if(j>(short_k*1.96)&&j<(short_k*5))da1527|=(1<<(7-k));                                                
                                                else {return;}          //乱码退出      
                                             j=0;
                                                      while(!RF && j<150){delay(2);j++;}      //跳过低电平                                 
                                                 }
                                 }//for(ii=0;ii<12;ii++)
                   j=0;while(RF && (j<200)){delay(1);j++;}            //跳个最后一个高脉冲                           
                               head_k=0;while(!RF) {delay(1);head_k++;} //检测下一个前导信号的寬度
                               if((head_k<(short_k*26)) || (head_k>(short_k*38))){return;} //引导码宽度是窄脉冲的32倍//乱码退出
                           }
            //+++++++++++++++++++++++++2262与1527数据分离处理++++++++++++++++++++++++++++++++++++++++            
                         if((da1527==da1527) && (da1527==da1527) && (da1527==da1527))      //两次接收到的数据相同
                      {         
                     uchar u,i,x;
                                       rf_ok=1;
                                       for(i=0;i<3;i++)//判定2262与1527
                        {
                           for(u=0;u<4;u++) {if(((da1527>>(u*2)) & 3)==2) {i=80;break;}}//有10则为1527
                                                   if(i==80) break;
                        }
                     if(i==80)//1527
                        {
                        key_d=da1527 & 0x0f;         //分出1527的按键值
                        da1527=da1527>>4; //分出1527的后4位地址
                                                jmnx=1;         //为0是2262,1是1527
                        }
                     else      //2262
                         {
                        key_d=0;
                        for(i=0;i<4;i++){if(((da1527>>(i*2))&3)==3) key_d|=1<<i;}   //计算出2262的按键数据                                 
                        da1527=0x00; //2262无后4位地址,全为0
                                                jmnx=0;         //为0是2262,1是1527
                                                jk++;//自锁用,作用:按下按键不松手继电器状态不变,松开再按下改变,一次只改变一次状态,因为按下按键后遥控会一直发码,所以让jk一直自加,但是只取jk=1的值的状态
                         }
                                                   
                                          if (!study)                //非学习状态
                                                {
                                                      rf_ok=0;
                                                      for(x=0;x<60;x++)
                                                                   {
                                                                        if((da1527==key_number)&&(da1527==key_number)
                                                                                                                                        &&(da1527==key_number))//判断是否已学习过的编码
                                                                              {

//                                                                                    D0=!(key_d&0x08);                //取得按键码
//                                                                                        D1=!(key_d&0x04);
//                                                                                        D2=!(key_d&0x02);
//                                                                                        D3=!(key_d&0x01);
                                          if(m==1)//互锁
                                                                                        {         
                                                                                        if(key_d == 0x01){D0=0;D1=1;D2=1;D3=1;}//D4=1;D5=1;D6=1;D7=1;D8=1;D9=1;D10=1;D11=1;}//else{D0=1;}
                                                                                        if(key_d == 0x02){D0=1;D1=0;D2=1;D3=1;}//D4=1;D5=1;D6=1;D7=1;D8=1;D9=1;D10=1;D11=1;}
//                                                                                        if(key_d == 0x03){D0=1;D1=1;D2=0;D3=1;D4=1;D5=1;D6=1;D7=1;D8=1;D9=1;D10=1;D11=1;}
                                                                                        if(key_d == 0x04){D0=1;D1=1;D2=0;D3=1;}//D4=1;D5=1;D6=1;D7=1;D8=1;D9=1;D10=1;D11=1;}
//                                                                                        if(key_d == 0x05){D0=1;D1=1;D2=1;D3=1;D4=0;D5=1;D6=1;D7=1;D8=1;D9=1;D10=1;D11=1;}
//                                                                                        if(key_d == 0x06){D0=1;D1=1;D2=1;D3=1;D4=1;D5=0;D6=1;D7=1;D8=1;D9=1;D10=1;D11=1;}
//                                                                                        if(key_d == 0x07){D0=1;D1=1;D2=1;D3=1;D4=1;D5=1;D6=0;D7=1;D8=1;D9=1;D10=1;D11=1;}
                                                                                        if(key_d == 0x08){D0=1;D1=1;D2=1;D3=0;}//D4=1;D5=1;D6=1;D7=0;D8=1;D9=1;D10=1;D11=1;}
//                                                                                        if(key_d == 0x09){D0=1;D1=1;D2=1;D3=1;D4=1;D5=1;D6=1;D7=1;D8=0;D9=1;D10=1;D11=1;}
//                                                                                        if(key_d == 0x0a){D0=1;D1=1;D2=1;D3=1;D4=1;D5=1;D6=1;D7=1;D8=1;D9=0;D10=1;D11=1;}
//                                                                                        if(key_d == 0x0b){D0=1;D1=1;D2=1;D3=1;D4=1;D5=1;D6=1;D7=1;D8=1;D9=1;D10=0;D11=1;}
//                                                                                        if(key_d == 0x0c){D0=1;D1=1;D2=1;D3=1;D4=1;D5=1;D6=1;D7=1;D8=1;D9=1;D10=1;D11=0;}
                                                                                        }
                                                                                        else
                                                                                        {
                                                                                        if(ba==0) //B按键自锁
                                                                                        {
                                                                                     if(key_d == 0x04)
                                                                                          {
                                                                                                if(jk==1)
                                                                                                   {
                                                                                                   D2=~D2;
                                                                                                      }
                                                                                          }
                                                                                       } //B自锁

                                                                                       if(da==0) //A按键自锁
                                                                                        {
                                                                                     if(key_d == 0x08)
                                                                                          {
                                                                                                 if(jk==1)
                                                                                                   {
                                                                                                   D3=~D3;
                                                                                                      }
                                                                                          }
                                                                                       } //A自锁
                                                                                       if(ca==0) //C按键自锁
                                                                                        {
                                                                                     if(key_d == 0x02)
                                                                                          {
                                                                                                 if(jk==1)
                                                                                                   {
                                                                                                   D1=~D1;
                                                                                                      }
                                                                                          }
                                                                                       } //C自锁
                                                                                       if(ea==0) //D按键自锁
                                                                                        {
                                                                                     if(key_d == 0x01)
                                                                                          {
                                                                                                 if(jk==1)
                                                                                                   {
                                                                                                   D0=~D0;
                                                                                                      }
                                                                                          }
                                                                                       } //D自锁
                                                                                       if(ba==1)//B按键点动,ba为自锁转点动标志位
                                                                                       {
                                                                                          if(key_d == 0x04){D2=0;}
                                                                                          }
                                                                                       if(da==1)//A按键点动,da为自锁转点动标志位
                                                                                       {
                                                                                          if(key_d == 0x08){D3=0;}
                                                                                          }
                                                                                          if(ca==1)//C按键点动,da为自锁转点动标志位
                                                                                       {
                                                                                          if(key_d == 0x02){D1=0;}
                                                                                          }
                                                                                          if(ea==1)//D按键点动,da为自锁转点动标志位
                                                                                       {
                                                                                          if(key_d == 0x01){D0=0;}
                                                                                          }
                                                                                        }                                                                              
                                                                                        decode_ok=1;
                                                                                        ss=1;
                                                                                        sn=1;
                                                                                        sj=1;
                                                                                        so=1;
                                                                                        VT=0;                                                               
                                                                                        s=30;
                                                                                        break;
                                                                              }
                                                                                                               
                                                                }      
                                                
                                                
                                                }
                           
               }
            
         }
      if(decode_ok)   //解码有效信号,类似2272 PT脚
                  {
                        s--;
                        if(!s)
                              {
                                     jk=0; //按一下按键只做一次动作信号没有后清零
                                        decode_ok=0;
                                        if(h==1){ss=2;}      //点动标志位
                                        if(hh==1){sn=2;}
                                        if(hk==1){sj=2;}//点动标志位
                                        if(hu==1){so=2;}
                                        VT=1;
                              }                                 
                  }
                                 
                  
}

void key_buffer()                  //把遥控器码从 EEPROM 复制到DATA
{
      uchar n;

      for(n=0;n<181;n++)
                {
                   key_number=read_add(0x0000+n);                        
                }
}

void KEY_study()      //遥控器学习
{      
      uchar num_rf;
      uint d_num;
      if(study)
                {
                           rf_ok=0;
                        d_num=0;
      
                        while(!rf_ok)
                              {
                                        RF_decode();
                                        d_num++;
                                        if(d_num>50000) break;                                                                        
                              }
                        d_num=0;
                        if(rf_ok==1)
                              {

                                        num_rf=key_number;                   //取已学习的遥控器数量
                                        if(num_rf>60){num_rf=0;}      //如果遥控器数量超过10个,覆盖最先学习的
                                        key_number=da1527;
                                        key_number=da1527;
                                        key_number=da1527;
                                        key_number=num_rf+1;

                                        Sector_Erase(0x0000);
                                        for(num_rf=0;num_rf<181;num_rf++)
                                                {
                                                      write_add(0x0000+num_rf,key_number);
                                                      
                                                }
                                        rf_ok=0;
                                        LED=1;                   //学习成功                                       
                                  }      
                              else
                                        {
                                                rf_ok=0;

                                                for(num_rf=0;num_rf<8;num_rf++)                   //操作超时
                                                      {
                                                                LED=!LED;
                                                                delay_1ms(100);                                                      
                                                      }
                                                 LED=1;
                                       
                                        }
                        d_num=0;
                        study=0;               
                }
}

void system_res()//系统清零         
{
      
          Sector_Erase(0x0000);      
      write_add(0x0000,0x00);      
      key_buffer();               

}

void set_scan()          //判断学习键状态
{
uchar h=0;

while(!set)         
      {                        
                if(h>5)
                        {
                              study=1;
                              h=0;
                              LED=0;
                              while(!set)
                                        {
                                          delay_1ms(100);
                                          h++;
                                          if(h>80)
                                                {
                                                         study=0;
                                                      h=0;
                                                      system_res();
                                                      LED=1;
                                                      while(!set);
                                                }
                                       
                                        }
                        }
               delay_1ms(100);
                  h++;
         }                                                                              
if(study)
                {
                        KEY_study();
                }         
}


/*******************************************************************
*                        按键读取
********************************************************************/
void KeyRead()//读取按键IO口函数
{
   ReadData = aj1^0xff;// 读取按键状态取反后赋值给ReadData
   trg = ReadData & (ReadData ^ cont);//trg短按,每按下按键trg=1;抬手后为trg=0,长按为trg=0
   cont = ReadData;   //cont长按,长按cont=1,抬手后cont=0
/*******************************************************************/
         ReadData_1 = aj2^0xff;// 读取按键状态取反后赋值给ReadData
   trg_1 = ReadData_1 & (ReadData_1 ^ cont_1);//trg短按,每按下按键trg=1;抬手后为trg=0,长按为trg=0
   cont_1 = ReadData_1;   //cont长按,长按cont=1,抬手后cont=0
/*******************************************************************/
         ReadData_2 = aj3^0xff;// 读取按键状态取反后赋值给ReadData
   trg_2 = ReadData_2 & (ReadData_2 ^ cont_2);//trg短按,每按下按键trg=1;抬手后为trg=0,长按为trg=0
   cont_2 = ReadData_2;   //cont长按,长按cont=1,抬手后cont=0
/*******************************************************************/      
            ReadData_3 = aj4^0xff;// 读取按键状态取反后赋值给ReadData
   trg_3 = ReadData_3 & (ReadData_3 ^ cont_3);//trg短按,每按下按键trg=1;抬手后为trg=0,长按为trg=0
   cont_3 = ReadData_3;   //cont长按,长按cont=1,抬手后cont=0
}
/*******************************************************************
*                        A按键
********************************************************************/
void key_1()
{         
if(trg & 0x01) //短按
{         rv=0;          //长按延时标志位防止短按到200次后长按启动
   biao=0; //这是长按屏蔽短按标志位
         g=0;//这是长按只执行一次标志位
         kt=1; //这是短按标志位,kt=1说明短按了
}
if((aj1!=0)&&(kt==1)&&(biao==0))//判断
      {
   D3=~D3;kt=0;
    }         // 短按
if((cont & 0x01)&&(g==0))//长按
{
   rv++;   //长按延时
   if(rv>200)
   {
    biao=1;      //屏蔽短按
               hm=1;
               yz+=1;//选位标志位
                           if(yz==1){h=1;da=1;za=0;hm=0;}
                           if(yz==2){h=2;m=1;yy=0;yk=0;yu=0;hh=0;hk=0;hu=0;ba=0;ca=0;ea=0;da=0;za=0;}
                           if(yz==3){
                           yz=0;         //选位标志重个位开始重新选
                                 h=0;
                                 m=0;za=0;
                                 }
      g=1;//只让输出一次
      rv=0; //延时时间归零
   }
}//长按
}

/*******************************************************************
*                        B选位按键
********************************************************************/
void key_2()
{         
if(trg_1 & 0x01) //短按
{         rv_1=0;          //长按延时标志位防止短按到200次后长按启动
   biao_1=0; //这是长按屏蔽短按标志位
         g_1=0;//这是长按只执行一次标志位
         kt_1=1; //这是短按标志位,kt=1说明短按了
}
if((aj2!=0)&&(kt_1==1)&&(biao_1==0))//判断
      {
   D2=~D2;kt_1=0;
    }         // 短按
if((cont_1 & 0x01)&&(g_1==0))//长按
{
   rv_1++;   //长按延时
   if(rv_1>200)
   {
    biao_1=1;      //屏蔽短按
               hm_1=1;
               yy+=1;//选位标志位
                           if(yy==1){hh=1;ba=1;aa=0;hm_1=0;}
                           if(yy==2){hh=2;m=1;hk=0;h=0;hu=0;yz=0;yk=0;yu=0;ba=0;ca=0;ea=0;da=0;aa=0;}
                           if(yy==3){
                           yy=0;         //选位标志重个位开始重新选
                                 hh=0;
                                 m=0;aa=0;
                        }
      g_1=1;//只让输出一次
      rv_1=0; //延时时间归零
   }
}//长按
}
/*******************************************************************
*                        C选位按键
********************************************************************/
void key_3()
{         
if(trg_2 & 0x01) //短按
{         rv_2=0;          //长按延时标志位防止短按到200次后长按启动
   biao_2=0; //这是长按屏蔽短按标志位
         g_2=0;//这是长按只执行一次标志位
         kt_2=1; //这是短按标志位,kt=1说明短按了
}
if((aj3!=0)&&(kt_2==1)&&(biao_2==0))//判断
      {
   D1=~D1;kt_2=0;
    }         // 短按
if((cont_2 & 0x01)&&(g_2==0))//长按
{
   rv_2++;   //长按延时
   if(rv_2>200)
   {
    biao_2=1;      //屏蔽短按
               hm_2=1;
               yk+=1;//选位标志位
                           if(yk==1){hk=1;ca=1;ff=0;hm_2=0;}
                           if(yk==2){hk=2;m=1;h=0;hh=0;hu=0;yz=0;yy=0;yu=0;ba=0;ca=0;ea=0;da=0;ff=0;}
                           if(yk==3){
                           yk=0;         //选位标志重个位开始重新选
                                 hk=0;
                                 m=0;ff=0;
                        }
      g_2=1;//只让输出一次
      rv_2=0; //延时时间归零
   }
}//长按
}

/*******************************************************************
*                        D选位按键
********************************************************************/
void key_4()
{         
if(trg_3 & 0x01) //短按
{         rv_3=0;          //长按延时标志位防止短按到200次后长按启动
   biao_3=0; //这是长按屏蔽短按标志位
         g_3=0;//这是长按只执行一次标志位
         kt_3=1; //这是短按标志位,kt=1说明短按了
}
if((aj4!=0)&&(kt_3==1)&&(biao_3==0))//判断
      {
   D0=~D0;kt_3=0;
    }         // 短按
if((cont_3 & 0x01)&&(g_3==0))//长按
{
   rv_3++;   //长按延时
   if(rv_3>200)
   {
    biao_3=1;      //屏蔽短按
               hm_3=1;
               yu+=1;//选位标志位
                           if(yu==1){hu=1;ea=1;hv=0;hm_3=0;}
                           if(yu==2){hu=2;m=1;h=0;hh=0;hk=0;yz=0;yy=0;yk=0;ba=0;ca=0;ea=0;da=0;hv=0;}
                           if(yu==3){
                           yu=0;         //选位标志重个位开始重新选
                                 hu=0;
                                 m=0;hv=0;
                        }
      g_3=1;//只让输出一次
      rv_3=0; //延时时间归零
   }
}//长按
}
/*******************************************************************
*                        定时器配置
********************************************************************/
void ConfigTimer0(){
      TMOD=0x01;//将定时器0,1都设置为模式1
    TH0=0XFC;//1ms
    TL0=0X66;
      TR0=1;//开启定时器0
      ET0=1;//开定时器0的中断
      EA=1;//开总中断
}
/*******************************************************************
*                         t0定时器
********************************************************************/
void timer0() interrupt 1
{
    TH0=0XFC;//1ms
    TL0=0X66;
      sk++;
      if((t1==1)||(t2==1)||(t3==1)||(t4==1)) //闪烁一下
      {
         dq++;
         if(dq==1000)
         {
         if(ra==1){deng1=0;}
         if(rb==1){deng2=0;}
         if(rc==1){deng3=0;}
         if(rd==1){deng4=0;}
         }
      if(dq==2500)
         {
         if(ra==1){deng1=1;t1=0;ra=0;}
         if(rb==1){deng2=1;t2=0;rb=0;}
         if(rc==1){deng3=1;t3=0;rc=0;}
         if(rd==1){deng4=1;t4=0;rd=0;}
         dq=0;
         }
      }
    if((t1==2)||(t2==2)||(t3==2)||(t4==2)) //闪烁两下
      {
         dt++;
         if(dt==1000)
         {
         if(ra==1){deng1=0;}
         if(rb==1){deng2=0;}
         if(rc==1){deng3=0;}
         if(rd==1){deng4=0;}
         }
         if(dt==2500)
         {
         if(ra==1){deng1=1;}
         if(rb==1){deng2=1;}
         if(rc==1){deng3=1;}
         if(rd==1){deng4=1;}
         }
         if(dt==4000)
         {
         if(ra==1){deng1=0;}
         if(rb==1){deng2=0;}
         if(rc==1){deng3=0;}
         if(rd==1){deng4=0;}
         }
         if(dt==5500)
         {
         if(ra==1){deng1=1;t1=0;ra=0;}
         if(rb==1){deng2=1;t2=0;rb=0;}
         if(rc==1){deng3=1;t3=0;rc=0;}
         if(rd==1){deng4=1;t4=0;rd=0;}
         
         dt=0;
         
         }
      }

      if((t1==3)||(t2==3)||(t3==3)||(t4==3)) //闪烁三下
      {
                   dr++;
         if(dr==1000)
         {
         if(ra==1){deng1=0;}
         if(rb==1){deng2=0;}
         if(rc==1){deng3=0;}
         if(rd==1){deng4=0;}
         }
         if(dr==2500)
         {
         if(ra==1){deng1=1;}
         if(rb==1){deng2=1;}
         if(rc==1){deng3=1;}
         if(rd==1){deng4=1;}
         }
         if(dr==4000)
         {
         if(ra==1){deng1=0;}
         if(rb==1){deng2=0;}
         if(rc==1){deng3=0;}
         if(rd==1){deng4=0;}
         }
         if(dr==5500)
         {
         if(ra==1){deng1=1;}
         if(rb==1){deng2=1;}
         if(rc==1){deng3=1;}
         if(rd==1){deng4=1;}
         }
         if(dr==7000)
         {
         if(ra==1){deng1=0;}
         if(rb==1){deng2=0;}
         if(rc==1){deng3=0;}
         if(rd==1){deng4=0;}
         }
         if(dr==8500)
         {
         if(ra==1){deng1=1;t1=0;ra=0;}
         if(rb==1){deng2=1;t2=0;rb=0;}
         if(rc==1){deng3=1;t3=0;rc=0;}
         if(rd==1){deng4=1;t4=0;rd=0;}
         dr=0;
         }
      }
}

void system_start()   //上电初始化
{      
         AUXR=0xb5;   
         P0=0xfe;
      P1=0xff;
          P3=0xff;
      key_buffer();
}

void main()
{
system_start();//上电初始化
ConfigTimer0();//t0中断配置
deng1=1;
deng2=1;
deng3=1;
deng4=1;
while(1)
      {
            KeyRead();      //按键读取函数
            key_1();
                key_2();
                key_3();
                key_4();
                RF_decode();//读取信号波形分析
                set_scan();          //学习按键
                  if((h==1)&&(ss==2)){D3=1;} //A按键点动,h为k1按键按下后h=1,ss为接收指示灯熄灭后ss=2;控制对应输出断开,形成点动
                  if((hh==1)&&(sn==2)){D2=1;}//B按键点动,hh为k2按键按下后hh=1,sn为接收指示灯熄灭后sn=2;控制对应输出断开,形成点动
                  if((hk==1)&&(sj==2)){D1=1;} //C按键点动,hk为k3按键按下后hk=1,sj为接收指示灯熄灭后sj=2;控制对应输出断开,形成点动
                  if((hu==1)&&(so==2)){D0=1;} //D按键点动,hu为k4按键按下后hu=1,so为接收指示灯熄灭后so=2;控制对应输出断开,形成点动
                  if((yz==0)&&(za==0)&&(hm==1)){t1=1;za=1;ra=1;}//A按键:主要控制对应灯闪烁,za为只执行一次闪烁标志位,t1为闪烁标志位t1=1,闪一下,t1=2闪两下,t1=3闪三下
                  if((yz==1)&&(za==0)){t1=2;za=1;ra=1;}                //ra为对应灯输出标志位,ra=1则输出,ra=0则停止
                  if((yz==2)&&(za==0)){t1=3;za=1;ra=1;}
                  if((yy==0)&&(aa==0)&&(hm_1==1)){t2=1;aa=1;rb=1;}//B按键:主要控制对应灯闪烁,aa为只执行一次闪烁标志位,t2为闪烁标志位t2=1,闪一下,t2=2闪两下,t2=3闪三下
                  if((yy==1)&&(aa==0)){t2=2;aa=1;rb=1;}         //rb为对应灯输出标志位,rb=1则输出,rb=0则停止
                  if((yy==2)&&(aa==0)){t2=3;aa=1;rb=1;}
                  if((yk==0)&&(ff==0)&&(hm_2==1)){t3=1;ff=1;rc=1;}//C按键:主要控制对应灯闪烁,ff为只执行一次闪烁标志位,t3为闪烁标志位t3=1,闪一下,t3=2闪两下,t3=3闪三下
                  if((yk==1)&&(ff==0)){t3=2;ff=1;rc=1;}          //rc为对应灯输出标志位,rc=1则输出,rc=0则停止
                  if((yk==2)&&(ff==0)){t3=3;ff=1;rc=1;}
                  if((yu==0)&&(hv==0)&&(hm_3==1)){t4=1;hv=1;rd=1;}//D按键:主要控制对应灯闪烁,hv为只执行一次闪烁标志位,t4为闪烁标志位t4=1,闪一下,t4=2闪两下,t4=3闪三下
                  if((yu==1)&&(hv==0)){t4=2;hv=1;rd=1;}          //rd为对应灯输出标志位,rd=1则输出,rd=0则停止
                  if((yu==2)&&(hv==0)){t4=3;hv=1;rd=1;}
      }

}我把上面程序中开关控制部省了,把保遥控60个改为10个,编译没有问题 ,但学习功能不能程序没反应,用表测试学习按键按下从高电平能变成低电平,就是没反应,找不问题在那,求高人指点
改的程序如下//-----------------STC8H1K08 SOP16 遥控解码程序----------------//
//测试单片机:STC8H1K08//封装:SOP16//晶振:内部11.0592MHz//功能:2262/1527解码,遥控控制4路继电器,存储10个遥控器 #include <STC8H.H>#include <intrins.h>#define uchar unsigned char #define uint unsigned int // IO口分配(用户指定)sbit RF         =   P3^2;    //信号输入sbit LED      =   P3^5;    //学习指示灯sbit set      =   P3^6;    //学习键sbit D0         =   P1^0;    //1号继电器sbit D1         =   P1^1;    //2号继电器sbit D2         =   P1^6;    //3号继电器sbit D3         =   P3^7;    //4号继电器 // 功能标志位bitdecode_ok;    //解码成功bit rf_ok;      //收到有效数据bit study;       //学习标志bit jmnx;      //编码类型:0=2262,1=1527 uchar da1527; //解码临时数组uchar key_d;      //遥控器按键码uchar short_k;      //窄脉冲宽度uchar ss=0, sn=0, s=0, x=0;uint jk=0; // 存储10个遥控器(每个3字节,共30字节+1字节数量)uchar key_number; // 0号单元存储数量,1-30存储遥控器数据 // 1ms延时函数void delay_1ms(uint x)   {    uchar b,c;   for(x;x>0;x--)    {       for(b=3;b>0;b--)      {         for(c=150;c>0;c--);      }    }} // 简易延时void delay(uint ms){ while(ms--);} //================ EEPROM操作函数 ================void IAP_Disable(){    IAP_CONTR = 0;    IAP_CMD   = 0;    IAP_TRIG = 0;    IAP_ADDRH = 0;    IAP_ADDRL = 0;} uchar read_add(uint addr){    IAP_DATA =0x00;    IAP_CONTR =0x84;    IAP_CMD = 0x01;    IAP_ADDRH =addr>>8;    IAP_ADDRL =addr&0xff;    EA = 0;    IAP_TRIG =0x5a;    IAP_TRIG =0xa5;    _nop_();    EA = 1;    IAP_Disable();    returnIAP_DATA;} void write_add(uint addr, uchar ch){    IAP_CONTR =0x84;    IAP_CMD = 0x02;    IAP_ADDRH =addr>>8;    IAP_ADDRL =addr&0xff;    IAP_DATA = ch;    EA = 0;    IAP_TRIG =0x5a;    IAP_TRIG =0xa5;    _nop_();    EA = 1;    IAP_Disable();} void Sector_Erase(uint addr){    IAP_CONTR =0x84;    IAP_CMD = 0x03;    IAP_ADDRH =addr>>8;    IAP_ADDRL =addr&0xff;    EA = 0;    IAP_TRIG =0x5a;    IAP_TRIG =0xa5;    _nop_();    EA = 1;} //================ 接收解码函数 ================void RF_decode()   {     ucharii=0,j=0,k=0,rep=0;    uint head_k=0;    uchar s;           short_k=0;    while(RF&& j<250)    {       delay(1);          short_k++;    }     while(!RF)     {      delay(1);      head_k++;    }        if(((short_k*24)<head_k) && (head_k<(short_k*38)))       {       for(rep=0;rep<2;rep++)      {         for(ii=0;ii<3;ii++)            {               for(k=0;k<8;k++)                {                   j=0;                   while(RF && j<245)                    {                     delay(1);                     j++;                   }                   if(j>(short_k-short_k/2-short_k/3)&&j<(short_k*1.96))                    {                     da1527&=~(1<<((7-k)));                  }                                               else if(j>(short_k*1.96)&&j<(short_k*5))                     da1527|=(1<<(7-k));                       else {return;}                                      j=0;                   while(!RF && j<150){delay(2);j++;}                }            }         j=0;while(RF && (j<200)){delay(1);j++;}         head_k=0;while(!RF) {delay(1);head_k++;}         if((head_k<(short_k*26)) || (head_k>(short_k*38))){return;}      }              if((da1527==da1527) && (da1527==da1527)&& (da1527==da1527))      {            uchari,u;         rf_ok=1;         for(i=0;i<3;i++)            {               for(u=0;u<4;u++) {if(((da1527>>(u*2)) & 3)==2){i=80;break;}}               if(i==80) break;            }         if(i==80)// 1527            {               key_d=da1527 & 0x0f;               da1527=da1527>>4;               jmnx=1;            }         else      // 2262            {               key_d=0;               for(i=0;i<4;i++){if(((da1527>>(i*2))&3)==3)key_d|=1<<i;}               da1527=0x00;               jmnx=0;                jk++;//自锁用            }      }    } } //================ 遥控器学习函数 ================void key_buffer()      // 读取EEPROM到RAM{    uchar n;   for(n=0;n<31;n++)    {       key_number=read_add(0x0000+n);    }} void KEY_study()       // 学习新遥控器{       uint d_num;    if(study)    {      rf_ok=0;      d_num=0;        while(!rf_ok)      {         RF_decode();         d_num++;         if(d_num>50000) break;      }      d_num=0;       if(rf_ok==1)      {            ucharnum_rf = key_number;         if(num_rf>=10){num_rf=0;}// 最多存储10个         key_number=da1527;         key_number=da1527;         key_number=da1527;            key_number=num_rf+1;          Sector_Erase(0x0000);         for(num_rf=0;num_rf<31;num_rf++)            {               write_add(0x0000+num_rf, key_number);            }         rf_ok=0;         LED=1;// 学习成功      }          else      {         for(num_rf=0;num_rf<8;num_rf++)            {               LED=!LED;               delay_1ms(100);            }            LED=1;      }      study=0;    }} void system_res() // 系统清零{    Sector_Erase(0x0000);   write_add(0x0000, 0x00);    key_buffer();} void set_scan()   // 学习键扫描{     uchar h=0;    while(!set)       {      if(h>5)      {         study=1;            h=0;            LED=0;         while(!set)            {               delay_1ms(100);               h++;               if(h>80)                {                   study=0;                   h=0;                   system_res();                   LED=1;                   while(!set);                }            }      }       delay_1ms(100);      h++;    }    if(study)    {       KEY_study();    }} //================ 定时器配置 ================void ConfigTimer0(){    TMOD=0x01;    TH0=0XFC;// 1ms定时初值    TL0=0X66;    TR0=1;    ET0=1;    EA=1;} void timer0() interrupt 1{    TH0=0XFC;    TL0=0X66;       if(decode_ok)   // 解码有效信号    {      s--;      if(!s)      {            jk=0;         decode_ok=0;      }    }} //================ 继电器控制逻辑(一路遥控一路) ================void relay_control(){    if(!study)// 非学习状态    {      rf_ok=0;       for(x=0;x<10;x++)// 检查10个遥控器      {         if((da1527==key_number)&&            (da1527==key_number)&&            (da1527==key_number))            {                // 一路遥控控制一路继电器(取消互锁,简化逻辑)               if(key_d == 0x01) {D0=~D0;} // 按键1控制D0               if(key_d == 0x02) {D1=~D1;} // 按键2控制D1               if(key_d == 0x04) {D2=~D2;} // 按键4控制D2               if(key_d == 0x08) {D3=~D3;} // 按键8控制D3                               decode_ok=1;               ss=1;               sn=1;               s=30;               break;            }       }    }} void system_start()// 上电初始化{       AUXR=0xb5;// 配置辅助寄存器,根据STC8H特性可能需要调整       P1=0xff;    P3=0xff;    key_buffer();} void main(){     system_start();    ConfigTimer0();    LED=1;// 初始化学习指示灯        while(1)    {       RF_decode();// 读取信号波形分析       set_scan();   // 学习按键扫描       relay_control();// 继电器控制    }}

神农鼎 发表于 2025-5-29 09:23:33

EEPROM 的使用,IAP_TPS 必须设置





同频率,指令快了将近 1倍





阿飞7812 发表于 2025-5-28 09:45:53

根据上面上下二个程序   AUXR这个配置要改吗?要怎么改

ercircle 发表于 2025-5-28 10:43:34



这两型号AUXR寄存器看描述一样的。
15W


8H


代码功能问题建议按模块拆分,做函数级单元测试再组合测试。

ercircle 发表于 2025-5-28 10:49:03

用点灯、IO翻转或串口日志方式看下进没进KEY_study函数,卡在哪一步?
单独测RF_decode,能解码吗?

网老四 发表于 2025-5-28 11:16:22

8H系列单片机比15系列指令速度快,移植程序时候有软件延时之类跟时间相关的部分代码需要重新检查修正

阿飞7812 发表于 2025-5-28 11:46:22

ercircle 发表于 2025-5-28 10:49
用点灯、IO翻转或串口日志方式看下进没进KEY_study函数,卡在哪一步?
单独测RF_decode,能解码吗? ...

点灯,IO翻转我试了没问题

ercircle 发表于 2025-5-28 11:48:08

阿飞7812 发表于 2025-5-28 11:46
点灯,IO翻转我试了没问题

没进rf_ok==1条件?看下是不是上面说的d_num>50000对于8H解码时间太短了?

阿飞7812 发表于 2025-5-28 11:49:35

IO口我重新配置成普通IO口,不配置它IO还不能工作

ercircle 发表于 2025-5-28 20:07:14

楼主咋样了,找到问题没

阿飞7812 发表于 2025-5-29 09:11:17

ercircle 发表于 2025-5-28 20:07
楼主咋样了,找到问题没

没找到,头都大了
页: [1] 2
查看完整版本: 15W408AS程序移植到STC8H1K08出现的问题