圣源电子制作

 找回密码
 立即注册
查看: 6676|回复: 2

红外线解码程序+仿真文件(可定义任意I/O作接收脚,支持长/短按,自适应主频6MHz~40MH

[复制链接]
发表于 2011-11-25 21:56:42 | 显示全部楼层 |阅读模式
转载自互联网!!!



0673d52fc931c140349bf7d9.jpg
  1. //*********************【 NEC解码头文件 】*******************
  2. //
  3. // 简介:本程序适用于NCE解码:(9ms+4.5ms)引导码+32位编码。
  4. // 兼容STC所有型号(包括 1T 和 12T 系列),可以定义任意I/O作红外接收脚,
  5. // 自适应解码主频:6MHz ~ 40MHz。
  6. //
  7. // 使用条件:占用系统定时器0,开启定时器0中断(如使用其它定时器请自改IR_Init();初始化函数)
  8. //
  9. // 使用说明:填相关宏定义:USER_H、USER_L、Check_EN、CPU_Fosc、IR,
  10. // 上电初始化函数IR_Init(),
  11. // 在定时器0中断中调用IR_NEC()解码函数,
  12. // 解码有效时,IR_BT=2即短按,IR_BT=3即长按,由用户清0,
  13. // 解码存放:用户码高8位NEC[0],用户码低8位NEC[1],操作码NEC[2],操作码反码NEC[3]。
  14. //
  15. //【供用户调用的函数】
  16. // IR_Init(); //接收初始化,开启定时器0中断400us
  17. // IR_NEC(); //红外线解码(解NEC编码)
  18. //
  19. //***************************************************************/
  20. #ifndef __IR_NEC_H__
  21. #define __IR_NEC_H__


  22. //【用户必填项:USER_H、USER_L、Check_EN、CPU_Fosc、IR】
  23. #define USER_H 0x80 //用户码高8位
  24. #define USER_L 0x7F //用户码低8位
  25. #define Check_EN 0 //是否要校验16位用户码:不校验填0,校验则填1
  26. #define CPU_Fosc 12000000L //输入主频,自适应解码(单位:Hz,范围:6MHz ~ 40MHz)
  27. #define CA_S 8 //长按时间设置,单位:108mS(即 108mS整数倍,10倍以上为宜)

  28. sbit IR = P3^6; //红外线接口(任意引脚)

  29. #define Step 400 //红外采样步长:400us
  30. #define TH_H ((65536-Step*(CPU_Fosc/300)/40000)/256) //定时器高8位基准赋值
  31. #define TH_L ((65536-Step*(CPU_Fosc/300)/40000)%256) //定时器低8位基准赋值

  32. uint8 IR_BT; //解码效果返回:0无效,1有效,2短按,3长按
  33. uint8 NEC[4]; //解码存放:16位用户码、操作码正反码
  34. uint8 cntCA; //长按计数
  35. uint16 cntStep; //步数计
  36. bit IRa,IRb; //接收脚电位状态保存
  37. bit IRsync; //同步标志
  38. uint8 BitN; //位码装载数


  39. /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
  40. 函数:红外线解码初始化
  41. ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
  42. void IR_Init()
  43. {
  44. TMOD &= 0xF0; //清定时器0
  45. TMOD |= 0x01; //定时器0:16位定时器
  46. TL0 = TH_L; //每步时间
  47. TH0 = TH_H;
  48. ET0 = 1;
  49. EA = 1;
  50. TR0 = 1;
  51. }

  52. /*┈┈┈┈┈┈┈┈┈┈ 基准 ┈┈┈┈┈┈┈┈┈┈┈*/
  53. #define Boot_Limit ((9000+4500 +1000)/Step) //引导码周期上限
  54. #define Boot_Lower ((9000+4500 -1000)/Step) //引导码周期下限
  55. #define Bit1_Limit ((2250 +800)/Step) //“1”周期上限
  56. #define Bit0_Limit ((1125 +400)/Step) //“0”周期上限
  57. /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
  58. 函数:红外线NEC周期采样解码法(定时中断,下降沿查询周期时间)
  59. 全局变量:IR_BT = 0无效
  60. 1有效,待继续判断长、短按(如不需要判断长、短按,则直接使用)
  61. 2短按
  62. 3长按
  63. ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
  64. void IR_NEC()
  65. {
  66. TL0 = TH_L; //重赋值
  67. TH0 = TH_H;

  68. IRb = IRa; //保存上次电位状态
  69. IRa = IR;   //保存当前电位状态
  70. cntStep++; //步数累加
  71. if(IR_BT==1)if(cntStep>300)IR_BT=2; //解码有效后,如果无长按,120ms(400us×300)后默认短按

  72. if(IRb && !IRa) //是否下降沿(上次高,当前低)
  73. {
  74. if(cntStep > Boot_Limit) //超过同步时间?
  75. {
  76. if(IR_BT==1)if(++cntCA>CA_S)IR_BT=3; //解码有效后,继续按住遥控>CA_S即长按
  77. IRsync=0; //同步位清0
  78. }
  79. else if(cntStep > Boot_Lower){ IRsync=1; BitN=32; } //同步位置1,装载位码数32
  80. else if(IRsync) //如果已同步
  81. {
  82. if(cntStep > Bit1_Limit)IRsync=0;
  83. else
  84. {
  85. NEC[3] >>= 1;
  86. if(cntStep > Bit0_Limit)NEC[3] |= 0x80; //“0”与“1”
  87. if(--BitN == 0)
  88. {
  89. IRsync = 0; //同步位清0

  90. #if (Check_EN == 1)
  91. if((NEC[0]==USER_H)&&(NEC[1]==USER_L)&&(NEC[2]==~NEC[3])) //校验16位用户码、操作码正反码
  92. { IR_BT=1; cntCA=0; } //解码有效,接下来判断:短按?长按?
  93. #else
  94. if(NEC[2]==~NEC[3]){ IR_BT=1; cntCA=0; } //只校验操作码正反码
  95. #endif
  96. }
  97. else if((BitN & 0x07)== 0) //NEC[3]每装满8位,移动保存一次(即 BitN%8 == 0)
  98. { NEC[0]=NEC[1]; NEC[1]=NEC[2]; NEC[2]=NEC[3]; }
  99. }
  100. }
  101. cntStep = 0; //步数计清0
  102. }
  103. }

  104. //取消相关宏定义
  105. #undef CPU_Fosc

  106. #endif





  107. 主程序
  108. #include "INCSTC89C52RC.H"
  109. #include "INCMY_SET.H"
  110. #include "INCIR_NEC.H" //调用NEC解码头文件

  111. sfr SE = 0x80; //数码管段选 P0:0x80 P1:0x90
  112. sbit WX1 = P2^0; //数码管位显
  113. sbit WX2 = P2^1;
  114. sbit WX3 = P2^2;
  115. sbit WX4 = P2^3;
  116. sbit WX5 = P2^4;
  117. sbit WX6 = P2^5;
  118. sbit WX7 = P2^6;
  119. sbit WX8 = P2^7;

  120. uint8c tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0X88,0X83,0XC6,0XA1,0X86,0X8E,0xFF};
  121. uint8 Xn,X1,X2,X3,X4,X5,X6;

  122. void KZ0(); //短按处理
  123. void KZ1(); //长按处理


  124. /***************** 主函数 ********************/
  125. void main(void)
  126. {
  127. IR_Init(); //红外线解码初始化

  128. while(1)
  129. {
  130. //遥控检测
  131. if((IR_BT==2)||(IR_BT==3))
  132. {
  133. if(IR_BT==2)KZ0(); //短按处理
  134. else KZ1(); //长按处理
  135. IR_BT =0; //清有效标志

  136. X1 = NEC[0]/16; //更新显示
  137. X2 = NEC[0]%16;
  138. X3 = NEC[1]/16;
  139. X4 = NEC[1]%16;
  140. X5 = NEC[2]/16;
  141. X6 = NEC[2]%16;
  142. }

  143. }

  144. }
  145. /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
  146. 函数:遥控短按处理
  147. ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
  148. void KZ0()
  149. {
  150. switch(NEC[2])
  151. {
  152. case 0x12: P10 = !P10; break;
  153. case 0x05: break;
  154. case 0x1E: break;
  155. case 0x55: break;

  156. case 0x01: break;
  157. case 0x1B: break;
  158. case 0x03: break;
  159. case 0x6B: break;

  160. case 0x07: break;
  161. case 0x08: break;
  162. case 0x09: break;
  163. case 0x68: break;

  164. case 0x22: break;
  165. case 0xE6: break;
  166. case 0x33: break;
  167. case 0xE2: break;
  168. default:break;
  169. }
  170. }
  171. /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
  172. 函数:遥控长按处理
  173. ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
  174. void KZ1()
  175. {
  176. switch(NEC[2])
  177. {
  178. case 0x12: P14 = !P14; break;
  179. case 0x05: break;
  180. case 0x1E: break;
  181. case 0x55: break;

  182. case 0x01: break;
  183. case 0x1B: break;
  184. case 0x03: break;
  185. case 0x6B: break;

  186. case 0x07: break;
  187. case 0x08: break;
  188. case 0x09: break;
  189. case 0x68: break;

  190. case 0x22: break;
  191. case 0xE6: break;
  192. case 0x33: break;
  193. case 0xE2: break;
  194. default:break;
  195. }
  196. }
  197. /*********************数码管扫描*************************/
  198. void XS(void)
  199. {
  200. if(++Xn > 7)Xn=0;
  201. switch(Xn)
  202. {
  203. case 0: WX8=1; NOP; //屏蔽上个位显
  204. SE=tab[X1]; //送段码
  205. WX1=0; //开位显
  206. break;
  207. case 1: WX1=1; NOP; SE=tab[X2]; WX2=0; break;
  208. case 2: WX2=1; NOP; SE=tab[X3]; WX3=0; break;
  209. case 3: WX3=1; NOP; SE=tab[X4]; WX4=0; break;
  210. case 4: WX4=1; NOP; SE=tab[16]; WX5=0; break;
  211. case 5: WX5=1; NOP; SE=tab[16]; WX6=0; break;
  212. case 6: WX6=1; NOP; SE=tab[X5]; WX7=0; break;
  213. case 7: WX7=1; NOP; SE=tab[X6]; WX8=0; break;
  214. default:break;
  215. }
  216. }

  217. /********************** 定时器0中断函数************************/
  218. void time0(void) interrupt 1
  219. {
  220. IR_NEC();
  221. XS();
  222. }
复制代码

源程序+仿真
syyyd.com-00.rar (110.81 KB, 下载次数: 104)

回复

使用道具 举报

发表于 2012-8-20 22:04:45 | 显示全部楼层
谢谢  学习一下
回复 支持 反对

使用道具 举报

发表于 2012-11-17 15:24:32 | 显示全部楼层
哈 谢谢啦 !谢谢分享
回复 支持 反对

使用道具 举报

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

本版积分规则

QQ|手机版|联系我们|闽公网安备 35012102000020号|圣源电子 ( 闽ICP备11020110号 )

GMT+8, 2019-4-21 00:46 , Processed in 0.067651 second(s), 20 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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