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]