板子是 FRDM-MCXA153,配合 HC-SR04 超声波模块和一块 SSD1306 OLED,做一个简易测距仪。目前测距和显示这两块底层已经跑通,还在面包板上飞线。
超声波测距的原理其实不复杂。Trig 给一个十微秒左右的高电平,模块发一串四十千赫兹的脉冲出去,Echo 拉高,高电平持续的时间就是声波从发射到碰到东西再回来的总时间。声速常温下大约三百四十米每秒,除个二、再换算一下单位,就得到距离。常用的近似是距离(厘米)等于 Echo 高电平时间(微秒)除以五十八。
实现上关键是把 Echo 的脉宽测准。我用定时器计数,上升沿开始计,下降沿读差值。Trig 那边先拉低一下再给高电平,避免上一次的余波影响这一次。
static uint32_t ultrasonic_measure(void)
{
echo_ready = 0;
trig_pulse();
uint32_t t0 = systick_ms;
while (!echo_ready) {
if (systick_ms - t0 > 30) return 0;
}
return echo_count / 58;
}OLED 那边走的是软件 I2C。大部分代码移植的是之前写的STM32上的驱动程序。原理就是用 GPIO 手动模拟时序,Start、发八位、第九个时钟读 SDA 看应答、Stop。SSD1306 的屏幕是按页组织的,一百二十八乘六十四分八页,每页一百二十八列。命令和数据用不同的控制字节区分开,命令是零,数据是四十。开机的时候顺便加了一段 I2C 扫描,读得到应答就打印从机地址。
static void i2c_start(void)
{
sda_high(); scl_high(); i2c_delay();
sda_low(); i2c_delay();
scl_low(); i2c_delay();
}
static uint8_t i2c_write_byte(uint8_t data)
{
for (uint8_t i = 0; i < 8; i++) {
scl_low();
if (data & 0x80) sda_high(); else sda_low();
data <<= 1;
i2c_delay();
scl_high();
i2c_delay();
}
scl_low();
sda_dir_input();
i2c_delay();
scl_high();
i2c_delay();
uint8_t ack = sda_read();
scl_low();
sda_dir_output();
i2c_delay();
return ack;
}测出来的数据会跳,直接显示不好看。现在先做五点中值滤波,把明显跳变的点剔掉,再做一阶滞后滤波平滑。按键这边用非阻塞轮询,一毫秒查一次,二十五毫秒消抖,下降沿触发一次,SW3 切单位,SW2 切显示样式。

目前测距和显示跑通了,滤波和按键也接上了。接下来准备联动起来。
我要赚赏金
