回答

收藏

基于GD32F450的红外解码--下位机篇

GD32 GD32 5072 人阅读 | 0 人回复 | 2017-06-12

有段日子没有更新了,我就不给自己找原因了,今天更新下下位机的代码。
下位机的思想就是在收到上位机发送的开始捕获指令后,启动两个定时器来进行捕获计时和测量脉宽。
在串口通讯时,往上位机传输数据时使用USART+DMA的方式传输,节省CPU资源。这个DMA传输花费了不少时间,原因是GD32的例子误导了很长时间,最后还是自己看手册试出的。
下位机实物图:PB2接HS0038的Out引脚,然后就是一个电源,一个地。

下位机代码:
  1. #include "gd32f4xx.h"                   // Device header
  2. #include "stddef.h"
  3. #include "ir_typedef.h"

  4. #define LED_ON                gpio_bit_set(LED4PORT,LED4)
  5. #define LED_OFF                gpio_bit_reset(LED4PORT,LED4)

  6. #define LEDx_ON                gpio_bit_set(LED5PORT,LED5)
  7. #define LEDx_OFF        gpio_bit_reset(LED5PORT,LED5)

  8. #define MeasureTimer        TIMER6
  9. #define CountTimer                TIMER5

  10. //红外数据
  11. IrDataType IrDat = {
  12.     .datBuffer1 = {0},
  13.     .i = 0
  14. };

  15. //能否上传
  16. BOOL CanTransfer;
  17. //开始捕获
  18. BOOL StartCapture;
  19. //
  20. uint32_t PulseWidth_us;
  21. //
  22. uint32_t ElapseTime;

  23. int main()
  24. {
  25.         InitLED();
  26.         InitIR();
  27.         InitUsart();
  28.         InitMeasureTimer();
  29.         InitCountTimer();
  30.        
  31.        
  32.         while(TRUE)
  33.         {
  34.                 if(CanTransfer)
  35.                 {
  36.                         if(IrDat.i != 0)
  37.                         {
  38.                                 dma_transfer_number_config(DMA0,DMA_CH3,IrDat.i);
  39.                                 dma_channel_enable(DMA0,DMA_CH3);
  40.                         }
  41.                         CanTransfer = FALSE;
  42.                 }                       
  43.         }
  44. }

  45. /*!
  46.     \brief      initialize LED Pin
  47.     \param[in]  none
  48.     \param[out] none
  49.     \retval     none
  50. */
  51. void InitLED(void)
  52. {
  53.         rcu_periph_clock_enable(RCU_GPIOB);
  54.         rcu_periph_clock_enable(RCU_GPIOD);
  55.        
  56.         gpio_deinit(GPIOB);
  57.         gpio_deinit(GPIOD);
  58.        
  59.         gpio_mode_set(LED4PORT,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,LED4|LED6);
  60.         gpio_output_options_set(LED4PORT,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,LED4|LED6);
  61.        
  62.         gpio_mode_set(LED5PORT,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,LED5);
  63.         gpio_output_options_set(LED5PORT,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,LED5);
  64.        
  65.         gpio_bit_reset(LED4PORT,LED4);
  66.         gpio_bit_reset(LED6PORT,LED6);
  67.         gpio_bit_reset(LED5PORT,LED5);
  68. }

  69. /*!
  70.     \brief      initialize IR Pin and Exit2
  71.     \param[in]  none
  72.     \param[out] none
  73.     \retval     none
  74. */
  75. void InitIR(void)
  76. {
  77.         rcu_periph_clock_enable(RCU_GPIOB);
  78.         rcu_periph_clock_enable(RCU_SYSCFG);
  79.        
  80.         gpio_mode_set(IRPORT,GPIO_MODE_INPUT,GPIO_PUPD_PULLUP,IR_PIN);
  81.        
  82.         //initialize Exti Interrupt(PB2)       
  83.         nvic_irq_enable(EXTI2_IRQn,0,1);
  84.         exti_init(EXTI_2,EXTI_INTERRUPT,EXTI_TRIG_BOTH);
  85.         syscfg_exti_line_config(EXTI_SOURCE_GPIOB,EXTI_SOURCE_PIN2);
  86.         exti_interrupt_flag_clear(EXTI_2);
  87. }

  88. /*!
  89.     \brief      initialize Timer to Measuring pulse width; 10 us
  90.     \param[in]  none
  91.     \param[out] none
  92.     \retval     none
  93. */
  94. void InitMeasureTimer(void)
  95. {
  96.         rcu_periph_clock_enable(RCU_TIMER6);
  97.         timer_deinit(TIMER6);
  98.        
  99.         timer_parameter_struct timer_initpara;
  100.         timer_initpara.prescaler = 99;
  101.         timer_initpara.period = 9;
  102.        
  103.         timer_init(TIMER6,&timer_initpara);
  104.         timer_auto_reload_shadow_enable(TIMER6);
  105.         timer_interrupt_enable(TIMER6,TIMER_INT_UP);
  106.        
  107.         nvic_irq_enable(TIMER6_IRQn,0,0);
  108.        
  109. }

  110. /*!
  111.     \brief      initialize Timer,100 ms
  112.     \param[in]  none
  113.     \param[out] none
  114.     \retval     none
  115. */
  116. void InitCountTimer(void)
  117. {
  118.         rcu_periph_clock_enable(RCU_TIMER5);
  119.         timer_deinit(TIMER5);
  120.        
  121.         timer_parameter_struct timer_initpara;
  122.         timer_initpara.prescaler = 9999;
  123.         timer_initpara.period = 999;
  124.        
  125.         timer_init(TIMER5,&timer_initpara);
  126.         timer_auto_reload_shadow_enable(TIMER5);
  127.         timer_interrupt_enable(TIMER5,TIMER_INT_UP);
  128.        
  129.         nvic_irq_enable(TIMER5_DAC_IRQn,0,1);
  130. }

  131. /*!
  132.     \brief      initialize USART2
  133.     \param[in]  none
  134.     \param[out] none
  135.     \retval     none
  136. */
  137. void InitUsart(void)
  138. {
  139.         rcu_periph_clock_enable(RCU_USART2);
  140.        
  141.         gpio_af_set(GPIOD,GPIO_AF_7,USART_TX_PIN);
  142.         gpio_af_set(GPIOD,GPIO_AF_7,USART_RX_PIN);
  143.        
  144.         gpio_mode_set(GPIOD,GPIO_MODE_AF,GPIO_PUPD_PULLUP,USART_TX_PIN);
  145.         gpio_output_options_set(GPIOD,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,USART_TX_PIN);
  146.        
  147.         gpio_mode_set(GPIOD,GPIO_MODE_AF,GPIO_PUPD_PULLUP,USART_RX_PIN);
  148.         gpio_output_options_set(GPIOD,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,USART_RX_PIN);
  149.        
  150.         usart_deinit(USART2);
  151.         usart_baudrate_set(USART2,115200);
  152.         usart_parity_config(USART2,USART_PM_NONE);
  153.         usart_word_length_set(USART2,USART_WL_8BIT);
  154.         usart_stop_bit_set(USART2,USART_STB_1BIT);
  155.         usart_transmit_config(USART2,USART_TRANSMIT_ENABLE);
  156.         usart_receive_config(USART2,USART_RECEIVE_ENABLE);
  157.         usart_interrupt_enable(USART2,USART_INTEN_RBNEIE);
  158.         usart_dma_transmit_config(USART2,USART_DENT_ENABLE);
  159.         usart_enable(USART2);
  160.         usart_flag_clear(USART2,USART_FLAG_TC);
  161.        
  162.         rcu_periph_clock_enable(RCU_DMA0);
  163.         dma_deinit(DMA0,DMA_CH3);
  164.         dma_transfer_direction_config(DMA0,DMA_CH3,DMA_MEMORY_TO_PERIPH);
  165.         dma_transfer_number_config(DMA0,DMA_CH3,IRBUF_LEN);
  166.         dma_memory_address_config(DMA0,DMA_CH3,DMA_MEMORY_0,(uint32_t)IrDat.datBuffer1);
  167.         dma_memory_width_config(DMA0,DMA_CH3,DMA_MEMORY_WIDTH_8BIT);
  168.         dma_memory_address_generation_config(DMA0,DMA_CH3,DMA_MEMORY_INCREASE_ENABLE);
  169.         dma_periph_address_config(DMA0,DMA_CH3,(uint32_t)&USART_DATA(USART2));
  170.         dma_periph_width_config(DMA0,DMA_CH3,DMA_PERIPH_WIDTH_8BIT);
  171.         dma_peripheral_address_generation_config(DMA0,DMA_CH3,DMA_PERIPH_INCREASE_DISABLE);
  172.         dma_priority_config(DMA0,DMA_CH3,DMA_PRIORITY_ULTRA_HIGH);
  173.         dma_circulation_disable(DMA0,DMA_CH3);
  174.         dma_channel_subperipheral_select(DMA0,DMA_CH3,DMA_SUBPERI4);
  175.         dma_interrupt_enable(DMA0,DMA_CH3,DMA_CHXCTL_FTFIE);
  176.        
  177.        
  178.         nvic_irq_enable(USART2_IRQn,0,2);
  179.         nvic_irq_enable(DMA0_Channel3_IRQn,0,3);
  180. }


  181. /*!
  182.     \brief      Exti2 Interrupt(PB2) Handler for ir input
  183.     \param[in]  none
  184.     \param[out] none
  185.     \retval     none
  186. */
  187. void EXTI2_IRQHandler(void)
  188. {
  189.         exti_interrupt_flag_clear(EXTI_2);
  190.         //判断是否开始捕获
  191.         if(!StartCapture)
  192.                 return;
  193.        
  194.         StopTiming();
  195.         uint32_t us = 0;
  196.         if(gpio_input_bit_get(GPIOB,GPIO_PIN_2) == SET)
  197.         {
  198.                 //上升沿触发(读取低电平的时间)
  199.                 us = (PulseWidth_us * 10) & 0x7FFFFFFF;
  200.                 LEDx_OFF;
  201.         }
  202.         else
  203.         {
  204.                 //T下降沿触发(读取高电平的时间)
  205.                 us = (PulseWidth_us * 10) | 0x80000000;
  206.                 LEDx_ON;
  207.         }
  208.         StartTiming();
  209.         if(IrDat.i >= IRBUF_LEN)
  210.     {
  211.         CanTransfer = TRUE;
  212.                 return;
  213.     }
  214.         IrDat.datBuffer1[IrDat.i] = us;
  215.         IrDat.i++;
  216. }

  217. /*!
  218.     \brief      TIMER6 interrupt Handler for measuring pulse width
  219.     \param[in]  none
  220.     \param[out] none
  221.     \retval     none
  222. */
  223. void TIMER6_IRQHandler(void)
  224. {
  225.         PulseWidth_us++;
  226.         timer_interrupt_flag_clear(TIMER6,TIMER_INT_UP);
  227. }

  228. /*!
  229.     \brief      TIMER5 interrupt Handler,5 second timer
  230.     \param[in]  none
  231.     \param[out] none
  232.     \retval     none
  233. */
  234. void TIMER5_DAC_IRQHandler(void)
  235. {
  236.         timer_interrupt_flag_clear(TIMER5,TIMER_INT_UP);
  237.         if(ElapseTime >= 50)
  238.         {
  239.                 StartCapture = FALSE;
  240.                 LED_OFF;
  241.                 timer_disable(TIMER5);
  242.                 StopTiming();
  243.                 CanTransfer = TRUE;
  244.                 return;
  245.         }
  246.         ElapseTime++;
  247. }

  248. /*!
  249.     \brief      USART2 interrupt Handler
  250.     \param[in]  none
  251.     \param[out] none
  252.     \retval     none
  253. */
  254. void USART2_IRQHandler()
  255. {
  256.         if(usart_interrupt_flag_get(USART2,USART_INT_RBNEIE) == SET)
  257.         {
  258.                 uint16_t dat = usart_data_receive(USART2);
  259.                 if(dat == 's' || dat == 'S')
  260.                 {
  261.                         if(StartCapture) return;
  262.                         IrDat.i = 0;
  263.                         LED_ON;
  264.                         Start_Capture();
  265.                         StartTiming();
  266.                 }
  267.         }
  268. }

  269. void DMA0_Channel3_IRQHandler(void)
  270. {
  271.         if(dma_interrupt_flag_get(DMA0,DMA_CH3,DMA_INTC_FTFIFC) == SET)
  272.         {
  273.                 dma_interrupt_flag_clear(DMA0,DMA_CH3,DMA_INTF_FTFIF);
  274.                 CanTransfer = FALSE;
  275.         }
  276. }

  277. /*!
  278.     \brief      Start capture ir data
  279.     \param[in]  none
  280.     \param[out] none
  281.     \retval     none
  282. */
  283. void Start_Capture(void)
  284. {
  285.         StartCapture = TRUE;
  286.         ElapseTime = 0;
  287.         timer_enable(TIMER5);
  288. }
  289. /*!
  290.     \brief      Start capture ir data
  291.     \param[in]  none
  292.     \param[out] none
  293.     \retval     none
  294. */
  295. void StartTiming(void)
  296. {
  297.         PulseWidth_us = 0;
  298.         timer_enable(TIMER6);
  299. }

  300. void StopTiming(void)
  301. {
  302.         timer_disable(TIMER6);
  303. }




复制代码
代码已经做了很详细的注释。有感兴趣的同学可以参考,有任何疑问可以提出来。



分享到:
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条