摘要:本文为你带来 LiteOS 基于 Sensorhub 的超声波模组移植的应用。
1、Sensor Hub
LiteOS 传感框架即 Sensor Hub,是一个基于 Huawei LiteOS 物联网操作系统的传感器管理框架。
随着物联网的发展,物联网终端越来越智能化,例如在个人穿戴、智能家居、家用医疗等终端上将配置越来越多的传感器,来获取更多传感数据,使终端更加智能,使得开发和维护变得复杂和困难。LiteOS 传感框架将物联网终端设备上例如加速计(Accelerometer)、陀螺仪(Gyroscope)、气压仪(Barometer)、温湿度计(Humidometer)等不同类型的传感器统一管理,通过抽象不同类型传感器接口,屏蔽其硬件细节,做到“硬件”无关性,非常方便于物联网设备的开发、维护和功能扩展。
LiteOS 传感框架主要包括了 Sensor Manager、BSP manager,Converged Algorithms。
Sensor Manager:统一的传感器交互管理,如 Sensor 的配置、采样、上报和管理。
BSP Manager:统一的驱动接口,负责 Sensor 驱动管理、电源管理、Sensor 交互管理,如 Sensor 的打开、关闭、读写、数据更新等。
Converged Algorithms:融合算法库(算法基于具体的业务模型),根据具体业务模型,在端侧 MCU 进行算法融合,例如环境监测算法、计步算法等,从传统、简单采集算法升级到智能算法,应用直接调用,提升传感数据的业务精准度,降低数据采集时延。
2、SR04 超声波模组
HC-SR04 超声波测距模块可提供 2cm-400cm 的非接触式距离感测功能,测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。基本工作原理:(1)采用 IO 口 TRIG 触发测距,给至少 10us 的高电平信号;(2)模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回;(3)有信号返回,通过 IO 口 ECHO 输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2;2、实物图:如右图接线,VCC 供 5V 电源,GND 为地线,TRIG 触发控制信号输入,ECHO 回响信号输出等四支线。图一实物图 3、电气参数:电气参数 HC-SR04 超声波模块工作电压 DC 5 V 工作电流 15mA 工作频率 40Hz 最远射程 4m 最近射程 2cm 测量角度 15 度输入触发信号 10uS 的 TTL 脉冲输出回响信号输出 TTL 电平信号,与射程成比例规格尺寸 45*20*15mm。
从时序图表明你只需要提供一个 10uS 以上脉冲触发信号,该模块内部将发出 8 个 40kHz 周期电平并检测回波。一旦检测到有回波信号则输出回响信号。回响信号的脉冲宽度与所测的距离成正比。由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。公式:uS/58=厘米或者 uS/148=英寸;或是:距离=高电平时间*声速(340M/S)/2;建议测量周期为 60ms 以上,以防止发射信号对回响信号的影响。
3、sensorhub 的 HC-SR04 驱动
通过时序图可以完成一个简单的读取传感器的接收程序:(这里用 GPIOA1 和 GPIOA4 举例)
uint32_t hcsr04_read (void)
{
local_time=0;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); // pull the TRIG pin HIGH
delay(2); // wait for 2 us
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); // pull the TRIG pin HIGH
delay(10); // wait for 10 us
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); // pull the TRIG pin low
// read the time for which the pin is high
while (!(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4))); // wait for the ECHO pin to go high
while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4)) // while the pin is high
{
local_time++; // measure time for which the pin is high
delay (1);
}
return local_time * .034/2;
}
复制代码
4、将驱动注册到 SensorHub 上
先写 iO 操作,初始化、打开、关闭和读取数据的操作
STATIC INT32 SR04Init(SensorType *sensor)
{
(VOID)(sensor);
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin : PD11 */
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PD12 PD13 PD14 PD15 */
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
return LOS_OK;
}
STATIC INT32 SR04ReadData(SensorType *sensor)
{
PRINTK("read data\n");
INT32 *data = (INT32 *)sensor->sensorData;
data[0] = hcsr04_read();
return LOS_OK;
}
STATIC INT32 SR04Open(SensorType *sensor, OpenParam *para)
{
UINT32 ret;
(VOID)(para);
SR04 *SR04 = (SR04 *)sensor->priv;
if ((sensor->sensorStat == SENSOR_STAT_OPEN) && (sensor->interval == SR04Period)) {
return LOS_OK;
}
if (SR04->gyroTimerId != INVALID_TIMER_ID) {
ret = LOS_SwtmrDelete(SR04->gyroTimerId);
SR04->gyroTimerId = INVALID_TIMER_ID;
if (ret != LOS_OK) {
PRINT_ERR("delete a timer failed!\n");
return LOS_NOK;
}
}
// creat a timer, first parameter is ticks.
ret = LOS_SwtmrCreate(sensor->interval, LOS_SWTMR_MODE_PERIOD, (SWTMR_PROC_FUNC)GypoTimerFunc, &SR04->gyroTimerId, (UINT32)sensor);
if (ret != LOS_OK) {
PRINT_ERR("creat a timer failed!\n");
return LOS_NOK;
}
ret = LOS_SwtmrStart(SR04->gyroTimerId);
if (ret != LOS_OK) {
PRINT_ERR("start timer err\n");
}
SR04Period = sensor->interval;
PRINTK("SR04 on.\n");
return LOS_OK;
}
STATIC INT32 SR04Close(SensorType *sensor)
{
UINT32 ret;
if (sensor->sensorStat == SENSOR_STAT_CLOSE) {
PRINT_DEBUG("sr04 has been closed\n");
return LOS_OK;
}
__HAL_RCC_GPIOA_CLK_DISABLE();
PRINTK("SR04 off.\n");
return LOS_OK;
}
复制代码
然后将设计的驱动注册到框架上
STATIC struct SensorOperation Sr04Ops = {
.Init = SR04Init,
.Open = SR04Open,
.Close = SR04Close,
.ReadData = SR04ReadData,
};
STATIC SensorType g_sensorSR04 = {
.sensorOp = &Sr04Ops,
.sensorData = &g_SR04Data,
.sensorDataLen = sizeof(g_SR04Data),
.priv = &g_SR04Priv,
.tag = TAG_BEGIN,
.cmd = CMD_CMN_INTERVAL_REQ,
.interval = DEFAULT_INTERVAL,
};
VOID SR04Register(VOID)
{
SensorRegister(&g_sensorSR04);
}
复制代码
将驱动注册到通用 sensor 驱动模块上。今天的代码移植基本完成,后续有传感器和板子进行验证
总结
这个驱动是有问题,就是这个是读取时阻塞的程序,后面试过,需要设计时采用定时器和外部中断完成,可以将这个阻塞的程序改成非阻塞的,效率大大提升,后续讲解如何用定时器和外部触发中断完成这个驱动设计。
点击关注,第一时间了解华为云新鲜技术~
评论