请选择 进入手机版 | 继续访问电脑版

930电子网

 找回密码
 立即注册
快捷导航
搜索
艾克姆科技推出最新产品STM32F103ZET6开发板
查看: 1934|回复: 4

哪位大神有红外遥控编码的例子,求分享,谢谢!!!

[复制链接]

2

主题

2

帖子

28

积分

新手上路

Rank: 1

积分
28
发表于 2018-3-9 13:36:26 | 显示全部楼层 |阅读模式
配套资料只有解码的例子,我想做一个用单片机编写红外遥控的编码实验,然后来模拟红外发送和接收。谢谢!
回复

使用道具 举报

94

主题

240

帖子

6482

积分

版主

Rank: 7Rank: 7Rank: 7

积分
6482
发表于 2018-3-9 17:45:37 | 显示全部楼层
帮顶
回复

使用道具 举报

1

主题

6

帖子

270

积分

中级会员

Rank: 3Rank: 3

积分
270
发表于 2019-6-16 20:09:00 | 显示全部楼层
我给你来个程序试试

  1. /* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序        */
  2. /*---------------------------------------------------------------------*/

  3. /*************  本程序功能说明  **************

  4. 用户可以在宏定义中改变MCU主时钟频率. 范围 8MHZ ~ 33MHZ.
  5. 红外接收程序。模拟市场上用量最大的NEC的编码。
  6. 用户可以在宏定义中指定用户码.
  7. 使用PCA2高速输出产生38KHZ载波, 1/3占空比, 每个38KHZ周期发射管发射9us,关闭16.3us.
  8. 使用开发板上的16个IO扫描按键, MCU不睡眠, 连续扫描按键.
  9. 当键按下, 第一帧为数据, 后面的帧为重复争,不带数据, 具体定义请自行参考NEC的编码资料.
  10. 键释放后, 停止发送.
  11. ******************************************/
  12. #include    "reg51.h"
  13. #include    "intrins.h"

  14. #define     MAIN_Fosc       11059200L   //定义主时钟
  15. typedef     unsigned char   u8;
  16. typedef     unsigned int    u16;
  17. typedef     unsigned long   u32;

  18. sfr TH2  = 0xD6;
  19. sfr TL2  = 0xD7;
  20. sfr IE2   = 0xAF;
  21. sfr INT_CLKO = 0x8F;
  22. sfr AUXR = 0x8E;
  23. sfr AUXR1 = 0xA2;
  24. sfr P_SW1 = 0xA2;
  25. sfr P_SW2 = 0xBA;
  26. sfr S2CON = 0x9A;
  27. sfr S2BUF = 0x9B;

  28. sfr ADC_CONTR = 0xBC;   //带AD系列
  29. sfr ADC_RES   = 0xBD;   //带AD系列
  30. sfr ADC_RESL  = 0xBE;   //带AD系列
  31. sfr P1ASF = 0x9D;   //只写,模拟输入(AD或LVD)选择

  32. sfr CCON = 0xD8;    //
  33. sbit CCF0  = CCON^0;    //PCA 模块0中断标志,由硬件置位,必须由软件清0。
  34. sbit CCF1  = CCON^1;    //PCA 模块1中断标志,由硬件置位,必须由软件清0。
  35. sbit CCF2  = CCON^2;    //PCA 模块2中断标志,由硬件置位,必须由软件清0。
  36. sbit CR    = CCON^6;    //1: 允许PCA计数器计数,必须由软件清0。
  37. sbit CF    = CCON^7;    //PCA计数器溢出(CH,CL由FFFFH变为0000H)标志。PCA计数器溢出后由硬件置位,必须由软件清0。
  38. sfr CMOD = 0xD9;    //
  39. sfr CCAPM0 = 0xDA;  //PCA模块0的工作模式寄存器。
  40. sfr CCAPM1 = 0xDB;  //PCA模块1的工作模式寄存器。
  41. sfr CCAPM2 = 0xDC;  //PCA模块2的工作模式寄存器。
  42. sfr CL     = 0xE9;  //
  43. sfr CCAP0L = 0xEA;  //PCA模块0的捕捉/比较寄存器低8位。
  44. sfr CCAP1L = 0xEB;  //PCA模块1的捕捉/比较寄存器低8位。
  45. sfr CCAP2L = 0xEC;  //PCA模块2的捕捉/比较寄存器低8位。
  46. sfr CH     = 0xF9;
  47. sfr CCAP0H = 0xFA;      //PCA模块0的捕捉/比较寄存器高8位。
  48. sfr CCAP1H = 0xFB;      //PCA模块1的捕捉/比较寄存器高8位。
  49. sfr CCAP2H = 0xFC;      //PCA模块2的捕捉/比较寄存器高8位。
  50. sfr PCA_PWM0 = 0xF2;    //PCA模块0 PWM寄存器。
  51. sfr PCA_PWM1 = 0xF3;    //PCA模块1 PWM寄存器。
  52. sfr PCA_PWM2 = 0xF4;    //PCA模块2 PWM寄存器。

  53. sbit PPCA   = IP^7;

  54. sfr P4   = 0xC0;
  55. sfr P5   = 0xC8;
  56. sfr P6   = 0xE8;
  57. sfr P7   = 0xF8;
  58. sfr P1M1 = 0x91;    //PxM1.n,PxM0.n     =00--->Standard,    01--->push-pull
  59. sfr P1M0 = 0x92;    //                  =10--->pure input,  11--->open drain
  60. sfr P0M1 = 0x93;
  61. sfr P0M0 = 0x94;
  62. sfr P2M1 = 0x95;
  63. sfr P2M0 = 0x96;
  64. sfr P3M1 = 0xB1;
  65. sfr P3M0 = 0xB2;
  66. sfr P4M1 = 0xB3;
  67. sfr P4M0 = 0xB4;
  68. sfr P5M1 = 0xC9;
  69. sfr P5M0 = 0xCA;
  70. sfr P6M1 = 0xCB;
  71. sfr P6M0 = 0xCC;
  72. sfr P7M1 = 0xE1;
  73. sfr P7M0 = 0xE2;

  74. sbit P00 = P0^0;
  75. sbit P01 = P0^1;
  76. sbit P02 = P0^2;
  77. sbit P03 = P0^3;
  78. sbit P04 = P0^4;
  79. sbit P05 = P0^5;
  80. sbit P06 = P0^6;
  81. sbit P07 = P0^7;
  82. sbit P10 = P1^0;
  83. sbit P11 = P1^1;
  84. sbit P12 = P1^2;
  85. sbit P13 = P1^3;
  86. sbit P14 = P1^4;
  87. sbit P15 = P1^5;
  88. sbit P16 = P1^6;
  89. sbit P17 = P1^7;
  90. sbit P20 = P2^0;
  91. sbit P21 = P2^1;
  92. sbit P22 = P2^2;
  93. sbit P23 = P2^3;
  94. sbit P24 = P2^4;
  95. sbit P25 = P2^5;
  96. sbit P26 = P2^6;
  97. sbit P27 = P2^7;
  98. sbit P30 = P3^0;
  99. sbit P31 = P3^1;
  100. sbit P32 = P3^2;
  101. sbit P33 = P3^3;
  102. sbit P34 = P3^4;
  103. sbit P35 = P3^5;
  104. sbit P36 = P3^6;
  105. sbit P37 = P3^7;
  106. sbit P40 = P4^0;
  107. sbit P41 = P4^1;
  108. sbit P42 = P4^2;
  109. sbit P43 = P4^3;
  110. sbit P44 = P4^4;
  111. sbit P45 = P4^5;
  112. sbit P46 = P4^6;
  113. sbit P47 = P4^7;
  114. sbit P50 = P5^0;
  115. sbit P51 = P5^1;
  116. sbit P52 = P5^2;
  117. sbit P53 = P5^3;
  118. sbit P54 = P5^4;
  119. sbit P55 = P5^5;
  120. sbit P56 = P5^6;
  121. sbit P57 = P5^7;


  122. /*************  红外发送相关变量    **************/
  123. #define User_code   0xFF00      //定义红外用户码

  124. sbit    P_IR_TX   = P3^7;   //定义红外发送端口

  125. u16     PCA_Timer2; //PCA2软件定时器变量
  126. bit     B_Space;    //发送空闲(延时)标志
  127. u16     tx_cnt;     //发送或空闲的脉冲计数(等于38KHZ的脉冲数,对应时间), 红外频率为38KHZ, 周期26.3us
  128. u8      TxTime;     //发送时间


  129. /*************  IO口定义    **************/
  130. sbit    P_HC595_SER   = P4^0;   //pin 14    SER     data input
  131. sbit    P_HC595_RCLK  = P5^4;   //pin 12    RCLk    store (latch) clock
  132. sbit    P_HC595_SRCLK = P4^3;   //pin 11    SRCLK   Shift data clock

  133. /*************  IO键盘变量声明  **************/
  134. u8  IO_KeyState, IO_KeyState1, IO_KeyHoldCnt;   //行列键盘变量
  135. u8  KeyHoldCnt; //键按下计时
  136. u8  KeyCode;    //给用户使用的键码, 1~16有效

  137. /*************  本地函数声明    **************/
  138. void    delay_ms(u8 ms);
  139. void    DisableHC595(void);
  140. void    IO_KeyScan(void);
  141. void    PCA_config(void);
  142. void    IR_TxPulse(u16 pulse);
  143. void    IR_TxSpace(u16 pulse);
  144. void    IR_TxByte(u8 dat);

  145. /******* 主函数 *********/
  146. void main(void)
  147. {
  148.     P0M1 = 0;   P0M0 = 0;   //设置为准双向口
  149.     P1M1 = 0;   P1M0 = 0;   //设置为准双向口
  150.     P2M1 = 0;   P2M0 = 0;   //设置为准双向口
  151.     P3M1 = 0;   P3M0 = 0;   //设置为准双向口
  152.     P4M1 = 0;   P4M0 = 0;   //设置为准双向口
  153.     P5M1 = 0;   P5M0 = 0;   //设置为准双向口
  154.     P6M1 = 0;   P6M0 = 0;   //设置为准双向口
  155.     P7M1 = 0;   P7M0 = 0;   //设置为准双向口
  156.    
  157.     PCA_config();
  158.    
  159.     EA = 1;                     //打开总中断
  160.    
  161.     DisableHC595();     //禁止掉学习板上的HC595显示,省电

  162.     while(1)
  163.     {
  164.         delay_ms(30);       //30ms
  165.         IO_KeyScan();

  166.         if(KeyCode != 0)        //检测到键码
  167.         {
  168.             TxTime = 0;
  169.                                 //一帧数据最小长度 = 9 + 4.5 + 0.5625 + 24 * 1.125 + 8 * 2.25 = 59.0625 ms
  170.                                 //一帧数据最大长度 = 9 + 4.5 + 0.5625 + 8 * 1.125 + 24 * 2.25 = 77.0625 ms
  171.             IR_TxPulse(342);    //对应9ms,同步头       9ms
  172.             IR_TxSpace(171);    //对应4.5ms,同步头间隔 4.5ms
  173.             IR_TxPulse(21);     //开始发送数据          0.5625ms

  174.             IR_TxByte(User_code%256);   //发用户码高字节
  175.             IR_TxByte(User_code/256);   //发用户码低字节
  176.             IR_TxByte(KeyCode);         //发数据
  177.             IR_TxByte(~KeyCode);        //发数据反码
  178.             
  179.             if(TxTime < 56)     //一帧按最大77ms发送, 不够的话,补偿时间     108ms
  180.             {
  181.                 TxTime = 56 - TxTime;
  182.                 TxTime = TxTime + TxTime / 8;
  183.                 delay_ms(TxTime);
  184.             }
  185.             delay_ms(31);

  186.             while(IO_KeyState != 0) //键未释放
  187.             {
  188.                 IR_TxPulse(342);    //对应9ms,   同步头        9ms
  189.                 IR_TxSpace(86);     //对应2.25ms,同步头间隔    2.25ms
  190.                 IR_TxPulse(21);     //开始发送数据              0.5625ms
  191.                 delay_ms(96);
  192.                 IO_KeyScan();
  193.             }
  194.             KeyCode = 0;
  195.         }
  196.     }
  197. }
  198. /*************/

  199. //==============
  200. // 函数: void  delay_ms(unsigned char ms)
  201. // 描述: 延时函数。
  202. // 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
  203. // 返回: none.
  204. // 版本: VER1.0
  205. // 日期: 2013-4-1
  206. // 备注:
  207. //===================
  208. void  delay_ms(u8 ms)
  209. {
  210.      u16 i;
  211.      do{
  212.           i = MAIN_Fosc / 13000;
  213.           while(--i)    ;   //13T per loop
  214.      }while(--ms);
  215. }

  216. void DisableHC595(void)
  217. {      
  218.     u8  i;
  219.     P_HC595_SER   = 1;
  220.     for(i=0; i<20; i++)
  221.     {
  222.         P_HC595_SRCLK = 1;
  223.         P_HC595_SRCLK = 0;
  224.     }
  225.     P_HC595_RCLK = 1;
  226.     P_HC595_RCLK = 0;                           //锁存输出数据
  227.     P_HC595_RCLK = 1;
  228.     P_HC595_RCLK = 0;                           //锁存输出数据
  229. }
  230. /************************
  231.     行列键扫描程序
  232.     使用XY查找4x4键的方法,只能单键,速度快

  233.    Y     P04      P05      P06      P07
  234.           |        |        |        |
  235. X         |        |        |        |
  236. P00 ---- K00 ---- K01 ---- K02 ---- K03 ----
  237.           |        |        |        |
  238. P01 ---- K04 ---- K05 ---- K06 ---- K07 ----
  239.           |        |        |        |
  240. P02 ---- K08 ---- K09 ---- K10 ---- K11 ----
  241.           |        |        |        |
  242. P03 ---- K12 ---- K13 ---- K14 ---- K15 ----
  243.           |        |        |        |
  244. ****************************/


  245. u8 code T_KeyTable[16] = {0,1,2,0,3,0,0,0,4,0,0,0,0,0,0,0};

  246. void IO_KeyDelay(void)
  247. {
  248.     u8 i;
  249.     i = 60;
  250.     while(--i)  ;
  251. }

  252. void    IO_KeyScan(void)    //50ms call
  253. {
  254.     u8  j;

  255.     j = IO_KeyState1;   //保存上一次状态

  256.     P0 = 0xf0;  //X低,读Y
  257.     IO_KeyDelay();
  258.     IO_KeyState1 = P0 & 0xf0;

  259.     P0 = 0x0f;  //Y低,读X
  260.     IO_KeyDelay();
  261.     IO_KeyState1 |= (P0 & 0x0f);
  262.     IO_KeyState1 ^= 0xff;   //取反
  263.    
  264.     if(j == IO_KeyState1)   //连续两次读相等
  265.     {
  266.         j = IO_KeyState;
  267.         IO_KeyState = IO_KeyState1;
  268.         if(IO_KeyState != 0)    //有键按下
  269.         {
  270.             F0 = 0;
  271.             if(j == 0)  F0 = 1; //第一次按下
  272.             else if(j == IO_KeyState)
  273.             {
  274.                 if(++IO_KeyHoldCnt >= 20)   //1秒后重键
  275.                 {
  276.                     IO_KeyHoldCnt = 18;
  277.                     F0 = 1;
  278.                 }
  279.             }
  280.             if(F0)
  281.             {
  282.                 j = T_KeyTable[IO_KeyState >> 4];
  283.                 if((j != 0) && (T_KeyTable[IO_KeyState& 0x0f] != 0))
  284.                     KeyCode = (j - 1) * 4 + T_KeyTable[IO_KeyState & 0x0f] + 16;    //计算键码,17~32
  285.             }
  286.         }
  287.         else    IO_KeyHoldCnt = 0;
  288.     }
  289.     P0 = 0xff;
  290. }
  291. /************* 发送脉冲函数 **************/
  292. void    IR_TxPulse(u16 pulse)
  293. {
  294.     tx_cnt = pulse;
  295.     B_Space = 0;    //发脉冲
  296.     CCAPM2 = 0x48 | 0x04 | 0x01;    //工作模式 0x00: PCA_Mode_Capture,  0x42: PCA_Mode_PWM,  0x48: PCA_Mode_SoftTimer
  297.     CR = 1;     //启动
  298.     while(CR);
  299. }

复制代码
回复 支持 反对

使用道具 举报

1

主题

6

帖子

270

积分

中级会员

Rank: 3Rank: 3

积分
270
发表于 2019-6-16 20:11:06 | 显示全部楼层

  1. /************* 发送空闲函数 **************/
  2. void    IR_TxSpace(u16 pulse)
  3. {
  4.     tx_cnt = pulse;
  5.     B_Space = 1;    //空闲
  6.     CCAPM2 = 0x48 | 0x01;   //工作模式 0x00: PCA_Mode_Capture,  0x42: PCA_Mode_PWM,  0x48: PCA_Mode_SoftTimer
  7.     CR = 1;     //启动
  8.     while(CR);
  9. }

  10. /************* 发送一个字节函数 **************/
  11. void    IR_TxByte(u8 dat)
  12. {
  13.     u8 i;
  14.     for(i=0; i<8; i++)
  15.     {
  16.         if(dat & 1)     IR_TxSpace(63), TxTime += 2;    //数据1对应 1.6875 + 0.5625 ms
  17.         else            IR_TxSpace(21), TxTime++;       //数据0对应 0.5625 + 0.5625 ms
  18.         IR_TxPulse(21);         //脉冲都是0.5625ms
  19.         dat >>= 1;              //下一个位
  20.     }
  21. }

  22. //========================================================================
  23. // 函数: void   PCA_config(void)
  24. // 描述: PCA配置函数.
  25. // 参数: None
  26. // 返回: none.
  27. // 版本: V1.0, 2012-11-22
  28. //===========================
  29. void    PCA_config(void)
  30. {
  31.     AUXR1   = (AUXR1 & ~0x30) | 0x10;   //切换IO口, 0x00: P1.2 P1.1 P1.0 P3.7,  0x10: P3.4 P3.5 P3.6 P3.7, 0x20: P2.4 P2.5 P2.6 P2.7

  32.     CCON = 0x00;    //清除所有中断标志
  33.     CCAPM2  = 0x48+ 1;  //工作模式 + 允许中断 0x00: PCA_Mode_Capture,  0x42: PCA_Mode_PWM,  0x48: PCA_Mode_SoftTimer
  34.     CCAPM2 |= 0x04; //允许高速取反输出, 一般用在16位软件定时器
  35.     PCA_Timer2 = 100;   //随便给一个小的初值
  36.     CCAP2L = (u8)PCA_Timer2;            //将影射寄存器写入捕获寄存器,先写CCAPxL
  37.     CCAP2H = (u8)(PCA_Timer2 >> 8); //后写CCAPxH

  38.     PPCA = 1;   //高优先级中断
  39.     CMOD  = (CMOD  & ~0xe0) | 0x08; //选择时钟源, 0x00: 12T, 0x02: 2T, 0x04: Timer0溢出, 0x06: ECI, 0x08: 1T, 0x0A: 4T, 0x0C: 6T, 0x0E: 8T
  40.     CH = 0;
  41.     CL = 0;
  42.     CR = 0;
  43.     tx_cnt = 2;
  44. }

  45. //=========================
  46. // 函数: void   PCA_Handler (void) interrupt PCA_VECTOR
  47. // 描述: PCA中断处理程序.
  48. // 参数: None
  49. // 返回: none.
  50. // 版本: V1.0, 2012-11-22
  51. //========================================================================

  52. #define D_38K_DUTY  ((MAIN_Fosc * 26) / 1000000UL + MAIN_Fosc / 3000000UL)  /*  38KHZ周期时间   26.3us */
  53. #define D_38K_OFF   ((MAIN_Fosc * 17) / 1000000UL + MAIN_Fosc / 3000000UL)  /* 发射管关闭时间   17.3us */
  54. #define D_38K_ON    ((MAIN_Fosc * 9) / 1000000UL)                           /* 发射管导通时间   9us */

  55. void    PCA_Handler (void) interrupt 7
  56. {
  57.     CCON = 0x40;    //清除所有中断标志,但不关CR
  58.     if(!B_Space)    //发送载波
  59.     {                               //发送脉冲,交替装载TH0值,溢出时自动重装
  60.         if(P_IR_TX)
  61.         {
  62.             PCA_Timer2 += D_38K_OFF;    //装载高电平时间    17.3us
  63.             if(--tx_cnt == 0)   CR = 0; //pulse has sent,   stop
  64.         }
  65.         else    PCA_Timer2 += D_38K_ON; //装载低电平时间    9us
  66.     }
  67.     else    //发送暂停时间
  68.     {
  69.         PCA_Timer2 += D_38K_DUTY;   //装载周期时间  26.3us
  70.         if(--tx_cnt == 0)   CR = 0; //空闲时间
  71.     }
  72.     CCAP2L = (u8)PCA_Timer2;            //将影射寄存器写入捕获寄存器,先写CCAP0L
  73.     CCAP2H = (u8)(PCA_Timer2 >> 8); //后写CCAP0H
  74. }
复制代码
回复 支持 反对

使用道具 举报

4

主题

46

帖子

208

积分

中级会员

Rank: 3Rank: 3

积分
208
发表于 2019-6-16 23:03:35 | 显示全部楼层
回复 支持 反对

使用道具 举报

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

本版积分规则

QQ|手机版|官方淘宝店|930电子网 ( 皖ICP备16000695号-2

GMT+8, 2019-8-24 19:41 , Processed in 0.502471 second(s), 24 queries .

Powered by 930电子网 X3.2

© 2013-2023 930ebbs

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