找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2801|回复: 10
打印 上一主题 下一主题
收起左侧

STC12C5A60S2单片机万能学习红外遥控只差一步

  [复制链接]
回帖奖励 2 黑币 回复本帖可获得 2 黑币奖励! 每人限 1 次
跳转到指定楼层
楼主
本帖最后由 liyago 于 2021-8-25 10:25 编辑

在论坛翻了好多天资料,终于把这个完全克隆信号的万能红外遥控器搞清楚了,论坛有位老兄很早就发了那篇红外收发的帖子,后面又有位兄弟改写了那程序,我都下在板上试验了,只是我对信号的收发波形还没有完全理解,所以走了几天弯路,下图是一个红外灯的开灯原始波形



刚开始学习时我还以为学习后发送的波形应该跟原始波形是一样的,可搞了好多天都没发现能发出原始波形,最后没办法了去了某一个宝买了一块万能学习红外遥控板回来,一看它的发射波形是完全跟我自已这个stc12c5a60s2发射的一样啊



上面这个是专业商品波形,实际控制灯是有效的,下图是自已搭的板的波形



波形是不是也很完美,跟专业的一样,但问题来了,这个波形控制不了灯啊,一看问题出在哪了吗,两个波形相反了,这就是问题了,只要把这个波形倒转那问题就解决了,可是我看了半天没看出要怎么倒,是学习部份还是发射部份造成的都没搞清楚,怎么说我也是从C51到STM32走过的人,怎么回到这只有几行代码的51反而晕晕了,稀望各位大神大虾能指点迷津,搞清楚这一步下一步就可以搞记忆了。

弱弱地问一句,51单片机能复制得出原始波形一样的波形吗?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:88256 发表于 2021-8-23 08:29 | 只看该作者
也不是新注册的,程序也不发一个出来。
那些波形是接在哪里测试的?红外接收的波形是倒的,没信号是高电平,接收到信号输出低电平,遵循这一点再结合程序就知道是接收还是发射部分出错了。至于怎么倒,没有程序就没办法建议了。
回复

使用道具 举报

板凳
ID:95375 发表于 2021-8-23 11:13 | 只看该作者
hhdsdy 发表于 2021-8-23 08:29
也不是新注册的,程序也不发一个出来。
那些波形是接在哪里测试的?红外接收的波形是倒的,没信号是高电平 ...
  1. /********学习型遥控器程序*********/
  2. /*
  3.       该程序只对红外脉冲波形复制并不解码是真正的万能学习型,程序是根据论坛公开程序资料修改完成的,
  4. 对多种遥控都能学习包括:电视遥控,机顶盒遥控,空调遥控等....学习到的波形脉冲总宽度几乎一致.
  5.          
  6. 源码调试:风中有你  
  7. */

  8. #include"stc12c5a60s2.h"

  9. #include<intrins.h>   //延时函数
  10. #define uchar unsigned char
  11. #define uint unsigned int
  12. sbit studylamp=P1^6; //学习指示灯 7p
  13. sbit lamp=P1^7; //发射指示灯         8p
  14. sbit studykey=P3^3; //学习键  13p  ---
  15. sbit remotein=P3^6; //遥控信号输入口16p
  16. sbit remoteout=P3^5; //遥控信号输出口15p
  17. sbit txkey=P3^4; //发射键 14p               
  18. uint i,j,m=5000,n,k,s;
  19. uint  remotedata[207]; //存脉冲宽度数据用
  20. uint remdata; //脉冲计数
  21. bit tag;//学习标致

  22. /****1ms*t延时程序****/
  23. void delay1ms(uint t)
  24. {
  25.   for(i=0;i<t;i++)
  26.    for(j=0;j<120;j++)
  27.   ;
  28. }
  29. /****2us*t秒延时程序****/
  30. void Delay2us(uchar y)                //@12.000MHz
  31. {
  32.         unsigned char i;

  33.         i = 3*y;
  34.         while (--i);
  35. }


  36. void Timer1Init(void)                //38Khz@12.000MHz
  37. {


  38.   AUXR &= 0xBF;                //定时器时钟12T模式        1011 1111
  39.         TMOD |= 0x20;                //设置定时器模式 10 0000
  40.   TH1=0xf3;//38KHz初值
  41.   TL1=0xf3;


  42. }


  43. void clr_ram()
  44. {
  45.   for(i=0;i<207;i++)
  46.   {
  47.    remotedata[i]=0x00;
  48.   }  //清内存
  49. }

  50. /////////////////////
  51. /****初始化程序****/

  52. void clearmen(void)
  53. {
  54.   P3M1=0x40;        //P3.5强推P3.6高阻
  55.                                 //P3M0=00100000
  56.   P3M0=0x20;        //P3M1=01000000,
  57.   P1M1=        0x00;                //P1M0=00000001
  58.   P1M0=0x01;                    //P1M1=00000000
  59.   studylamp=1;//关学习指示灯
  60.   lamp=1;  //关发射指示灯
  61.   remoteout=0; //关遥控输出
  62.   remotein=1;  // 遥控输入置高电平
  63.   

  64.   IE=0x00;
  65.   IP=0x01;


  66.   Timer1Init();

  67.   EA=1; //开总中断
  68. clr_ram();


  69. }

  70. /*****发送键功能函数****/        
  71. void keywork(void)
  72. {


  73.   if (txkey==0)         //有按键按下
  74.     {
  75.            delay1ms(10);
  76.           while(txkey==0);//等待键释放
  77.          
  78.            n=0;
  79.            lamp=0;
  80.     while(1)   //开始发射调制波形
  81.     {



  82.      i=remotedata[n];
  83.           ET1=1;
  84.       TR1=1;  //开定时
  85.      while(i--)
  86.          {
  87.           Delay2us(2);
  88.         // _nop_();
  89.          }


  90.       ET1=0;
  91.       TR1=0;//不发送调制脉冲
  92.           remoteout=0; //关红外发射
  93.           n++;//下一组脉冲宽度地址
  94.           i=remotedata[n];
  95.          
  96.      while(i--)  //根据i值发送计时
  97.          {
  98.           Delay2us(2);
  99.          // _nop_();
  100.           }
  101.   
  102.                //等待该位时间结束
  103.       n++; //下一组脉冲宽度地址
  104.           if((remotedata[n]==0)||(n>206)){delay1ms(10);break;} //该位地址数据为0或地址计数大于设定值就结束
  105.     }  
  106.   }
  107.   lamp=1; //灭灯

  108. }

  109. /****40KHz载波发生函数*****/

  110. void time_intt(void)interrupt 3
  111. {
  112. remoteout=~remoteout;

  113. }


  114. //*********学习红外函数*************
  115. void studywork()
  116. {
  117.    while(studykey==0)//按键按下放
  118.    {

  119.     while(studykey==1);//等待键释放

  120.            studylamp=0;         //学习灯亮
  121.            lamp=1;
  122.            tag=1;        //学习标致置1
  123.        n=0;
  124.            remdata=0x00;//脉宽计数器清零

  125.    while(remotein==1);//等待遥控码输入

  126.    while(tag)
  127.     {
  128.   
  129.     while(remotein==0)//有遥控码输入

  130.       {

  131.            Delay2us(4);
  132.            


  133.      remdata++;        //记录低电平脉宽时间
  134.             if(remdata>m) //计数大于设定值退出
  135.           {remotedata[n]=0x00;
  136.             tag=0;
  137.                goto end;
  138.               }
  139.        }

  140.          
  141.     remotedata[n]=remdata;
  142.         remdata=0x00;//脉宽计数器清零
  143.    n++;//存低电平脉宽数据
  144.            if(n>206) //缓存满退出
  145.       {
  146.             remotedata[n]=0x00;
  147.         tag=0;
  148.             goto end;
  149.           }

  150.   while(remotein==1)
  151.   {
  152. Delay2us(4);


  153.   remdata++; //高电平计数
  154.    if(remdata>m) //计数大于设定值退出
  155.      {remotedata[n]=0x00;
  156.       tag=0;
  157.           goto end;
  158.         }
  159.   }


  160.   remotedata[n]=remdata; //存高电平脉宽数据
  161.   n++;
  162.        remdata=0x00;//脉宽计数器清零
  163. }
  164.   
  165.   }
  166.   end:
  167.   {
  168.       lamp=1;
  169.     studylamp=1;         //学习灯灭

  170.         }

  171. }
  172. /******主函数****/                                                                                                                                                                        
  173. void main()
  174. {  
  175.   
  176.   clearmen();

  177.             remoteout=0; //关红外发射
  178.             studylamp=0;         //学习灯灭

  179.             tag=0;
  180.                 studykey=1;


  181.   while(1)
  182.   {
  183.    keywork();        // 发射
  184.       studywork();        //学习

  185. }

  186. }
复制代码



这个程序是论坛里下的,只是把二级管改成了阴级导通,想不明白为什么原帖会用三级管控制LED,IO口加限流电阻控制LED应没问题吧,又不多。

所有波形都是在IO口测的
回复

使用道具 举报

地板
ID:88256 发表于 2021-8-24 10:18 | 只看该作者
你改了电路啊,原来是怎么控制的?用NPN的三极管?现在不用三极管又是怎么接的,可能就是出在更改上
回复

使用道具 举报

5#
ID:95375 发表于 2021-8-25 10:25 | 只看该作者
hhdsdy 发表于 2021-8-24 10:18
你改了电路啊,原来是怎么控制的?用NPN的三极管?现在不用三极管又是怎么接的,可能就是出在更改上



原来有两个提示用的LED是用三级管驱动的,我把它们去掉了,直接用IO口加限流电阻代替了,这跟波形没关系吧,大部份单片机都是这样接LED灯,除口IO口不够用了才加个控制片。

经过这两天研究,原来的波算是负波,而这个单片机发射的是正波,测试结果这也可以控制灯,但要贴很近了,不明原理,昨晚搞出了跟原始波形一样的纯线条波形,但好你去控制不了灯,奇怪,等把正波变负波先,论坛有负波的程序,研究看看再说。
回复

使用道具 举报

6#
ID:95375 发表于 2021-8-25 22:55 | 只看该作者
已经有结果了,想追求完美最后还是初完美打败。已经做出了跟原始波形一样的了,但就是不起做用,不明原因,反而是那填充了载波的长条图波形能正常遥控。

把程序里         remoteout=0; //关红外发射  变成         remoteout=1; //开红外发射  波形就从正波变成负波了。

  1.      i=remotedata[n];
  2.       ET1=1;
  3.       TR1=0;  //开定时
  4. 。。。。。。。。。。。
  5.       ET1=0;
  6.       TR1=1;//不发送调制脉冲
复制代码



然后把ET1和TR1改成上面的就可以出线条图而不是填充载波的长条图


整个代码如下,基本全注释了,能搞清楚这代码为什么不实用的大神请M我
  1. /********学习型遥控器程序*********/
  2. /*
  3.       该程序只对红外脉冲波形复制并不解码是真正的万能学习型,程序是根据论坛公开程序资料修改完成的,
  4. 对多种遥控都能学习包括:电视遥控,机顶盒遥控,空调遥控等....学习到的波形脉冲总宽度几乎一致.
  5.          
  6.                                                                                                                                                                                  源码调试:风中有你        2015.11.29
  7.                                                                                                                                                                                  
  8.                                                                                                                                                                                  
  9. 2021年8月25日  
  10. 改为低电平亮灯,芯片用STC8F1K08S2,波形跟原始波一样都是线条形,波形也是负波,但就是无效果

  11. */

  12. #include"stc8.h"

  13. #include<intrins.h>   //延时函数
  14. #define uchar unsigned char
  15. #define uint unsigned int
  16. sbit studylamp=P5^4; //学习指示灯
  17. sbit lamp=P1^1; //发射指示灯
  18. sbit studykey=P3^4; //学习键
  19. sbit txkey=P3^5; //发射键
  20. sbit remotein=P3^2; //遥控信号输入口 高阻
  21. sbit remoteout=P5^5; //遥控信号输出口 强推
  22. uint i,j,m=5000,n,k,s;
  23. uint  remotedata[207]; //存脉冲宽度数据用
  24. uint remdata; //脉冲计数
  25. bit tag;//学习状态标志

  26. /****1ms*t延时程序****/
  27. void delay1ms(uint t)
  28. {
  29.                 for(i=0;i<t;i++)
  30.                 for(j=0;j<120;j++)
  31.                 ;
  32. }
  33. /****2us*t秒延时程序****/
  34. void Delay2us(uchar y)                //@12.000MHz
  35. {
  36.                 unsigned char i;
  37.                 i = y;//数越大长度越短
  38.                 while (--i);
  39. }


  40. void Timer1Init(void)                //38Khz@12.000MHz
  41. {
  42.                 AUXR &= 0xBF;                //定时器时钟12T模式        1011 1111
  43.                 TMOD |= 0x20;                //设置定时器模式 10 0000
  44.                 TH1=0xf3;//38KHz初值
  45.                 TL1=0xf3;
  46. }


  47. void clr_ram()
  48. {
  49.                 for(i=0;i<207;i++)
  50.                 {
  51.                                 remotedata[i]=0x00;
  52.                 }  //清内存
  53. }

  54. /////////////////////
  55. /****初始化程序****/

  56. void clearmen(void)
  57. {
  58. // I/O 口特殊功能寄存器,这里不定义还好,定义后就不可用了,不明白
  59. //P3M0=0x04;        P3M1=0x00;//P3.2        红外输入 高阻
  60. //P5M0=0x00;        P5M1=0x20;//P5.5 红外输出 推挽输出
  61.         
  62. /*
  63. P0M0[1:0]        P0M1[1:0]
  64.         0                                        0                准双向口(传统8051 I/O口模式)灌电流可达20mA
  65.         0                                        1                推挽输出(强上拉输出,可达20mA,要加限流电阻)
  66.         1                                        0                仅为输入(高阻)
  67.         1                                        1                开漏(Open Drain),内部上拉电阻断开,要外加
  68. */        
  69.         
  70.         
  71.         
  72.                 studylamp=1;//关学习指示灯
  73.                 lamp=1;  //关发射指示灯
  74.                 remoteout=0; //关遥控输出
  75.                 remotein=1;  // 遥控输入置高电平

  76.                 IE=0x00;//IE是中端允许寄存器,这里面包括了定时器和外部中断还有EA等
  77.                 IP=0x01;//IP是中断优先级控制寄存器
  78.                 Timer1Init();
  79.                 EA=1; //开总中断
  80.                 clr_ram();
  81. }

  82. /*
  83. (IP.7:保留)
  84. (IP.6:保留)
  85. PT2(IP.5):若=1,定时器2中断设为高优先级(只适用于8052及其增强型)
  86. PS(IP.4):若=1,串行中断设为高优先级
  87. PT1(IP.3):若=1,定时器1中断设为高优先级
  88. PX1(IP.2):若=1,外部中断1设为高优先级
  89. PT0(IP.1):若=1,定时器0中断设为高优先级
  90. PX0(IP.0):若=1,外部中断0设为高优先级
  91. */

  92. /*****发送键功能函数****/        
  93. void keywork(void)
  94. {
  95.         if (txkey==0)         //如发射按键按下
  96.                 {
  97.                                 delay1ms(10);//延时10毫秒防抖
  98.                                 while(txkey==0);//等待发射键释放,释放后txkey==1,释放后才继续执行下去就是为了防止按键一按下就无数次循环了
  99.                                 n=0;//计数用
  100.                                 lamp=0;//学习灯亮
  101.                                 while(1)   //开始发射调制波形
  102.                                 {
  103.                                                 i=remotedata[n]; //把读到的数组数据第0个赋给i
  104.                                                 ET1=1;//开启T1中断 关闭也无波
  105.                                                 TR1=0;  //关闭定时器T1不发送调制脉冲
  106.                                                 while(i--)
  107.                                                 {
  108.                                                                 Delay2us(2);//延时2个2毫秒
  109.                                                                 _nop_();//单片机空跑一周期
  110.                                                                 _nop_();//单片机空跑一周期
  111.                                                 }
  112. /*
  113.                                                 方式1:上面的ET1=1 TR1=1 下面的ET1=0 TR1=0 出有色波,能遥控
  114.                                                 
  115.                                                 0001不出波
  116.                                                 0010不出波
  117.                                                 0011全黄,全输出载波,没得停了
  118.                                                 0100不出波
  119.                                                 0101不出波
  120.                                                 0110一直高电平
  121.                                                 0111全黄,全输出载波,没得停了
  122.                                                 1000不出波
  123.                                                 1001出跟原始波一样的线条波形,方向反,不能遥控
  124.                                                 1010不出波
  125.                                                 1011全黄
  126.                                                 1100出有色波,能遥控
  127.                                                 1101出有色波,能遥控
  128.                                                 1110也有色波但跟方式1有点不一样,在遥控码中部有一上电平线,能遥控
  129.                                                 1111全黄
  130. */                                                
  131.                                                 
  132.                                                 ET1=0;//关闭T1中断
  133.                                                 TR1=1;//开启定时器T1发送调制脉冲  TR1=0且上面那个TR1=1时波形有填充色且能遥控,灯充满电遥控较远,
  134.                                                                         //TR1=1且上面的TR1=0时波形跟原始波一样无填充色,但不能遥控
  135.                                                 remoteout=1; //关红外发射
  136.                                                 n++;//下一组脉冲宽度地址
  137.                                                 i=remotedata[n]; //把读到的数组数据第n个赋给i
  138.                                                 while(i--)  //根据i值发送计时
  139.                                                 {
  140.                                                                 Delay2us(2);//延时2个2毫秒
  141.                                                                 _nop_();//单片机空跑一周期
  142.                                                                 _nop_();//单片机空跑一周期
  143.                                                 }
  144.                                                 //等待该位时间结束
  145.                                                 n++; //下一组脉冲宽度地址
  146.                                                 if((remotedata[n]==0)||(n>206))//如果数值为0了或超过了206个//该位地址数据为0或地址计数大于设定值就结束
  147.                                                 {
  148.                                                                 delay1ms(10);//延时10毫秒
  149.                                                                 break;//结束退出
  150.                                                 }
  151.                         
  152.                                 }  
  153.                 }
  154.                 lamp=1; //灭灯
  155. }



  156. /****40KHz载波发生函数*****/

  157. void time_intt(void)interrupt 3        //定时器1
  158. {
  159.                 remoteout=~remoteout;
  160. }

  161. /*
  162. 外部中断0 interrupt 0
  163. 定时器0     interrupt 1
  164. 外部中断1 interrupt 2
  165. 定时器1     interrupt 3
  166. 串口中断   interrupt 4
  167. 定时器2     interrupt 5
  168. */




  169. //*********学习红外函数*************
  170. void studywork()
  171. {
  172.                 while(studykey==0)//按键按下放
  173.                 {
  174.                                 while(studykey==1);//等待键释放
  175.                                 studylamp=0;         //学习灯亮
  176.                                 lamp=1;//发射灯灭
  177.                                 tag=1;        //学习标致置1
  178.                                 n=0;
  179.                                 remdata=0x00;//脉宽计数器清零
  180.                                 while(remotein==1);//等待遥控码输入
  181.                                 while(tag)//当tag是1在学习状态就一直循环
  182.                                 {
  183.                                                 while(remotein==0)//当低电平时有遥控码输入
  184.                                                 {
  185.                                                                 Delay2us(4);//延时4个2微秒
  186.                                                                 remdata++;        //记录低电平脉宽时间
  187.                                                                 if(remdata>m) //计数大于设定值退出  m设为5000,这个值不懂怎么来的,设为255只有一条竖线
  188.                                                                 {
  189.                                                                                 remotedata[n]=0x00; //肪冲宽度置0
  190.                                                                                 tag=0;//学习标志置0,结束学习
  191.                                                                                 goto end;//跳到结束
  192.                                                                 }
  193.                                                 }
  194.                                                 remotedata[n]=remdata;//如果低电平肪宽时间remdata不大于5000就把值赋给脉冲宽度数组remotedata[n],就是说这个值有效吧记录下来
  195.                                                 remdata=0x00;//脉宽计数器清零
  196.                                                 n++;//电平脉宽数据个数加1
  197.                                                 if(n>206) //缓存满退出,remotedata[n]设为最大207
  198.                                                 {
  199.                                                                 remotedata[n]=0x00;//一组数是206,大于就清0
  200.                                                                 tag=0;//学习标志置0,结束学习
  201.                                                                 goto end;//跳到结束,两灯都灭了
  202.                                                 }
  203.                                                 while(remotein==1)//当高电平时无遥控码输入
  204.                                                 {
  205.                                                                 Delay2us(4);//延时4个2微秒
  206.                                                                 remdata++; //高电平计数
  207.                                                                 if(remdata>m) //计数大于设定值退出  m设为5000,这个值不懂怎么来的,设为255只有一条竖线
  208.                                                                 {               
  209.                                                                                 remotedata[n]=0x00; //肪冲宽度置0
  210.                                                                                 tag=0;//学习标志置0,结束学习
  211.                                                                                 goto end;//跳到结束,两灯都灭了
  212.                                                                 }
  213.                                                 }
  214.                                                 remotedata[n]=remdata; //存高电平脉宽数据
  215.                                                 remdata=0x00;//脉宽计数器清零
  216.                                                 n++;//电平脉宽数据个数加1
  217.                                 }
  218.                 }
  219.                 end:
  220.                 {//学习结束
  221.                                 lamp=1;//发射灯灭
  222.                                 studylamp=1;         //学习灯灭
  223.                 }
  224. }
  225. /******主函数****/                                                                                                                                                                        
  226. void main()
  227. {  
  228.                 clearmen();
  229.                 remoteout=0; //关红外发射
  230.                 studylamp=0;         //学习灯灭
  231.                 tag=0;
  232.                 studykey=1;
  233.                 while(1)
  234.                 {
  235.                                 keywork();        // 发射
  236.                                 studywork();        //学习
  237.                 }
  238. }
复制代码

回复

使用道具 举报

7#
ID:742998 发表于 2022-9-16 22:27 | 只看该作者
liyago 发表于 2021-8-25 22:55
已经有结果了,想追求完美最后还是初完美打败。已经做出了跟原始波形一样的了,但就是不起做用,不明原因, ...

你好,问题弄清楚了吗?
回复

使用道具 举报

8#
ID:1045007 发表于 2022-9-17 05:47 | 只看该作者
不错,新手多多指教
回复

使用道具 举报

9#
ID:695401 发表于 2022-11-7 00:44 | 只看该作者
三极管倒向应该可以吧
回复

使用道具 举报

10#
ID:195496 发表于 2022-11-7 07:21 | 只看该作者
你的图上有三个二极管,哪一个是红外发射用的,
回复

使用道具 举报

11#
ID:965189 发表于 2022-11-7 11:00 | 只看该作者
三极管有放大并倒相的作用。
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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