找回密码
 立即注册

QQ登录

只需一步,快速开始

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

真正的万能红外学习与发射 单片机程序

  [复制链接]
跳转到指定楼层
楼主
无需外围38KHZ晶振,STC8H系列芯片按道理都能用,万能接受,万能发射,EEPROM存储数据,暂时只能存一个码,串口输出信息,按下遥控器按键,发送02可显示刚刚收到的信息并保存,发送10可发射刚刚保存的数据,本人新手,程序有些乱,但有注释,因为刚刚做出来所以并不完善,还请大佬多多指教!
红外发射接P11,接受接P20。
原始波形:


经过学以后发射的波形:


单片机源程序如下:
  1. #include "stc8H.h"
  2. #include "intrins.h"
  3. #include <stdio.h>
  4. #include "uart.h"
  5. #include "eeprom.h"
  6. #include "launch.h"


  7. extern  char ch;

  8. int ir1  = 0x0400;
  9. unsigned short xdata captures[VAL] = {0},eep_captures[VAL] = {0}; //缓存数组
  10. static unsigned int num = 0; //一共接受了几个脉冲
  11. unsigned int two_num;
  12. static unsigned int Overflow = 0; //溢出次数
  13. static unsigned char val; //接收超时变量


  14. void Timer0_Init(void)        //1毫秒@24.000MHz,定时器0
  15. {
  16.     AUXR |= 0x80;
  17.     TMOD &= 0xF0;            //设置定时器模式
  18. //    TL0 = 0x90;                //设置定时初始值
  19. //    TH0 = 0xE8;                //设置定时初始值
  20.    
  21.         TL0 = 0x40;                //设置定时初始值
  22.     TH0 = 0xA2;                //设置定时初始值
  23.    
  24.     TF0 = 0;                //清除TF0标志
  25.     TR0 = 1;                //定时器0开始计时
  26.     ET0 = 1;
  27. }

  28. void IR() //初始化
  29. {
  30.     P1M0 = 0x00;
  31.     P1M1 = 0x00;
  32.     P3M0 = 0x00;
  33.     P3M1 = 0x00;
  34.     P5M0 = 0x00;
  35.     P5M1 = 0x00;
  36.     P_SW2 = 0x80;

  37.     PWM1_PS = 0x05;

  38.     //(CC1捕获TI1上升沿,CC2捕获TI1下降沿)
  39.     PWMA_CCER1 = 0x00;
  40.     PWMA_CCMR1 = 0x01;                          //CC1为输入模式,且映射到TI1FP1上
  41.     PWMA_CCMR2 = 0x02;                          //CC2为输入模式,且映射到TI1FP2上
  42.     PWMA_CCER1 = 0x11;                          //使能CC1/CC2上的捕获功能
  43.     PWMA_CCER1 |= 0x00;                         //设置捕获极性为CC1的上升沿
  44.     PWMA_CCER1 |= 0x20;                         //设置捕获极性为CC2的下降沿
  45.    
  46.     PWMA_CR1 = 0x01;
  47.    
  48.         PWMA_PSCR = 0x09;
  49.         
  50.     PWMA_IER = 0x04;                            //使能CC2捕获中断
  51.         PWMA_IER |= 0x02;                            //使能CC1捕获中断
  52.     EA = 1;
  53. }




  54. void PWMA_ISR() interrupt 26 //PWM沿触发中断
  55. {
  56.     unsigned int cnt_l;
  57.         unsigned int cnt_h;
  58.    

  59.     if (PWMA_SR1 & 0x02)
  60.     {
  61.         PWMA_SR1 &= ~0x02;
  62.         cnt_l = (PWMA_CCR1 - PWMA_CCR2)/24;            //差值即为低电平宽度  cnt/时钟频率 = 脉宽(us)   
  63.                 captures[num++] = cnt_l;
  64.     }
  65.         
  66.          

  67.     if (PWMA_SR1 & 0x04)
  68.     {
  69.         PWMA_SR1 &= ~0x04;
  70.         cnt_h = (PWMA_CCR2 - PWMA_CCR1)/24;            //差值即为高电平宽度
  71.                 captures[num++] = cnt_h;
  72.     }
  73. }

  74. void TM0_Isr() interrupt 1 //定时器0中断用来判断脉冲接受是否超时,大于30ms为超时
  75. {   
  76.     if(P20 == 1)
  77.     {
  78.         val++;
  79.         if(val > 30)
  80.         {
  81.             Overflow = 1;
  82.             val = 0;
  83.         }
  84.     }else {val = 0;Overflow = 0;}
  85. }


  86. void UartReceiveHandler() interrupt 4 {
  87.     if (RI) {              // 接收中断
  88.         RI = 0;            // 清除接收标志位
  89.         ch = SBUF;    // 读取接收到的数据
  90.         //UartSend(ch);      // 原样返回接收到的数据
  91.     }
  92. }

  93. void TM3_Isr() interrupt 19 //定时器3中断发生38K载波
  94. {
  95.     P11 = !P11;                                 //红外1端口
  96. }



  97. //---------------------------------------------------------------------------------------------
  98. void main()
  99. {
  100.     unsigned int i = 0,a = 0;
  101.    
  102.    
  103.    
  104.     Timer0_Init();
  105.     Timer3_Init();
  106.     UartInit();
  107.     IR();
  108.   
  109.   UartSendString("Starting\r\n");
  110.     lach1 = 1;
  111.     while(1)
  112.     {
  113.         //lach1 = 1;
  114.             if(Overflow == 1 && ch == 0x02)//如果超时溢出,并且接收到0x02
  115.             {
  116.                 EraseUIntFromEEPROM(0x0400);
  117.                 EraseUIntFromEEPROM(0x0600);
  118.                 delays(5);               
  119.                 EraseUIntFromEEPROM(0x0000);
  120.                 delays(5);
  121.                 for(i = 0; i <= num; i++)
  122.                 {
  123.                     SaveUIntToEEPROM(ir1+i*2, captures[i]); //写入eeprom
  124.                     //SaveUIntToEEPROM(ir1+i*2, '3'); //写入eeprom
  125.                     UartSendUint(captures[i]);//打印保存到数组里的数据
  126.                     captures[i] = 0;
  127.                     delays(1);
  128.                 }
  129.                 SaveUIntToEEPROM(0x0000, num); //将脉冲个数写入eeprom
  130.                     UartSendString("End\r\n"); /*End结束*/
  131.                     UartSendUint(num);
  132.                     ir1 = 0x0400;
  133.                     ch = 0;
  134.                     num = 0;
  135.                     Overflow = 0;
  136.                     PWMA_IER = 0; //关闭PWM中断使能
  137.                     ET0 = 0;    //关闭定时器0中断
  138.             }else if(P20 == 0 && Overflow==0){
  139.                 PWMA_IER = 0x06; //打开PWM中断使能
  140.                 ET0 = 1; //打开定时器0中断
  141.             }
  142.             
  143.             
  144.             if(ch == 0x01)
  145.             {
  146.                 two_num = ReadUIntFromEEPROM(0x0000);
  147.                     for(a = 0;a<=two_num;a++) //读取红外接收数组
  148.                     {
  149.                         eep_captures[a] = ReadUIntFromEEPROM(ir1+a*2);
  150.                         UartSendUint(eep_captures[a]);//打印保存到数组里的数据
  151.                         delays(1);
  152.                     }
  153.                     UartSendUint(two_num);
  154.                     ir1 = 0x0400;
  155.                     two_num = 0;
  156.                     ch = 0x00;
  157.             }
  158.             if(ch == 0x10)
  159.             {
  160.                 two_num = ReadUIntFromEEPROM(0x0000);
  161.                 for(a = 0;a<=two_num;a++) //读取红外接收数组
  162.                     {
  163.                         eep_captures[a] = ReadUIntFromEEPROM(ir1+a*2);
  164.                         UartSendUint(eep_captures[a]);//打印保存到数组里的数据
  165.                         delays(1);
  166.                     }
  167.                 Launch_1(eep_captures,two_num);
  168.                 ch = 0;
  169.             }

  170.             
  171.     }
  172. }
  173. 单片机源程序如下:
  174. [code]#include "stc8H.h"
  175. #include "intrins.h"
  176. #include <stdio.h>
  177. #include "uart.h"
  178. #include "eeprom.h"
  179. #include "launch.h"


  180. extern  char ch;

  181. int ir1  = 0x0400;
  182. unsigned short xdata captures[VAL] = {0},eep_captures[VAL] = {0}; //缓存数组
  183. static unsigned int num = 0; //一共接受了几个脉冲
  184. unsigned int two_num;
  185. static unsigned int Overflow = 0; //溢出次数
  186. static unsigned char val; //接收超时变量


  187. void Timer0_Init(void)                //1毫秒@24.000MHz,定时器0
  188. {
  189.         AUXR |= 0x80;
  190.         TMOD &= 0xF0;                        //设置定时器模式
  191. //        TL0 = 0x90;                                //设置定时初始值
  192. //        TH0 = 0xE8;                                //设置定时初始值
  193.         
  194.                 TL0 = 0x40;                                //设置定时初始值
  195.         TH0 = 0xA2;                                //设置定时初始值
  196.         
  197.         TF0 = 0;                                //清除TF0标志
  198.         TR0 = 1;                                //定时器0开始计时
  199.         ET0 = 1;
  200. }

  201. void IR() //初始化
  202. {
  203.     P1M0 = 0x00;
  204.     P1M1 = 0x00;
  205.     P3M0 = 0x00;
  206.     P3M1 = 0x00;
  207.     P5M0 = 0x00;
  208.     P5M1 = 0x00;
  209.     P_SW2 = 0x80;

  210.     PWM1_PS = 0x05;

  211.     //(CC1捕获TI1上升沿,CC2捕获TI1下降沿)
  212.     PWMA_CCER1 = 0x00;
  213.     PWMA_CCMR1 = 0x01;                          //CC1为输入模式,且映射到TI1FP1上
  214.     PWMA_CCMR2 = 0x02;                          //CC2为输入模式,且映射到TI1FP2上
  215.     PWMA_CCER1 = 0x11;                          //使能CC1/CC2上的捕获功能
  216.     PWMA_CCER1 |= 0x00;                         //设置捕获极性为CC1的上升沿
  217.     PWMA_CCER1 |= 0x20;                         //设置捕获极性为CC2的下降沿
  218.         
  219.     PWMA_CR1 = 0x01;
  220.         
  221.                 PWMA_PSCR = 0x09;
  222.                
  223.     PWMA_IER = 0x04;                            //使能CC2捕获中断
  224.                 PWMA_IER |= 0x02;                            //使能CC1捕获中断
  225.     EA = 1;
  226. }




  227. void PWMA_ISR() interrupt 26 //PWM沿触发中断
  228. {
  229.     unsigned int cnt_l;
  230.                 unsigned int cnt_h;
  231.         

  232.     if (PWMA_SR1 & 0x02)
  233.     {
  234.         PWMA_SR1 &= ~0x02;
  235.         cnt_l = (PWMA_CCR1 - PWMA_CCR2)/24;            //差值即为低电平宽度  cnt/时钟频率 = 脉宽(us)        
  236.                                 captures[num++] = cnt_l;
  237.     }
  238.                
  239.                  

  240.     if (PWMA_SR1 & 0x04)
  241.     {
  242.         PWMA_SR1 &= ~0x04;
  243.         cnt_h = (PWMA_CCR2 - PWMA_CCR1)/24;            //差值即为高电平宽度
  244.                                 captures[num++] = cnt_h;
  245.     }
  246. }

  247. void TM0_Isr() interrupt 1 //定时器0中断用来判断脉冲接受是否超时,大于30ms为超时
  248. {        
  249.         if(P20 == 1)
  250.         {
  251.                 val++;
  252.                 if(val > 30)
  253.                 {
  254.                         Overflow = 1;
  255.                         val = 0;
  256.                 }
  257.         }else {val = 0;Overflow = 0;}
  258. }


  259. void UartReceiveHandler() interrupt 4 {
  260.     if (RI) {              // 接收中断
  261.         RI = 0;            // 清除接收标志位
  262.         ch = SBUF;    // 读取接收到的数据
  263.         //UartSend(ch);      // 原样返回接收到的数据
  264.     }
  265. }

  266. void TM3_Isr() interrupt 19 //定时器3中断发生38K载波
  267. {
  268.     P11 = !P11;                                 //红外1端口
  269. }



  270. //---------------------------------------------------------------------------------------------
  271. void main()
  272. {
  273.         unsigned int i = 0,a = 0;
  274.         
  275.         
  276.         
  277.         Timer0_Init();
  278.         Timer3_Init();
  279.         UartInit();
  280.         IR();
  281.   
  282.   UartSendString("Starting\r\n");
  283.         lach1 = 1;
  284.         while(1)
  285.         {
  286.                 //lach1 = 1;
  287.                         if(Overflow == 1 && ch == 0x02)//如果超时溢出,并且接收到0x02
  288.                         {
  289.                                 EraseUIntFromEEPROM(0x0400);
  290.                                 EraseUIntFromEEPROM(0x0600);
  291.                                 delays(5);                                
  292.                                 EraseUIntFromEEPROM(0x0000);
  293.                                 delays(5);
  294.                                 for(i = 0; i <= num; i++)
  295.                                 {
  296.                                         SaveUIntToEEPROM(ir1+i*2, captures[i]); //写入eeprom
  297.                                         //SaveUIntToEEPROM(ir1+i*2, '3'); //写入eeprom
  298.                                         UartSendUint(captures[i]);//打印保存到数组里的数据
  299.                                         captures[i] = 0;
  300.                                         delays(1);
  301.                                 }
  302.                                 SaveUIntToEEPROM(0x0000, num); //将脉冲个数写入eeprom
  303.                                         UartSendString("End\r\n"); /*End结束*/
  304.                                         UartSendUint(num);
  305.                                         ir1 = 0x0400;
  306.                                         ch = 0;
  307.                                         num = 0;
  308.                                         Overflow = 0;
  309.                                         PWMA_IER = 0; //关闭PWM中断使能
  310.                                         ET0 = 0;    //关闭定时器0中断
  311.                         }else if(P20 == 0 && Overflow==0){
  312.                                 PWMA_IER = 0x06; //打开PWM中断使能
  313.                                 ET0 = 1; //打开定时器0中断
  314.                         }
  315.                         
  316.                         
  317.                         if(ch == 0x01)
  318.                         {
  319.                                 two_num = ReadUIntFromEEPROM(0x0000);
  320.                                         for(a = 0;a<=two_num;a++) //读取红外接收数组
  321.                                         {
  322.                                                 eep_captures[a] = ReadUIntFromEEPROM(ir1+a*2);
  323.                                                 UartSendUint(eep_captures[a]);//打印保存到数组里的数据
  324.                                                 delays(1);
  325.                                         }
  326.                                         UartSendUint(two_num);
  327.                                         ir1 = 0x0400;
  328.                                         two_num = 0;
  329.                                         ch = 0x00;
  330.                         }
  331.                         if(ch == 0x10)
  332.                         {
  333.                                 two_num = ReadUIntFromEEPROM(0x0000);
  334.                                 for(a = 0;a<=two_num;a++) //读取红外接收数组
  335.                                         {
  336.                                                 eep_captures[a] = ReadUIntFromEEPROM(ir1+a*2);
  337.                                                 UartSendUint(eep_captures[a]);//打印保存到数组里的数据
  338.                                                 delays(1);
  339.                                         }
  340.                                 Launch_1(eep_captures,two_num);
  341.                                 ch = 0;
  342.                         }

  343.                         
  344.         }
  345. }
复制代码


原理图:无
仿真:无
程序: 8路红外.zip (125.01 KB, 下载次数: 53)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏15 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:433219 发表于 2023-8-9 16:32 | 只看该作者
,发送02可显  --->pc上,stc-isp软件 向mcu串口发送???
回复

使用道具 举报

板凳
ID:276663 发表于 2023-8-9 17:41 | 只看该作者
实物靓照呢
回复

使用道具 举报

地板
ID:773929 发表于 2023-8-10 08:43 | 只看该作者
wkman 发表于 2023-8-9 16:32
,发送02可显  --->pc上,stc-isp软件 向mcu串口发送???

向mcu发
回复

使用道具 举报

5#
ID:773929 发表于 2023-8-10 08:47 | 只看该作者

才刚调好一路,板子焊接的烂,没好意思发

cab83b072fab2423c70208daf7d3588.jpg (91.58 KB, 下载次数: 54)

cab83b072fab2423c70208daf7d3588.jpg
回复

使用道具 举报

6#
ID:276663 发表于 2023-8-10 11:06 | 只看该作者
范莉萍 发表于 2023-8-10 08:47
才刚调好一路,板子焊接的烂,没好意思发

现在学习型遥控器只要一个发射灯就能实现学习了,有没有搞清楚原理
回复

使用道具 举报

7#
ID:773929 发表于 2023-8-10 11:50 | 只看该作者
IdeaMing 发表于 2023-8-10 11:06
现在学习型遥控器只要一个发射灯就能实现学习了,有没有搞清楚原理

8路发射对应的是8个位置,比如八间屋子
回复

使用道具 举报

8#
ID:256970 发表于 2023-8-10 14:45 | 只看该作者
IdeaMing 发表于 2023-8-10 11:06
现在学习型遥控器只要一个发射灯就能实现学习了,有没有搞清楚原理

发射头是可以接收的,只是接收到的信号较弱,只能近距离接收
回复

使用道具 举报

9#
ID:773929 发表于 2023-8-10 15:36 | 只看该作者
蓝色海阳 发表于 2023-8-10 14:45
发射头是可以接收的,只是接收到的信号较弱,只能近距离接收

啊?这么吊
回复

使用道具 举报

10#
ID:1099505 发表于 2024-3-12 07:24 | 只看该作者
真不错,学习了。
回复

使用道具 举报

11#
ID:235438 发表于 2024-3-20 00:21 | 只看该作者
我都用定时器来做,还不会用捕获,代码收了,回头试试看
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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