搜索

[RISC-V MCU 应用开发] 第九十七章、CH32V103应用教程——超声波测距

[复制链接]
198|12
RISCVLAR|  楼主 | 2021-5-25 20:30 | 显示全部楼层 |阅读模式
CH32V103应用教程——超声波测距

本章教程主要通过使用CH32V103开发板连接超声波测距模块进行超声波测距实验。本次实验教程所用传感器为HC-SR04超声波传感器。

1、TIM简介及超声波测距原理简介
关于TIM,在前面章节已经进行过介绍,在此不再赘述。
HC-SR04超声波传感器模块共有4个引脚可与开发板连接:VCC、GND、Trig、Echo。其中,VCC支持3.3V-5V供电;Trig引脚作为控制端,其内部上拉10K的电阻,需用单片机的IO口拉低Trig引脚,然后给一个10us以上的脉冲信号。Echo引脚作为接收端,主要接收返回信号。
关于超声波模块测距原理,主要如下:
(1)通过单片机IO口触发测距,给(Trig引脚)至少10us以上的高电平信号;
(2)模块会自动发送8个40KHz的方波,并自动检测是否有信号返回;
(3)针对这个模块Echo是输出,接下来它会自动接收超声波,并且接收完后在Echo这个输出脚上输出一段高电平,这个高电平的时间就是声波发出并且反射回来所用的时间,所以我们在单片机中就需要读取这个引脚。此处需要用到定时器的输入捕获功能。
超声波从发射到返回的时间,测试距离D=(高电平时间T*声速340m/s)/2.
关于TIM具体介绍,可参考前面章节及CH32V103应用手册。

2、硬件设计
本章教程使用超声波模块进行测距。CH32V103开发板与超声波测距模块的连接方式如下:
  • CH32V103开发板的VCC引脚与超声波测距模块的VCC引脚连接
  • CH32V103开发板的GND引脚与超声波测距模块的GND引脚连接
  • CH32V103开发板的PA0引脚与超声波测距模块的Trig引脚连接
  • CH32V103开发板的PA1引脚与超声波测距模块的Echo引脚连接

3软件设计
本章教程主要进行超声波测距实验,需要用到GPIO输出以及TIM输入捕获功能,具体程序如下:
gpio.h文件
  1. #ifndef __GPIO_H
  2. #define __GPIO_H

  3. #include "ch32v10x_conf.h"

  4. #define  Trig_H  GPIO_SetBits(GPIOA,GPIO_Pin_0)
  5. #define  Trig_L  GPIO_ResetBits(GPIOA,GPIO_Pin_0)

  6. #define  Echo_H  GPIO_SetBits(GPIOA,GPIO_Pin_1)
  7. #define  Echo_L  GPIO_ResetBits(GPIOA,GPIO_Pin_1)

  8. void ultrasonic_GPIO_Init(void);
  9. void Start_Trig(void);

  10. #endif
复制代码
gpio.h文件主要进行相关定义和函数声明;
gpio.c文件

  1. #include "gpio.h"
  2. #include "debug.h"

  3. void ultrasonic_GPIO_Init(void)
  4. {
  5.     GPIO_InitTypeDef  GPIO_InitStructure;

  6.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

  7.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  8.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  9.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  10.     GPIO_Init(GPIOA,&GPIO_InitStructure);

  11.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  12.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  13.     GPIO_Init( GPIOA, &GPIO_InitStructure);

  14.     GPIO_ResetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1);
  15. }

  16. void Start_Trig(void)
  17. {
  18.     Trig_H;
  19.     Delay_Us(20);
  20.     Trig_L;
  21. }
复制代码
gpio.c文件主要进行GPIO初始化以及进行开启超声波测距函数配置。
tim.h文件
  1. #ifndef __TIMER_H
  2. #define __TIMER_H

  3. #include "ch32v10x_conf.h"

  4. void Input_Capture_Init( u16 arr, u16 psc );
  5. void ENABLE_TIM(void);
  6. void DISABLE_TIM(void);
  7. u32 GetCount(void);
  8. float Ultrasoniclength(void);

  9. #endif
复制代码
tim.h文件主要进行相关定义和函数声明;
tim.c文件

  1. #include "timer.h"
  2. #include "gpio.h"
  3. #include "debug.h"

  4. void TIM2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));

  5. u16 count = 0;

  6. /*******************************************************************************
  7. * Function Name  : Input_Capture_Init
  8. * Input          : arr: the period value.
  9. *                  psc: the prescaler value.
  10. * Return         : None
  11. *******************************************************************************/
  12. void Input_Capture_Init( u16 arr, u16 psc )
  13. {
  14.     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  15.     NVIC_InitTypeDef        NVIC_InitStructure;

  16.     //使能IM2时钟
  17.     RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE);

  18.     ultrasonic_GPIO_Init();

  19.     TIM_DeInit(TIM2);
  20.     //定时器周期,实际就是设定自动重载寄存器 ARR 的值, ARR 为要装载到实际自动重载寄存器(即影子寄存器) 的值, 可设置范围为 0 至 65535。
  21.     TIM_TimeBaseInitStructure.TIM_Period = arr;
  22.     //定时器预分频器设置,时钟源经该预分频器才是定时器计数时钟CK_CNT,它设定 PSC 寄存器的值。
  23.     //计算公式为: 计数器时钟频率 (fCK_CNT) 等于fCK_PSC / (PSC[15:0] + 1),可实现 1 至 65536 分频。
  24.     TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
  25.     //时钟分频,设置定时器时钟 CK_INT 频率与死区发生器以及数字滤波器采样时钟频率分频比。可以选择 1、 2、 4 分频。
  26.     TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  27.     TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置计数模式,向上计数模式
  28.     //TIM_TimeBaseInitStructure.TIM_RepetitionCounter =  0x00;      //设置重复计数器的值,0。重复计数器,只有 8 位,只存在于高级定时器。
  29.     TIM_TimeBaseInit( TIM2, &TIM_TimeBaseInitStructure);            //初始化

  30.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  31.     NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;          //TIM1捕获比较中断
  32.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//设置抢占优先级
  33.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;       //设置响应优先级
  34.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;          //使能通道
  35.     NVIC_Init(&NVIC_InitStructure);

  36.     TIM_ClearFlag(TIM2, TIM_FLAG_Update);
  37.     TIM_ITConfig( TIM2, TIM_IT_Update, ENABLE ); //使能TIM2更新中断
  38.     TIM_Cmd( TIM2, DISABLE );                    //定时器使能
  39. }

  40. void ENABLE_TIM(void)
  41. {
  42.     //while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)==RESET)
  43.     {
  44.         TIM_SetCounter(TIM2,0);
  45.         count = 0;
  46.         TIM_Cmd(TIM2,ENABLE);//回响信号到来,开启定时器计数
  47.     }
  48. }

  49. void DISABLE_TIM(void)
  50. {
  51.     //while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)==SET)
  52.     {
  53.         TIM_Cmd(TIM2,DISABLE);//回响信号到来,开启定时器计数
  54.     }
  55. }

  56. u32 GetCount(void)
  57. {
  58.     u32 t = 0;
  59.     t = count*1000;
  60.     t += TIM_GetCounter(TIM2);
  61.     TIM_SetCounter(TIM2,0);
  62.     Delay_Ms(10);
  63.     return t;
  64. }

  65. //一次获取超声波测距数据 两次测距之间需要相隔一段时间,隔断回响信号
  66. //为了消除余震的影响,取五次数据的平均值进行加权滤波。
  67. float Ultrasoniclength(void )
  68. {
  69.     u32 t = 0;
  70.     int i = 0;
  71.     float length = 0 , sum = 0;
  72.     while(i!=5)
  73.     {
  74. //       Trig_H;
  75. //       Delay_Us(20);
  76. //       Trig_L;
  77.        Start_Trig();
  78.        while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)==RESET);  //此处一直等,等到为1,进行下一步
  79.        ENABLE_TIM();//回响信号到来,开启定时器计数
  80.        i = i + 1;
  81.        while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)==SET);  //此处一直等,等到为0,进行下一步,这两段while之间的时间就是高电平时间,即发出到返回接收的时间
  82.        DISABLE_TIM();//回响信号到来,开启定时器计数
  83.        t = TIM_GetCounter(TIM2);
  84.        length=(t+count*1000)/58.0;//通过回响信号计算距离
  85.        sum = length + sum ;
  86.        TIM_SetCounter(TIM2,0);
  87.        count = 0;
  88.        Delay_Ms(100);
  89.      }
  90.      length = sum/5.0;
  91.      return length;
  92. }

  93. /*******************************************************************************
  94. * Function Name  : TIM2_IRQHandler
  95. *******************************************************************************/
  96. void TIM2_IRQHandler(void)
  97. {
  98.     if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
  99.     {
  100.         TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中断标志
  101.         count++;
  102.     }
  103. }
复制代码
tim.c文件主要进行TIM输入捕获初始化以及超声波测距相关函数配置。
main.c文件
  1. /********************************** (C) COPYRIGHT *******************************
  2. * File Name          : main.c
  3. * Author             : WCH
  4. * Version            : V1.0.0
  5. * Date               : 2020/04/30
  6. * Description        : Main program body.
  7. *******************************************************************************/

  8. /*
  9. *@Note
  10. 超声波测距模块
  11. */

  12. #include "debug.h"
  13. #include "gpio.h"
  14. #include "timer.h"

  15. /*******************************************************************************
  16. * Function Name  : main
  17. * Description    : Main program.
  18. * Input          : None
  19. * Return         : None
  20. *******************************************************************************/
  21. int main(void)
  22. {
  23.     float distance = 0;

  24.         Delay_Init();
  25.         USART_Printf_Init(115200);

  26.         //ultrasonic_GPIO_Init();
  27.         Input_Capture_Init(1000-1,72-1);

  28.         printf("SystemClk:%d\r\n",SystemCoreClock);
  29.         printf("This is Ultrasonic ranging example\r\n");

  30.         while(1)
  31.         {
  32.             distance = Ultrasoniclength();  //cm
  33.             printf("DISTANCE:%3.2f cm\n",distance);
  34.             Delay_Ms(1000);
  35.         }
  36. }
复制代码
main.c文件主要进行函数初始化以及打印输出模块测量的距离。

4下载验证
将编译好的程序下载到开发版并复位,与超声波测距模块接好之后串口打印如下:
图片1.png

  

96、超声波测距.rar

579.78 KB, 下载次数: 4

使用特权

评论回复

相关帖子

xinxianshi| | 2021-5-31 15:24 | 显示全部楼层
这个经常在遥控车比赛中用到的技术,学习学习软件操作方法。

使用特权

评论回复
laocuo1142| | 2021-6-2 10:46 | 显示全部楼层
用超声波来探测距离还是蛮厉害的

使用特权

评论回复
usysm| | 2021-6-12 10:30 | 显示全部楼层
没有做超时处理吗      

使用特权

评论回复
typeof| | 2021-6-12 10:31 | 显示全部楼层
推荐捕获的方式。

使用特权

评论回复
yujielun| | 2021-6-12 10:31 | 显示全部楼层
定时器计时准确吗   

使用特权

评论回复
htmlme| | 2021-6-12 10:32 | 显示全部楼层
超声波不是支持5V吗?

使用特权

评论回复
pklong| | 2021-6-12 10:32 | 显示全部楼层
超声波测距模块还是不错的。      

使用特权

评论回复
touser| | 2021-6-12 10:33 | 显示全部楼层
us的延时使用的是什么?   

使用特权

评论回复
myiclife| | 2021-6-12 10:33 | 显示全部楼层
Start_Trig()这个代码在哪里呢   

使用特权

评论回复
uytyu| | 2021-6-12 10:33 | 显示全部楼层
看着这个代码好熟悉,在csdn上有很多。   

使用特权

评论回复
iyoum| | 2021-6-12 10:33 | 显示全部楼层
模块化开发与设计。            

使用特权

评论回复
jkl21| | 2021-6-12 10:33 | 显示全部楼层
HC-SR04精度不是很好         

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 我要提问 投诉建议 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

本版热帖

本版活跃用户

优质原创写原创,赢大奖

编辑推荐

  • 1 wolfe_yu 得到打赏 ¥180.00
  • 2 最美葫芦娃 得到打赏 ¥155.00
  • 3 hk386 得到打赏 ¥75.00
  • 4 火星国务卿 得到打赏 ¥63.00
  • 5 两只袜子 得到打赏 ¥56.00
  • 6 laocuo1142 得到打赏 ¥50.00
  • 7 linghz 得到打赏 ¥45.00
  • 8 gaon2 得到打赏 ¥45.00
  • 9 ezcui 得到打赏 ¥45.00
  • 10 jlc317 得到打赏 ¥40.00
在线客服 快速回复 返回顶部 返回列表