当前位置:   article > 正文

单片机基于NEC协议的红外软编码和硬解码方案_红外解码层序

红外解码层序

在物联网产品的开发过程中经常需要基于无线的简单交互通讯,红外通讯比较适合近距离低速的

交换数据场景,红外协议比较多,比如NEC,RC5,NRC17等。

NEC红外协议,GPIO口的输出时序,
1.逻辑0为脉冲时间560us低电平+560us高电平,1.12ms周期 ,逻辑1为脉冲时间560us低电平+1690us高电平,  2.25ms周期。
2.命令格式 9ms低电平引导码+4.5ms高电平结果码+地址码+地址反码+命令码+命令反码 (经测试必须32BIT(4个字节))+560us低电平作为结束,经测试接收管自动反向,注意这四个字节为(A,~A,B,~B)。
3.占空比1/4到1/3载波为38KHZ的PWM。
4.命令格式的电平反向形式。

使用GD32F4XX串口3作为红外编解码通讯接口,

USART3_RX接收BC7120A的红外解码数据,波特率9600。

USART3_TX作为普通IO输出因引脚与外部38KHZ振荡电路通过与门输出调制脉冲到红外发射管。

delay.c软件延时

  1. #ifndef __DELAY_H__
  2. #define __DELAY_H__
  3. #include "gd32f4xx.h"
  4. #define delay_us Delay_US
  5. #define delay_ms Delay_MS
  6. #define HAL_Delay Delay_MS
  7. void Delay_US(uint32_t time);
  8. void Delay_MS(uint32_t time);
  9. #endif
  10. #include "delay.h"
  11. #define CURRENT_CPU_FREQ (SystemCoreClock / 1000000)
  12. void Delay_US(uint32_t time)
  13. {
  14. while(time--)
  15. {
  16. #if (CURRENT_CPU_FREQ == 120)
  17. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  18. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  19. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  20. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  21. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  22. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  23. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  24. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  25. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  26. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  27. #elif (CURRENT_CPU_FREQ == 168)
  28. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  29. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  30. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  31. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  32. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  33. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  34. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  35. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  36. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  37. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  38. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  39. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  40. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  41. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  42. #elif (CURRENT_CPU_FREQ == 200)
  43. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  44. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  45. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  46. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  47. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  48. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  49. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  50. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  51. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  52. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  53. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  54. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  55. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  56. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  57. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  58. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  59. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  60. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  61. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  62. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  63. #else
  64. __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
  65. #endif
  66. }
  67. }
  68. void Delay_MS(uint32_t time)
  69. {
  70. Delay_US(time * 11000);
  71. }


 

timer1.c定时器硬件延时

  1. #ifndef __TIMER1_H__
  2. #define __TIMER1_H__
  3. #include "gd32f4xx.h"
  4. #include "it_config.h"
  5. void Timer_Init(void);
  6. void Timer_Dly_Wait(uint32_t time);
  7. #endif
  8. #include "timer1.h"
  9. #define TIMx TIMER0
  10. #define RCU_TIMx_CLK RCU_TIMER0
  11. #define TIMx_IRQn TIMER0_UP_TIMER9_IRQn
  12. #define TIMx_IRQHandler TIMER0_UP_TIMER9_IRQHandler
  13. /**100us时基*/
  14. static __IO uint32_t timer1_100us_cnt = 0;
  15. void Timer_Init(void)
  16. {
  17. timer_parameter_struct timer_initpara;
  18. rcu_periph_clock_enable(RCU_TIMx_CLK);
  19. timer_deinit(TIMx);
  20. /* initialize TIMER init parameter struct */
  21. timer_struct_para_init(&timer_initpara);
  22. /* TIMER1 configuration 配置出来中断为100us 168MHZ下*/
  23. timer_initpara.prescaler = 168 - 1;
  24. timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
  25. timer_initpara.counterdirection = TIMER_COUNTER_UP;
  26. timer_initpara.period = 100;
  27. timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
  28. nvic_irq_enable(TIMx_IRQn, TIMER1_NVIC_PREEMPTIONPRIORITY, TIMER1_NVIC_SUBPRIORITY);
  29. timer_init(TIMx, &timer_initpara);
  30. timer_interrupt_enable(TIMx, TIMER_INT_UP);
  31. timer_enable(TIMx);
  32. }
  33. /**
  34. * @brief This function handles TIMER1 interrupt request.
  35. * @param None
  36. * @retval None
  37. */
  38. void TIMx_IRQHandler(void)
  39. {
  40. if(SET == timer_interrupt_flag_get(TIMx, TIMER_INT_FLAG_UP)){
  41. /* clear channel 0 interrupt bit */
  42. timer_interrupt_flag_clear(TIMx, TIMER_INT_FLAG_UP);
  43. timer1_100us_cnt++;
  44. }
  45. }
  46. //定时器防止uint32_t溢出延时函数
  47. void Timer_Dly_Wait(uint32_t time)
  48. {
  49. uint32_t cur_cnt = timer1_100us_cnt;
  50. if(cur_cnt + time <= 0xFFFFFFFF)
  51. {
  52. while(timer1_100us_cnt - cur_cnt < time);
  53. }
  54. else
  55. {
  56. while(timer1_100us_cnt < 0xFFFFFFFF);
  57. time = time - (0xFFFFFFFF - cur_cnt);
  58. while(1 + timer1_100us_cnt < time);
  59. }
  60. }

infrared.c红外软编码硬解码实现

  1. #ifndef __INFRARED_H__
  2. #define __INFRARED_H__
  3. #include <string.h>
  4. #include "cmsis_os.h"
  5. #include "gd32f4xx.h"
  6. #include "config.h"
  7. #include "comtypes.h"
  8. #include "delay.h"
  9. #include "timer1.h"
  10. #include "raygunled.h"
  11. #include "mode.h"
  12. #define IR_TX_FUNC
  13. #define IR_RX_FUNC
  14. void IR_Init(void);
  15. void IR_Send(uint8_t*buf, uint8_t len);
  16. #endif
  17. #include "infrared.h"
  18. #define USART2_DATA_ADDRESS ((uint32_t)&USART_DATA(USART2))
  19. #define USART3_DR_ADDR USART2_DATA_ADDRESS
  20. #define USARTx USART2
  21. #define RCU_GPIO_CLK RCU_GPIOC
  22. #define RCU_USARTx_CLK RCU_USART2
  23. #define USART_GPIO_AF GPIO_AF_7
  24. #define USARTx_TX_GPIO_PORT GPIOC
  25. #define USARTx_TX_PIN GPIO_PIN_10
  26. #define USARTx_RX_GPIO_PORT GPIOC
  27. #define USARTx_RX_PIN GPIO_PIN_11
  28. #define DMAx DMA0
  29. #define RCU_DMAx_CLK RCU_DMA0
  30. #define USARTx_TX_DMA_CHANNEL DMA_CH3
  31. #define USARTx_RX_DMA_CHANNEL DMA_CH1
  32. #define USARTx_DMA_SUBPERI4 DMA_SUBPERI4
  33. #define USARTx_IRQn USART2_IRQn
  34. #define USARTx_IRQHandler USART2_IRQHandler
  35. #define USART3_RECV_BUFF_LEN (3)
  36. #define TX_PIN_SET gpio_bit_set(USARTx_TX_GPIO_PORT,USARTx_TX_PIN)
  37. #define TX_PIN_RESET gpio_bit_reset(USARTx_TX_GPIO_PORT,USARTx_TX_PIN)
  38. #define IR_TX(x) ((x) ? TX_PIN_SET : TX_PIN_RESET)
  39. static dma_single_data_parameter_struct dma_init_struct;
  40. //DMA接收缓冲区
  41. static __IO uint8_t usart3_recv_buf[USART3_RECV_BUFF_LEN];
  42. __IO BOOLEAN is_be_shooted = FALSE;
  43. __IO int shooted_bullet = 0;
  44. #ifdef IR_TX_FUNC
  45. static __INLINE void IR_DELAY(uint8_t tm)
  46. {
  47. uint8_t tmp;
  48. tmp = tm / 10;
  49. if(tmp)
  50. {
  51. osDelay(tmp);
  52. }
  53. tmp = tm % 10;
  54. if(tmp)
  55. {
  56. Timer_Dly_Wait(tmp);
  57. }
  58. }
  59. #endif
  60. void IR_Init(void)
  61. {
  62. rcu_periph_clock_enable(RCU_GPIO_CLK);
  63. /* enable USART clock */
  64. rcu_periph_clock_enable(RCU_USARTx_CLK);
  65. /* connect port to USARTx_Tx */
  66. //gpio_af_set(USARTx_TX_GPIO_PORT, USART_GPIO_AF, USARTx_TX_PIN);
  67. /* connect port to USARTx_Rx */
  68. gpio_af_set(USARTx_RX_GPIO_PORT, USART_GPIO_AF, USARTx_RX_PIN);
  69. /* configure USART Tx push-pull */
  70. gpio_mode_set(USARTx_TX_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP,USARTx_TX_PIN);
  71. gpio_output_options_set(USARTx_TX_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,USARTx_TX_PIN);
  72. gpio_bit_set(USARTx_TX_GPIO_PORT,USARTx_TX_PIN);
  73. /* configure USART Rx as alternate function push-pull */
  74. gpio_mode_set(USARTx_RX_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP,USARTx_RX_PIN);
  75. gpio_output_options_set(USARTx_RX_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,USARTx_RX_PIN);
  76. /* USART configure */
  77. usart_deinit(USARTx);
  78. //注意该波特率
  79. usart_baudrate_set(USARTx, 9600U);
  80. usart_word_length_set(USARTx, USART_WL_8BIT);
  81. usart_stop_bit_set(USARTx, USART_STB_1BIT);
  82. usart_parity_config(USARTx, USART_PM_NONE);
  83. usart_hardware_flow_rts_config(USARTx, USART_RTS_DISABLE);
  84. usart_hardware_flow_cts_config(USARTx, USART_CTS_DISABLE);
  85. usart_receive_config(USARTx, USART_RECEIVE_ENABLE);
  86. //usart_transmit_config(USARTx, USART_TRANSMIT_ENABLE);
  87. ///
  88. /* enable DMA1 */
  89. rcu_periph_clock_enable(RCU_DMAx_CLK);
  90. dma_deinit(DMAx, USARTx_RX_DMA_CHANNEL);
  91. dma_init_struct.direction = DMA_PERIPH_TO_MEMORY;
  92. dma_init_struct.memory0_addr = (uint32_t)usart3_recv_buf;
  93. dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
  94. dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
  95. dma_init_struct.number = USART3_RECV_BUFF_LEN;
  96. dma_init_struct.periph_addr = USART3_DR_ADDR;
  97. dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
  98. dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
  99. dma_single_data_mode_init(DMAx, USARTx_RX_DMA_CHANNEL, &dma_init_struct);
  100. /* configure DMA mode */
  101. dma_circulation_enable(DMAx, USARTx_RX_DMA_CHANNEL);
  102. dma_channel_subperipheral_select(DMAx, USARTx_RX_DMA_CHANNEL, USARTx_DMA_SUBPERI4);
  103. nvic_irq_enable(USARTx_IRQn, USART3_NVIC_PREEMPTIONPRIORITY, USART3_NVIC_SUBPRIORITY);
  104. usart_dma_receive_config(USARTx, USART_DENR_ENABLE);
  105. dma_channel_enable(DMAx, USARTx_RX_DMA_CHANNEL);
  106. usart_interrupt_enable(USARTx,USART_INT_IDLE);
  107. usart_enable(USARTx);
  108. }
  109. //NEC协议软编码
  110. void IR_Send(uint8_t*buf, uint8_t len)
  111. {
  112. #ifdef IR_TX_FUNC
  113. uint8_t i = 0;
  114. uint8_t j = 0;
  115. uint8_t tmp = 0;
  116. //发送9ms引导码 低电平
  117. IR_TX(0);
  118. IR_DELAY(90);
  119. //发送4.5ms结果码 高电平
  120. IR_TX(1);
  121. IR_DELAY(45);
  122. IR_TX(0);
  123. for(i=0;i < len;i++)
  124. {
  125. tmp = buf[i];
  126. //数据从低位向高位发送
  127. for(j=0;j < 8;j++)
  128. {
  129. //发送逻辑1
  130. if(tmp & 0x01)
  131. {
  132. IR_TX(0);
  133. IR_DELAY(5);
  134. Delay_US(60);
  135. //共计560us 低电平
  136. IR_TX(1);
  137. IR_DELAY(16);
  138. Delay_US(90);
  139. IR_TX(0);
  140. //共计1.690ms 高电平
  141. }
  142. //发送逻辑0
  143. else
  144. {
  145. IR_TX(0);
  146. IR_DELAY(5);
  147. Delay_US(60);
  148. //共计560us 低电平
  149. IR_TX(1);
  150. IR_DELAY(5);
  151. Delay_US(60);
  152. IR_TX(0);
  153. //共计560us 高电平
  154. }
  155. tmp >>= 1;
  156. }
  157. }
  158. //最后发送一个结束560us低电平,实验得到非常重要
  159. IR_TX(0);
  160. IR_DELAY(5);
  161. Delay_US(60);
  162. //波形两端拉高
  163. IR_TX(1);
  164. #endif
  165. }
  166. //串口3DMA空闲中断处理函数,用于接收BC7120A硬解码的红外数据。
  167. void USARTx_IRQHandler(void)
  168. {
  169. uint16_t tmp;
  170. dma_channel_disable(DMAx, USARTx_RX_DMA_CHANNEL);
  171. usart_interrupt_flag_clear(USARTx,USART_INT_FLAG_IDLE);
  172. usart_data_receive(USARTx);
  173. if(USART3_RECV_BUFF_LEN != dma_transfer_number_get(DMAx,USARTx_RX_DMA_CHANNEL)) goto USART3_IRQEND;
  174. tmp = usart3_recv_buf[0];
  175. if(usart3_recv_buf[1] != (uint8_t)~tmp) goto USART3_IRQEND;
  176. usart3_recv_buf[2] ^= (uint8_t)(tmp * 5);
  177. if(!Is_Raygunled_Hurt(usart3_recv_buf[2],&tmp)) goto USART3_IRQEND;
  178. shooted_bullet = tmp;
  179. is_be_shooted = TRUE;
  180. USART3_IRQEND:
  181. dma_deinit(DMAx, USARTx_RX_DMA_CHANNEL);
  182. dma_single_data_mode_init(DMAx, USARTx_RX_DMA_CHANNEL, &dma_init_struct);
  183. dma_circulation_enable(DMAx, USARTx_RX_DMA_CHANNEL);
  184. dma_channel_subperipheral_select(DMAx, USARTx_RX_DMA_CHANNEL, USARTx_DMA_SUBPERI4);
  185. dma_channel_enable(DMAx, USARTx_RX_DMA_CHANNEL);
  186. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/493120
推荐阅读
相关标签
  

闽ICP备14008679号