[技术问答] 串口通信+红外通信 通过串口发送红外遥控器的解码值到PC

[复制链接]
 楼主| Tennasi 发表于 2016-2-28 22:41 | 显示全部楼层 |阅读模式
  1. /**
  2.   *************************************************************************
  3.   * [url=home.php?mod=space&uid=288409]@file[/url]       main.c
  4.   * [url=home.php?mod=space&uid=187600]@author[/url]     xr
  5.   * [url=home.php?mod=space&uid=212281]@date[/url]       2014年3月31日22:30:08
  6.   * [url=home.php?mod=space&uid=895143]@version[/url]    V1.2.3
  7.   * [url=home.php?mod=space&uid=247401]@brief[/url]      串口通信+红外通信 通过串口发送红外遥控器的解码值到PC
  8.   * [url=home.php?mod=space&uid=536309]@NOTE[/url]       单片机STC89C52RC MCU  晶振 11.0592MHZ
  9.   *************************************************************************
  10.   */

  11. #include <reg52.h>

  12. void ConfigUart();
  13. void UartSend(unsigned char dat);
  14. void delayms(unsigned int xms);
  15. extern bit irflag;
  16. extern unsigned char ircode[4];
  17. extern void ConfigInfrared();

  18. void main()
  19. {
  20. ConfigUart();
  21. ConfigInfrared();

  22. while (1)
  23. {
  24. if (irflag) //接收到红外数据
  25. {
  26. irflag = 0;
  27. UartSend(ircode[0]); //发送用户码
  28. delayms(100);//延时100ms
  29. UartSend(ircode[2]); //发送键码
  30. }
  31. }
  32. }

  33. /**
  34.   * @brief     延时xms
  35.   * @param     xms
  36.   * @retval    无
  37.   */
  38. void delayms(unsigned int xms)
  39. {
  40. unsigned int x, y;

  41. for (x = 0; x < xms; x++)
  42. for (y = 0; y < 110; y++);
  43. }

  44. /**
  45.   * @brief     配置串口通信
  46.   * @param     无
  47.   * @retval    无
  48.   */
  49. void ConfigUart()
  50. {
  51. TMOD &= 0x0F;//清零T1控制位
  52. TMOD |= 0x20;//T1方式2,八位自动重装模式
  53. TH1 = 0xFD; //波特率 = 256-1/2^SMOD*T1溢出率  X=256-11059200/12/32/波特率
  54. TL1 = TH1;//波特率9600bps
  55. TR1 = 1;
  56. ET1 = 0;//只用T1的计数
  57. SCON |= 0x50;//串口方式1 SM0 SM1 SM2 REN TB8 RB8 TI RI 0101 0000
  58. /*
  59. SM0 = 0;
  60. SM1 = 1;//方式1 SM2多机通信位
  61. REN = 1;//允许接收数据
  62. TI = 0;//发送完成中断标志
  63. RI = 0;//接收完成中断标志
  64. */
  65. ES = 1;//开串口中断
  66. EA = 1;//开总中断
  67. }


 楼主| Tennasi 发表于 2016-2-28 22:41 | 显示全部楼层
  1. /**
  2.   * @brief     串口发送一个字节数据到PC
  3.   * @param     待发送数据
  4.   * @retval    无
  5.   */
  6. void UartSend(unsigned char dat)
  7. {
  8. SBUF = dat;
  9. //while (!TI);//等待发送完成,在中断模式下不需要等待,否则进不了中断
  10. }

  11. /**
  12.   * @brief     串口中断
  13.   * @param     无
  14.   * @retval    无
  15.   */
  16. void Uart_ISP() interrupt 4 //串口中断标号是4
  17. {
  18. if (TI) //等待发送完成
  19. { //发送完成
  20. TI = 0;//清零
  21. }
  22. }


  23. /**
  24.   **************************************************************
  25.   * @file      infrared.c
  26.   * @author    xr
  27.   * @date      2014年3月31日20:51:23
  28.   * @version   V1.2.3
  29.   * @brief     红外通信--红外遥控器NEC协议解码
  30.   * @note      单片机STC89C52RC MCU  晶振 11.0592MHZ
  31.   **************************************************************
  32.   */

  33. #include <reg52.h>

  34. sbit IRD = P3^3;//红外接收检测端口

  35. bit irflag = 0;//接收到数据的标志
  36. unsigned char ircode[4];//存放红外遥控器发送的用户码,用户码反码 键码 键码反码

  37. /**
  38.   * @brief     红外配置
  39.   * @param     无
  40.   * @retval    无
  41.   */
  42. void ConfigInfrared()
  43. {
  44. TH0 = 0;
  45. TL0 = 0;//清零T0计数
  46. TMOD &= 0xF0;
  47. TMOD |= 0x01;//T0方式1
  48. TR0 = 0;//在没有红外信号之前先关闭T0
  49. ET0 = 0;//只用T0的计数

  50. //外部中断1
  51. IT1 = 1;//设置外部中断触发方式为下降沿触发
  52. EX1 = 1;//开启外部中断1
  53. }

  54. /**
  55.   * @brief     获得IRD红外检测引脚的高电平时间(空闲时间)
  56.   * @param     无
  57.   * @retval    高电平持续的计数值
  58.   */
  59. unsigned int getHeighTime()
  60. {
  61. //在检测外部信号前,必须先将IRDIO口拉高
  62. IRD = 1;
  63. TH0 = 0;
  64. TL0 = 0;//清零T0计数
  65. TR0 = 1;//开启T0计数

  66. while (IRD) //持续高电平
  67. {
  68. //超时判断
  69. if (TH0 > 0x40) //当IRD持续高电平时间17.7ms,远远大于引导码的9ms,是误码
  70. {
  71. break;//退出
  72. }
  73. }
  74. TR0 = 0;//停止计数

  75. return (TH0*256 + TL0);//返回高电平计数值
  76. }

  77. /**
  78.   * @brief     获得IRD红外检测引脚的低电平时间(载波时间)
  79.   * @param     无
  80.   * @retval    低电平持续的计数值
  81.   */
  82. unsigned int getLowTime()
  83. {
  84. IRD = 1;//释放IRD,检测外部信号
  85. TH0 = 0;
  86. TL0 = 0;//清零T0计数
  87. TR0 = 1;//开始计数

  88. while (!IRD) //持续低电平
  89. {
  90. if (TH0 > 0x40) //超过18ms就是误码,错误信号
  91. {
  92. break;
  93. }
  94. }
  95. TR0 = 0;//停止计数

  96. return (TH0*256 + TL0);//返回低电平计数值
  97. }

  98. /**
  99.   * @brief     外部中断1服务程序,检测红外信号
  100.   * @param     无
  101.   * @retval    无
  102.   */
  103. void EXINT_ISP() interrupt 2  //外部中断标号2
  104. {
  105. unsigned char byte;//接收数据
  106. unsigned char i, j;
  107. unsigned int time;//时间

  108. time = getLowTime();//获得载波时间
  109. if (time < 7833 || time > 8755) //引导码载波是9ms,这里规定在8.5ms-9.5ms之间是9ms的载波
  110. {
  111. //范围之外,误码
  112. IE1 = 0;//清零外部中断1中断标志,为下一次再进入中断
  113. return;//退出中断
  114. }
  115. //否则是9ms的载波
  116. time = getHeighTime();//空闲时间
  117. if (time < 3686 || time > 4608) //引导码的空闲时间4.5ms 这里规定4ms-5ms是4.5ms的空闲
  118. {
  119. IE1 = 0;//清零中断标志
  120. return;//退出中断
  121. }
  122. //否则是4.5ms的空闲
  123. //开始接收用户码和键码等
  124. for (i = 0; i < 4; i++)
  125. {
  126. for (j = 0; j < 8; j++)
  127. {
  128. time = getLowTime();//载波
  129. if (time < 423 || time > 608) //560us的载波和560us的空闲是0 范围460us-660us
  130. {
  131. IE1 = 0;
  132. return;
  133. }
  134. //560us载波
  135. time = getHeighTime();
  136. if (time > 423 && time < 608) //560us空闲
  137. {
  138. //bit '0'
  139. byte >>= 1;//低位在前,移入一位0
  140. }
  141. else if (time > 1198 && time < 1658) //1.68ms的空闲是1 范围 1300us-1800us
  142. {
  143. //bit '1'
  144. byte >>= 1;//移入一位
  145. byte |= 0x80;//移入的一位置1
  146. }
  147. else
  148. {
  149. //误码
  150. IE1 = 0;
  151. return;//退出中断
  152. }
  153. }
  154. ircode = byte;
  155. }
  156. //接收完成
  157. irflag = 1;

  158. //退出中断时清零中断标志
  159. IE1 = 0;
  160. }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

22

主题

169

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部