找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8900|回复: 9
收起左侧

STC15单片机只用一个定时器的红外接收程序

  [复制链接]
ID:99618 发表于 2015-12-20 01:38 | 显示全部楼层 |阅读模式
红外线
红外接收程序,请测试。
红外接收输入可以定义在任何IO。
串口使用9600,N,8,1来监控。
主频适应5~36MHZ。

0.png

  1. /*------------------------------------------------------------------*/
  2. /* --- STC MCU International Limited -------------------------------*/
  3. /* If you want to use the program or the program referenced in the  */
  4. /* article, please specify in which data and procedures from STC    */
  5. /*------------------------------------------------------------------*/


  6. /*************        功能说明        **************

  7. 红外接收程序。适用于市场上用量最大的HT6121/6122及其兼容IC的编码。

  8. 对于用户码与User_code定义不同的遥控器,程序会将用户码一起从串口输出。

  9. 使用模拟串口发送监控显示编码,显示内容为ASCII码和中文。

  10. 本接收程序基于状态机的方式,占用CPU的时间非常少。

  11. HEX文件在本目录的/list里面。

  12. ******************************************/


  13. /*************        用户系统配置        **************/

  14. #define MAIN_Fosc                12000000L        //定义主时钟, 模拟串口和红外接收会自动适应。5~36MHZ

  15. #define D_TIMER0                125                        //选择定时器时间, us, 红外接收要求在60us~250us之间

  16. #define        User_code                0xFD02                //定义红外接收用户码


  17. /*************        以下宏定义用户请勿修改        **************/
  18. #include        "reg51.H"
  19. #define        uchar        unsigned char
  20. #define uint        unsigned int

  21. #define freq_base                        (MAIN_Fosc / 1200)
  22. #define Timer0_Reload                (65536 - (D_TIMER0 * freq_base / 10000))




  23. /*************        本地常量声明        **************/



  24. /*************        本地变量声明        **************/
  25. sbit        P_TXD1 = P3^1;                //定义模拟串口发送脚,打印信息用
  26. sbit        P_IR_RX = P0^1;                //定义红外接收输入端口

  27. bit                P_IR_RX_temp;                //Last sample
  28. bit                B_IR_Sync;                        //已收到同步标志
  29. uchar        IR_SampleCnt;                //采样计数
  30. uchar        IR_BitCnt;                        //编码位数
  31. uchar        IR_UserH;                        //用户码(地址)高字节
  32. uchar        IR_UserL;                        //用户码(地址)低字节
  33. uchar        IR_data;                        //数据原码
  34. uchar        IR_DataShit;                //数据反码

  35. bit                B_IrUserErr;                //User code error flag
  36. bit                B_IR_Press;                        //Key press flag,include repeat key.
  37. uchar        IR_code;                        //IR code        红外键码


  38. /*************        本地函数声明        **************/
  39. void        Tx1Send(uchar dat);
  40. uchar        HEX2ASCII(uchar dat);
  41. void        InitTimer(void);
  42. void        PrintString(unsigned char code *puts);



  43. /*************  外部函数和变量声明 *****************/



  44. /********************* 主函数 *************************/
  45. void main(void)
  46. {
  47.         InitTimer();                //初始化Timer
  48.         
  49.         PrintString("****** STC系列MCU红外接收程序 2010-12-10 ******\r\n");        //上电后串口发送一条提示信息

  50.         while(1)
  51.         {
  52.                 if(B_IR_Press)                //有IR键按下
  53.                 {
  54.                         PrintString("红外码: 0x");                        //提示红外键码
  55.                         Tx1Send(HEX2ASCII(IR_code >> 4));        //键码高半字节
  56.                         Tx1Send(HEX2ASCII(IR_code));                //键码低半字节
  57.                         if(B_IrUserErr)                                                //用户码错误,则发送用户码
  58.                         {
  59.                                 Tx1Send(' ');                                        //发空格
  60.                                 Tx1Send(' ');                                        //发空格
  61.                                 PrintString("用户码: 0x");                //提示用户码
  62.                                 Tx1Send(HEX2ASCII(IR_UserH >> 4));        //用户码高字节的高半字节
  63.                                 Tx1Send(HEX2ASCII(IR_UserH));                //用户码高字节的低半字节
  64.                                 Tx1Send(HEX2ASCII(IR_UserL >> 4));        //用户码低字节的高半字节
  65.                                 Tx1Send(HEX2ASCII(IR_UserL));                //用户码低字节的低半字节
  66.                         }
  67.                         Tx1Send(0x0d);                //发回车
  68.                         Tx1Send(0x0a);                //发回车
  69.                         B_IR_Press = 0;                //清除IR键按下标志
  70.                 }
  71.         }
  72. }


  73. /********************* 十六进制转ASCII函数 *************************/
  74. uchar        HEX2ASCII(uchar dat)
  75. {
  76.         dat &= 0x0f;
  77.         if(dat <= 9)        return (dat + '0');        //数字0~9
  78.         return (dat - 10 + 'A');                        //字母A~F
  79. }




  80. //*******************************************************************
  81. //*********************** IR Remote Module **************************

  82. //*********************** IR Remote Module **************************
  83. //this programme is used for Receive IR Remote (HT6121).

  84. //data format: Synchro,AddressH,AddressL,data,/data, (total 32 bit).

  85. //send a frame(85ms), pause 23ms, send synchro of another frame, pause 94ms

  86. //data rate: 108ms/Frame


  87. //Synchro:low=9ms,high=4.5/2.25ms,low=0.5626ms
  88. //Bit0:high=0.5626ms,low=0.5626ms
  89. //Bit1:high=1.6879ms,low=0.5626ms
  90. //frame space = 23 ms or 96 ms

  91. /******************** 红外采样时间宏定义, 用户不要随意修改        *******************/

  92. #if ((D_TIMER0 <= 250) && (D_TIMER0 >= 60))
  93.         #define        D_IR_sample                        D_TIMER0                //定义采样时间,在60us~250us之间
  94. #endif

  95. #define D_IR_SYNC_MAX                (15000/D_IR_sample)        //SYNC max time
  96. #define D_IR_SYNC_MIN                (9700 /D_IR_sample)        //SYNC min time
  97. #define D_IR_SYNC_DIVIDE        (12375/D_IR_sample)        //decide data 0 or 1
  98. #define D_IR_DATA_MAX                (3000 /D_IR_sample)        //data max time
  99. #define D_IR_DATA_MIN                (600  /D_IR_sample)        //data min time
  100. #define D_IR_DATA_DIVIDE        (1687 /D_IR_sample)        //decide data 0 or 1
  101. #define D_IR_BIT_NUMBER                32                                        //bit number

  102. //*******************************************************************************************
  103. //**************************** IR RECEIVE MODULE ********************************************

  104. void IR_RX_HT6121(void)
  105. {
  106.         uchar        SampleTime;

  107.         IR_SampleCnt++;                                                        //Sample + 1

  108.         F0 = P_IR_RX_temp;                                                //Save Last sample status
  109.         P_IR_RX_temp = P_IR_RX;                                        //Read current status
  110.         if(F0 && !P_IR_RX_temp)                                        //Last sample is high,and current sample is low, so is fall edge
  111.         {
  112.                 SampleTime = IR_SampleCnt;                        //get the sample time
  113.                 IR_SampleCnt = 0;                                        //Clear the sample counter

  114.                          if(SampleTime > D_IR_SYNC_MAX)                B_IR_Sync = 0;        //large the Maxim SYNC time, then error
  115.                 else if(SampleTime >= D_IR_SYNC_MIN)                                        //SYNC
  116.                 {
  117.                         if(SampleTime >= D_IR_SYNC_DIVIDE)
  118.                         {
  119.                                 B_IR_Sync = 1;                                        //has received SYNC
  120.                                 IR_BitCnt = D_IR_BIT_NUMBER;        //Load bit number
  121.                         }
  122.                 }
  123.                 else if(B_IR_Sync)                                                //has received SYNC
  124.                 {
  125.                         if(SampleTime > D_IR_DATA_MAX)                B_IR_Sync=0;        //data samlpe time to large
  126.                         else
  127.                         {
  128.                                 IR_DataShit >>= 1;                                        //data shift right 1 bit
  129.                                 if(SampleTime >= D_IR_DATA_DIVIDE)        IR_DataShit |= 0x80;        //devide data 0 or 1
  130.                                 if(--IR_BitCnt == 0)                                //bit number is over?
  131.                                 {
  132.                                         B_IR_Sync = 0;                                        //Clear SYNC
  133.                                         if(~IR_DataShit == IR_data)                //判断数据正反码
  134.                                         {
  135.                                                 if((IR_UserH == (User_code / 256)) &&
  136.                                                         IR_UserL == (User_code % 256))
  137.                                                                 B_IrUserErr = 0;        //User code is righe
  138.                                                 else        B_IrUserErr = 1;        //user code is wrong
  139.                                                         
  140.                                                 IR_code      = IR_data;
  141.                                                 B_IR_Press   = 1;                        //数据有效
  142.                                         }
  143.                                 }
  144.                                 else if((IR_BitCnt & 7)== 0)                //one byte receive
  145.                                 {
  146.                                         IR_UserL = IR_UserH;                        //Save the User code high byte
  147.                                         IR_UserH = IR_data;                                //Save the User code low byte
  148.                                         IR_data  = IR_DataShit;                        //Save the IR data byte
  149.                                 }
  150.                         }
  151.                 }
  152.         }
  153. }


  154. /**************** Timer初始化函数 ******************************/
  155. void InitTimer(void)
  156. {
  157.         TMOD = 0;                //for STC15Fxxx系列        Timer0 as 16bit reload timer.
  158.         TH0 = Timer0_Reload / 256;
  159.         TL0 = Timer0_Reload % 256;
  160.         ET0 = 1;
  161.         TR0 = 1;

  162.         EA  = 1;
  163. }


  164. /********************** Timer0中断函数************************/
  165. void timer0 (void) interrupt 1
  166. {
  167.         IR_RX_HT6121();
  168. }


  169. /********************** 模拟串口相关函数************************/

  170. void        BitTime(void)        //位时间函数
  171. {
  172.         uint i;
  173.         i = ((MAIN_Fosc / 100) * 104) / 140000 - 1;                //根据主时钟来计算位时间
  174.         while(--i);
  175. }

  176. //模拟串口发送
  177. void        Tx1Send(uchar dat)                //9600,N,8,1                发送一个字节
  178. {
  179.         uchar        i;
  180.         EA = 0;
  181.         P_TXD1 = 0;
  182.         BitTime();
  183.         for(i=0; i<8; i++)
  184.         {
  185.                 if(dat & 1)                P_TXD1 = 1;
  186.                 else                        P_TXD1 = 0;
  187.                 dat >>= 1;
  188.                 BitTime();
  189.         }
  190.         P_TXD1 = 1;
  191.         EA = 1;
  192.         BitTime();
  193.         BitTime();
  194. }

  195. void PrintString(unsigned char code *puts)                //发送一串字符串
  196. {
  197.     for (; *puts != 0;        puts++)  Tx1Send(*puts);         //遇到停止符0结束
  198. }
复制代码


STC15系列只用一个定时器的红外接收程序.rar

9.51 KB, 下载次数: 119, 下载积分: 黑币 -5

评分

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

查看全部评分

回复

使用道具 举报

ID:67274 发表于 2020-3-29 02:47 | 显示全部楼层
这个程序定时器时间溢出计算有个不严谨写法,初学者可能会晕。
#define freq_base                        (FOSC  / 1200)
#define Timer0_Reload                (65536 - (D_TIMER0 * freq_base / 10000))
应该是

#define freq_base                        (FOSC  / 12)
#define Timer0_Reload                (65536 - (D_TIMER0 * freq_base / 1000000))
回复

使用道具 举报

ID:597505 发表于 2019-8-8 12:56 | 显示全部楼层
请问这个程序, 如何判断重复码??  

比如按音量加 , 这个程序只能按一次加一次, , 正常应该是按住, 音量一直加 才正确.
回复

使用道具 举报

ID:694878 发表于 2020-2-19 22:55 | 显示全部楼层
学习了,谢谢!
回复

使用道具 举报

ID:695423 发表于 2020-2-20 07:25 | 显示全部楼层
真好,多么详细的说明
回复

使用道具 举报

ID:67274 发表于 2020-3-28 01:11 | 显示全部楼层
好巧妙的模拟串口。
回复

使用道具 举报

ID:27916 发表于 2020-3-28 08:20 | 显示全部楼层
赞赞


回复

使用道具 举报

ID:685070 发表于 2020-3-29 08:58 | 显示全部楼层
学习了 谢谢
回复

使用道具 举报

ID:272612 发表于 2020-5-17 01:12 | 显示全部楼层
学习了 谢谢
回复

使用道具 举报

ID:746849 发表于 2020-5-17 13:35 | 显示全部楼层
学习了,顶了,希望出更精彩的教程
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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