找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3931|回复: 3
收起左侧

51单片机38k红外解码程序与制作

[复制链接]
ID:499469 发表于 2019-6-8 20:49 | 显示全部楼层 |阅读模式
上次大神指点后做了一些改进显示16位16进制的数据,二进制就是64位。频率是38k的。空调,电视,风扇,只要是家电的红外95%以上都可以解码,如果解码空调,建议每次使用前复位一次,清空数组的程序一直写失败,大神可以来改一下。另外发现部分手机(测试荣耀9)打开相机的时候会触发中断,让数据变得不正常。

制作出来的实物图如下:
微信图片_20190608204008.jpg

单片机源程序如下:
  1. /*********************************************************************************************
  2. 程序名:    DHT11-1602
  3. 编写人:    fby
  4. 硬件支持:  STC89C52RC  DHT11  LCD1602
  5. 接口说明:  DHT11:VCC DATA NC GND
  6. *********************************************************************************************
  7. 说明:1、单片机是STC89C52RC,晶振频率11.0592MHz,实验成功。
  8.           2、好东西要共享,大家随意折腾~~
  9. *********************************************************************************************/
  10. #include<reg51.h>
  11. #include<intrins.h>
  12. #include<stdio.h>


  13. #define uchar unsigned char        //无符号字符型类型数据
  14. #define uint unsigned int //无符号整型数据
  15.         #define ulong unsigned long //无符号整型数据
  16.         #define xiao float //xiaoshu
  17. #define IODATA  P0
  18. unsigned char IrValue[24]; //接收收据
  19. unsigned char Time;

  20. sbit RS=P2^6; //定义rs端口
  21. sbit RW=P2^5; //定义rw端口
  22. sbit E=P2^7;
  23.        
  24. sbit IRIN=P3^2;//红外数据io

  25.              
  26. /*******************************************************************************
  27. * 函数名         : DelayMs()
  28. * 函数功能                   : 延时
  29. * 输入           : x
  30. * 输出                  : 无
  31. *******************************************************************************/

  32. void DelayMs(unsigned int x)   //0.14ms误差 0us
  33. {
  34. unsigned char i;
  35.   while(x--)
  36. {
  37.   for (i = 0; i<13; i++)
  38. {}
  39. }
  40. }
  41. /*******************************************************************************
  42. * 函数名         : IrInit()
  43. * 函数功能                   : 初始化红外线接收
  44. * 输入           : 无
  45. * 输出                  : 无
  46. *******************************************************************************/

  47. void IrInit()
  48. {
  49.         IT0=1;//下降沿触发
  50.         EX0=1;//打开中断0允许
  51.         EA=1;        //打开总中断

  52.         IRIN=1;//初始化端口
  53.        
  54. }
  55. /*******************************************************************************
  56. * 函数名         : ReadIr()
  57. * 函数功能                   : 读取红外数值的中断函数
  58. * 输入           : 无
  59. * 输出                  : 无
  60. *******************************************************************************/
  61.    //数据处理

  62. void sjcl()
  63. {
  64.                 IrValue[8]=IrValue[0]>>4;                          //高位  用户码
  65.                 IrValue[9]=IrValue[0]&0x0f;                //低位       

  66.     IrValue[10]=IrValue[1]>>4;                          //高位   用户反码
  67.                 IrValue[11]=IrValue[1]&0x0f;                //低位       

  68.     IrValue[12]=IrValue[2]>>4;                          //高位   数据码
  69.                 IrValue[13]=IrValue[2]&0x0f;                //低位

  70.     IrValue[14]=IrValue[3]>>4;                          //高位  数据反码
  71.                 IrValue[15]=IrValue[3]&0x0f;                //低位       
  72.        
  73.           IrValue[16]=IrValue[4]>>4;                          //高位  数据反码
  74.                 IrValue[17]=IrValue[4]&0x0f;                //低位       

  75.           IrValue[18]=IrValue[5]>>4;                          //高位  数据反码
  76.                 IrValue[19]=IrValue[5]&0x0f;                //低位       

  77.           IrValue[20]=IrValue[6]>>4;                          //高位  数据反码
  78.                 IrValue[21]=IrValue[6]&0x0f;                //低位       

  79.           IrValue[22]=IrValue[7]>>4;                          //高位  数据反码
  80.                 IrValue[23]=IrValue[7]&0x0f;                //低位       


  81. }

  82. void ReadIr() interrupt 0
  83. {
  84.        
  85.         unsigned char j,k;
  86.         unsigned int err;
  87.        
  88.        
  89.         Time=0;                                         
  90.         DelayMs(70);

  91.         if(IRIN==0)                //确认是否真的接收到正确的信号
  92.         {         
  93.                
  94.           
  95.                 err=1000;                                //1000*10us=10ms,超过说明接收到错误的信号
  96.                 /*当两个条件都为真是循环,如果有一个条件为假的时候跳出循环,免得程序出错的时
  97.                 侯,程序死在这里*/       
  98.                 while((IRIN==0)&&(err>0))        //等待前面9ms的低电平过去                 
  99.                 {       
  100.                  
  101.                         DelayMs(1);
  102.                         err--;
  103.                 }
  104.                 if(IRIN==1)                        //如果正确等到9ms低电平
  105.                 {
  106.                        
  107.                         err=500;
  108.                         while((IRIN==1)&&(err>0))                 //等待4.5ms的起始高电平过去
  109.                         {
  110.                                
  111.                                 DelayMs(1);
  112.                                 err--;
  113.                         }
  114.                         for(k=0;k<8;k++)                //共有8组数据
  115.                         {                               
  116.                                 for(j=0;j<8;j++)        //接收一组数据
  117.                                 {

  118.                                         err=60;               
  119.                                         while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去
  120. //                                        while (!IRIN)
  121.                                         {
  122.                                                 DelayMs(1);
  123.                                                 err--;
  124.                                         }
  125.                                         err=500;
  126.                                         while((IRIN==1)&&(err>0))         //计算高电平的时间长度。
  127.                                         {
  128.                                                 DelayMs(1);//0.14ms
  129.                                                 Time++;
  130.                                                 err--;
  131.                                                 if(Time>30)
  132.                                                 {
  133.                                                         EX0=1;
  134.                                                         return;
  135.                                                 }
  136.                                         }
  137.                                         IrValue[k]>>=1;         //k表示第几组数据
  138.                                         if(Time>=8)                        //如果高电平出现大于565us,那么是1
  139.                                         {
  140.                                                 IrValue[k]|=0x80;
  141.                                         }
  142.                                         Time=0;                //用完时间要重新赋值                                                       
  143.                                 }
  144.                         }
  145.                 }
  146.                
  147.                         return;
  148.                
  149.         }       
  150.        sjcl();  //数据处理       
  151. }



  152.        

  153. /*********************************************************************************************
  154. 函数名:延时函数
  155. 调  用:Delay30us();/Delay20ms();/Delay1s();
  156. 参  数:无
  157. 返回值:无
  158. 结  果:延时相应时间
  159. 备  注:振荡晶体为11.0592MHz(所有延时函数Copy自STC-ISP(v6.85).exe)
  160. **********************************************************************************************/
  161. void Delay30us()                //@11.0592MHz-40
  162. {
  163.         unsigned char i;

  164.         i = 11;
  165.         while (--i);
  166. }


  167. void Delay20ms()                //@11.0592MHz
  168. {
  169.         unsigned char i, j;

  170.         i = 36;
  171.         j = 217;
  172.         do
  173.         {
  174.                 while (--j);
  175.         } while (--i);
  176. }


  177. void Delay1s()                //@11.0592MHz
  178. {
  179.         unsigned char i, j, k;

  180.         _nop_();
  181.         i = 8;
  182.         j = 1;
  183.         k = 243;
  184.         do
  185.         {
  186.                 do
  187.                 {
  188.                         while (--k);
  189.                 } while (--j);
  190.         } while (--i);
  191. }





  192. /********************************************************************
  193. * 名称 : bit Busy(void)
  194. * 功能 : 这个是一个读状态函数,读出函数是否处在忙状态
  195. * 输入 : 输入的命令值
  196. * 输出 : 无
  197. ***********************************************************************/
  198. void Busy(void)
  199. {
  200. bit busy_flag = 1;
  201. IODATA  = 0xff;
  202. RS = 0;          //指令关
  203. Delay30us();
  204. RW = 1;          //读状态
  205. Delay30us();
  206. E = 1;        //使能高电平
  207. while(1)
  208. {
  209. busy_flag = (bit)(IODATA  & 0x80); //强制取最高位
  210. if(busy_flag == 0)
  211. {
  212. break;
  213. }
  214. }
  215. E = 0;           //E 1->0,rs=0,rw=1,
  216.            //将数据寄存器内的数据读到DB0~DB7,分别将状态标志BF和地址计数器(AC)内容读到DB7和DB6~DB0。

  217. }

  218. /********************************************************************
  219. * 名称 : lcd1602_write_cmd(uchar del)
  220. * 功能 : 1602命令函数
  221. * 输入 : 输入的命令值
  222. * 输出 : 无
  223. ***********************************************************************/
  224. void lcd1602_write_cmd(uchar del)
  225. {
  226. RS = 0;
  227. Delay30us();
  228. RW = 0;
  229. Delay30us();
  230. E = 0;
  231. Delay30us();
  232. IODATA  = del;
  233. Delay30us();
  234. E = 1;
  235. Delay30us();
  236. E = 0;                        //E 1->0,rs=0,rw=0, 将指令代码写入指令寄存器中
  237. }

  238. /********************************************************************
  239. * 名称 : lcd1602_write_data(uchar del)
  240. * 功能 : 1602写数据函数
  241. * 输入 : 需要写入1602的数据
  242. * 输出 : 无
  243. ***********************************************************************/

  244. void lcd1602_write_data(uchar del)
  245. {
  246. Busy();      
  247. Delay30us();
  248. RS = 1;
  249. Delay30us();
  250. RW = 0;
  251. Delay30us();
  252. E = 0;
  253. Delay30us();
  254. IODATA  = del;
  255. Delay30us();
  256. E = 1;
  257. Delay30us();
  258. E = 0;                          //E 1->0,rs=1,rw=0, 数据写入数据寄存器中
  259. }

  260. /********************************************************************
  261. * 名称 : lcd1602_init()
  262. * 功能 : 1602初始化,请参考1602的资料
  263. * 输入 : 无
  264. * 输出 : 无
  265. ***********************************************************************/
  266. void lcd1602_init(void)
  267. {
  268. Delay20ms();
  269. lcd1602_write_cmd(0x38);         //8位数据,双列,5*7字形
  270. Delay20ms();
  271. lcd1602_write_cmd(0x38);
  272. Delay20ms();
  273. lcd1602_write_cmd(0x38);
  274. Busy();
  275. lcd1602_write_cmd(0x08);// 只开显示
  276. Busy();   
  277. lcd1602_write_cmd(0x01);        //清屏
  278. Busy();
  279. lcd1602_write_cmd(0x06);//显示地址递增,即写一个数据后,显示位置右移一位
  280. Busy();
  281. lcd1602_write_cmd(0x0c);        //开启显示屏,关光标,光标不闪烁
  282. }

  283. /********************************************************************
  284. * 名称 : lcd1602_char(uchar hang,uchar lie,char sign)
  285. * 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下
  286. L1602_char(1,5,'b')
  287. * 输入 : 行,列,需要输入1602的数据
  288. * 输出 : 无
  289. ***********************************************************************/
  290. void lcd1602_char(uchar hang,uchar lie,char sign)
  291. {
  292. uchar a;
  293. if(hang == 1)
  294. {
  295. a = 0x80;
  296. }
  297. if(hang == 2)
  298. {
  299. a = 0xc0;
  300. }
  301. a = a + lie - 1;
  302. Busy();
  303. lcd1602_write_cmd(a);  //置数据存贮器地址
  304. Busy();
  305. lcd1602_write_data(sign);
  306. }




  307. /********************************************************************
  308. * 名称 : lcd1602_string(uchar hang,uchar lie,uchar *p)
  309. * 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
  310. L1602_string(1,5,"ab cd ef;")
  311. * 输入 : 行,列,需要输入1602的数据
  312. * 输出 : 无
  313. ***********************************************************************/

  314. void lcd1602_string(uchar hang,uchar lie,uchar *p)
  315. {
  316. uchar a;
  317. if(hang == 1)
  318. {
  319. a = 0x80;
  320. }
  321. if(hang == 2)
  322. {
  323. a = 0xc0;
  324. }
  325. a = a + lie - 1;
  326. while(1)
  327. {
  328. Busy();
  329. lcd1602_write_cmd(a);
  330. Busy();
  331. lcd1602_write_data(*p);
  332. a++;
  333. p++;   
  334. if((*p == '\0')||(a==0x90)||(a==0xd0)) //字符结束或每行最后一个字符
  335. {
  336. break;
  337. }
  338. }
  339. }




  340. /*********************************************************************************************
  341. 函数名:主函数
  342. 调  用:无
  343. 参  数:无
  344. 返回值:无
  345. 结  果:读DHT11数据并送到1602显示
  346. 备  注:
  347. **********************************************************************************************/
  348. void main (void)
  349. {
  350.     unsigned char k;
  351.        Delay20ms();
  352.         lcd1602_init();         //LCD初始化
  353.               IrInit();             //红外初始化
  354.                
  355.         while(1)
  356.         {
  357.                                        
  358.       
  359.                         //LcdWriteData(0x37+IrValue[4]);        //将数值转换为该显示的ASCII码
  360.                         //LcdWriteData(IrValue[4]+0x30);        //将数值转换为该显示的ASCII码
  361.      
  362.       lcd1602_string(1,1,"HWJM:");
  363.         for(k=0;k<16;k++)
  364.                         {
  365.                 if(IrValue[k+8]>9)
  366.                                                                 {
  367.                 lcd1602_char(2,k+1,IrValue[k+8]+0x37);
  368.                 }
  369.                                  else
  370.                            {
  371.                                  lcd1602_char(2,k+1,IrValue[k+8]+0x30);
  372.                                   }

  373.       

  374. }
  375. }
  376. }
  377.                                
  378.                                
复制代码

所有资料51hei提供下载:
红外解码.zip (57.38 KB, 下载次数: 50)

评分

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

查看全部评分

回复

使用道具 举报

ID:499469 发表于 2019-6-8 20:50 | 显示全部楼层
后面为0的是没有数据,可以不用看
回复

使用道具 举报

ID:558095 发表于 2019-6-9 17:02 | 显示全部楼层
虽然看不懂,还是默默点个赞
回复

使用道具 举报

ID:796012 发表于 2023-3-2 15:16 | 显示全部楼层
我试了我只风扇遥控器,按同样的键,每次显示的码都不一样
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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