樊涵菡 发表于 2025-6-11 15:55:34

STM8开发实战:HC-SR04超声波测距仪

前言


[*]在经过前期理论的学习,懂得如何使用单片机的各项外设之后,我们便可以想做什么就做什么了,本文以制作一个基于HC-SRO4超声波测距模块的测距仪为例子,演示怎样通过单片机的各项外设来控制各种功能的外围电路,从而实现我们想要的各种功能
[*]本程序已开源,提供了STM8S105C6与STM8S003F3两个版本的代码,开源地址:https://github.com/artless-artist/STM8_UltrasonicRangefinder
准备工作

硬件


[*]HC-SR04超声波测距模块
[*]0.96寸OLED屏幕(集成了SSD1306显示驱动芯片)
[*]STM8S,推荐使用STM8S105C6这样的高级型号,若使用内存较小的型号会遇到开发困难
软件


[*]使用IAR开发
HR-SR04超声波测距模块

工作原理


[*]超声波测距原理

超声波模块会在触发测距后发射8个40khz的方波(这是为了让声波独特,避免与环境中的其他信号混淆),从声波接触到被测物体时就会被反射回来,被模块接收
那么,从发射声波到接收到反射声波的用时除以2就是声音从模块传播到被测物体所用的时间,再将这个时间乘以声速就是距离了
[*]HC-SR04工作时序

1.在TRIG引脚上给至少10us的高电平信号后触发测距;
2.触发测距后模块自动发送8个40khz的方波,自动检测是否有信号返回;
3.若有信号返回,通过ECHO引脚输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。
STM8控制原理

<ul>设计思路


[*]从工作时序来看,我们需要让STM8的一个引脚作为TRIG,输出高电平触发测距;另外需要一个ECHO引脚被配置为输入模式,用以测量超声波模块的ECHO引脚返回的高电平持续时间
[*]测量ECHO引脚高电平持续时间是整个功能实现的核心,我们很容易想到通过STM8的定时器外设来实现这一点,具体方法如下:
使用基本型定时器


[*]使用任意定时器的计时功能,在返回高电平信号后开始计时,当返回信号变回低电平后结束计时,并计算
[*]由于适用轮询的数据传输方式,将单片机主频设置为16MHz以提高运行速度,而又由于计数值有限,为了扩展测量范围,设定TIM4预分频系数为128,让计数值每8us加一
//使用TIM4进行计时
void TIM4_Init(void)
{
        TIM4_PSCR = 0x07;   // 预分频器128,16MHz/128=125kHz(8us)
        TIM4_ARR = 255;   // 自动重装载值
        TIM4_CNTR = 0;      // 计数器清零
        TIM4_CR1 |= 0x01;   // 使能计数器
}
//详细的宏定义、初始化代码受限篇幅省略,需要完整驱动请到开源地址中查看
float HC_SR04_GetDistance(void)
{
        float time = 0;
        float distance = 0;

        // 发送10us的高电平触发信号
        TRIG = 1;
        Delay_us(15);       // 延时一段时间保证触发测距
        TRIG = 0;

        // 等待回波信号变高
        while(ECHO == 0);
        // 开始计时
        TIM4_CNTR = 0;
        // 等待回波信号变低
        while(ECHO == 1);

        // 获取计时值
        time = TIM4_CNTR * 8;
        distance = time * (0.0331 + 0.00006*temperature) /2;
        //声速加入温度补偿系数后的计算公式,单位为厘米
        return distance;
}使用高级计时器的输入捕获功能


[*]我们的需求是在对信号的高电平持续时间进行测量,也就是在低电平变为高电平时从零开始计时,而高电平变回低电平时,这显然与我们曾学习过的定时器输入捕获与复位触发功能不谋而合,我们曾用这个功能进行信号占空比的测量
//使用TIM1输入捕获的复位触发模式对echo引脚返回的高电平持续时间进行测量void TIM1_Init(void){        TIM1_PSCRH = 0x00;        TIM1_PSCRL = 0x02;        TIM1_ARRH = 0xFF;        TIM1_ARRL = 0xFF;        //利用输入时TIx产生的两路相同信号TIxFP1和TIxFP2,对上边沿与下边沿进行检测        TIM1_CCMR1 = 0x01;//CC1S=01 TI1FP1连接到IC1        TIM1_CCMR2 = 0x02;//CC2S=10 TI1FP2连接到IC2        TIM1_CCER1_CC1P = 0;      //检测TI1FP1上升沿        TIM1_CCER1_CC2P = 1;      //检测TI1FP2下降沿        TIM1_SMCR = 0x54;   //TS=101(TI1FP1为触发信号), SMS=100(复位触发模式)        //从TI1的上升沿触发复位,在捕获到TI2的下降沿时        TIM1_CCER1 |= 0x11;    //使能两个捕获        TIM1_CR1 = 0x01;    // 使能计数器}float HC_SR04_GetDistance(void){        TIM1_SR1 &= 0xF9; //清除CC1IF和CC2IF标志位        TIM1_CCER1 |= 0x11; //开启捕获功能        float time = 0;        float distance = 0;        u16 pulse_width = 0;        // 发送高电平触发信号        TRIG = 1;        Delay_us(15);        TRIG = 0;        while((TIM1_SR1&0x02)==0); //等待捕获比较标志位CC1IF变为1(上升沿)        while((TIM1_SR1&0x04)==0); //等待捕获比较标志位CC2IF变为1(下降沿)        //IC1检测到上升沿时复位计时,到IC2检测到下降沿时即高电平脉宽        pulse_width = (u16)TIM1_CCR2H
页: [1]
查看完整版本: STM8开发实战:HC-SR04超声波测距仪