学习目标

  1. 了解超声波测距原理
  2. 掌握逻辑分析仪使用
  3. 掌握驱动编写

    学习内容

    原理图

    image.png

    传感器

    171.png
    178.png

驱动编写

定时器代码

  1. #include "bsp_timer.h"
  2. #include <stdio.h>
  3. uint32_t timer_ms = 0;
  4. void bsp_timer_init(void){
  5. // 开启时钟
  6. rcu_periph_clock_enable(RCU_TIMER5);
  7. // 开启倍频
  8. rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
  9. // 定义结构
  10. timer_parameter_struct timer_initpara;
  11. // 复位定时器
  12. timer_deinit(TIMER5);
  13. timer_struct_para_init(&timer_initpara);
  14. // 定时器配置
  15. timer_initpara.period = 1000 - 1; // 定时1ms
  16. timer_initpara.prescaler = 240 - 1;
  17. // 定时器初始化
  18. timer_init(TIMER5, &timer_initpara);
  19. // 配置中断优先级
  20. nvic_irq_enable(TIMER5_DAC_IRQn,1,1);
  21. // 使能中断. 更新事件
  22. timer_interrupt_enable(TIMER5,TIMER_INT_UP);
  23. // 使能定时器
  24. timer_enable(TIMER5);
  25. }
  26. void bsp_timer_open(void){
  27. // 清空计数器
  28. timer_counter_value_config(TIMER5,0);
  29. timer_ms = 0;
  30. timer_enable(TIMER5);
  31. }
  32. void bsp_timer_close(void){
  33. timer_disable(TIMER5);
  34. }
  35. void TIMER5_DAC_IRQHandler(void)
  36. {
  37. static int i = 0;
  38. if( timer_interrupt_flag_get(TIMER5, TIMER_INT_UP) != RESET )
  39. {
  40. timer_ms++;
  41. timer_interrupt_flag_clear(TIMER5,TIMER_INT_UP);
  42. }
  43. }
  44. uint32_t bsp_timer_get(){
  45. uint32_t t = 0;
  46. t = timer_ms*1000;
  47. t += timer_counter_read(TIMER5);
  48. return t;
  49. }

超声波驱动

  1. #ifndef __BSP_ultrasonic_H
  2. #define __BSP_ultrasonic_H
  3. #include "gd32f4xx.h"
  4. #include "systick.h"
  5. #include <stdint.h>
  6. void bsp_ultrasonic_init(void);
  7. float bsp_ultrasonic_get(void);
  8. #endif /* __BSP_LED_H */
  1. #include "bsp_ultrasonic.h"
  2. #include <stdio.h>
  3. #include "bsp_timer.h"
  4. // 定义TRIG
  5. #define RCU_TRIG RCU_GPIOB
  6. #define PORT_TRIG GPIOB
  7. #define GPIO_TRIG GPIO_PIN_14
  8. // 定义ECHO
  9. #define RCU_ECHO RCU_GPIOB
  10. #define PORT_ECHO GPIOB
  11. #define GPIO_ECHO GPIO_PIN_13
  12. void bsp_ultrasonic_gpio_init(){
  13. // 开启IO时钟
  14. rcu_periph_clock_enable(RCU_TRIG);
  15. rcu_periph_clock_enable(RCU_ECHO);
  16. // 设置TRIG引脚
  17. gpio_mode_set(PORT_TRIG,GPIO_MODE_OUTPUT,GPIO_PUPD_PULLUP,GPIO_TRIG);
  18. gpio_output_options_set(PORT_TRIG,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_TRIG);
  19. gpio_bit_write(PORT_TRIG,GPIO_TRIG,RESET);
  20. // 设置ECHO引脚
  21. gpio_mode_set(PORT_ECHO,GPIO_MODE_INPUT,GPIO_PUPD_NONE,GPIO_ECHO);
  22. gpio_bit_write(PORT_ECHO,GPIO_ECHO,RESET);
  23. }
  24. void bsp_ultrasonic_init(void){
  25. bsp_ultrasonic_gpio_init();
  26. }
  27. float bsp_ultrasonic_get(){
  28. // 连续测量5次 取平均值
  29. float distance = 0;
  30. uint8_t i = 0;
  31. uint8_t count = 5;
  32. while(i<count){
  33. // 先将trig 拉高 10us以上
  34. gpio_bit_write(PORT_TRIG,GPIO_TRIG,SET);
  35. // 持续10us以上
  36. delay_1us(20);
  37. // 再拉低,超声波就发射出去了,同时Echo引脚的电平又0变为1
  38. gpio_bit_write(PORT_TRIG,GPIO_TRIG,RESET);
  39. // 当超声波发送出去之后,ECHO由0变为1
  40. while(gpio_input_bit_get(PORT_ECHO,GPIO_ECHO) == RESET);
  41. // 发送成功
  42. bsp_timer_open();
  43. // 当超声波返回时, ECHO由1变为0
  44. while(gpio_input_bit_get(PORT_ECHO,GPIO_ECHO) == SET);
  45. // 关闭定时器
  46. bsp_timer_close();
  47. // 获取高电平的时长
  48. uint32_t time = bsp_timer_get(); // 单位us
  49. /** 计算距离
  50. * 声音在空气中的传播速度是343m/s
  51. * 34300cm/1000ms
  52. * 34300cm/1000 000us
  53. * 0.0343cm/us
  54. */
  55. distance += 0.0343*time/2;
  56. // 延时10ms
  57. delay_1ms(10);
  58. i++;
  59. }
  60. return distance/5;
  61. }

练习题

  1. 实现超声波测距驱动