昆仑山

首页 » 问答 » 问答 » RTThread传感器驱动开发指南
TUhjnbcbe - 2023/7/23 19:20:00

概述

目的与概述

本文档为RT-ThreadSensor驱动框架下传感器驱动的开发指南文档,给开发团队提供开发标准和规范。

阅读对象

进行传感器驱动开发的工程人员注意事项:在阅读本篇文档之前,请先翻阅历史文章查看传感器驱动框架介绍。

开发指南

开发一个传感器驱动一般需要下面的几个步骤:调研与准备、开发、测试、提交。

开发过程可以参考已经支持的传感器,如果需要获取传感器列表请直接留言即可。

调研与准备

根据datasheet或其他途径,了解传感器的特性,并记录下来,如下面几种:

传感器类型通讯接口(i2c/spi/…)测量范围最短测量周期支持几种工作模式、电源模式开发

开发的主要任务就是对接Sensor驱动框架的ops接口,然后注册为Sensor设备,进而能够通过驱动框架控制传感器的相关行为。

ops接口对接

sensor框架共给出了两个接口(

fetch_data

/

control

),需要在驱动中实现这两个接口。

fetchdata

作用:获取传感器的数据。接口原型:

1rt_size_t(*fetch_data)(structrt_sensor_device*sensor,void*buf,rt_size_tlen);

Sensor驱动框架当前默认支持轮询(POLLING)、中断(INT)、FIFO这三种工作模式。如果要开发的传感器支持

中断

FIFO

的工作模式,需要在这里判断传感器的工作模式,然后再根据不同的模式返回传感器数据。

如下所示:

1staticrt_size_txxx_acc_fetch_data(structrt_sensor_device*sensor,void*buf,rt_size_tlen)2{3if(sensor-config.mode==RT_SENSOR_MODE_POLLING)4{5return_xxx_acc_polling_get_data(sensor,buf,len);6}7elseif(sensor-config.mode==RT_SENSOR_MODE_INT)8{9return_xxx_acc_int_get_data(sensor,buf,len);10}11elseif(sensor-config.mode==RT_SENSOR_MODE_FIFO)12{13return_xxx_acc_fifo_get_data(sensor,buf,len);14}15else16return0;17}

开发人员在返回数据时应先标识存储数据的数据类型,然后再填充数据域与时间戳,如下所示:

1sensor_data-type=RT_SENSOR_CLASS_ACCE2sensor_data-data.acce.x=acceleration.x;3sensor_data-data.acce.y=acceleration.y;4sensor_data-data.acce.z=acceleration.z;5sensor_data-timestamp=rt_sensor_get_ts();

注意事项

-时间戳的获取函数请使用Sensor驱动框架提供的时间戳获取函数

rt_sensor_get_ts

-在FIFO模式下底层数据可能会有耦合,需要使用module,同时更新两个传感器的数据。-要将数据的单位转换为Sensor驱动框架里规定的数据单位。

数据单位参考如下:

注:后期会迭代增加新的传感器数据单位。

control

1rt_err_t(*control)(structrt_sensor_device*sensor,intcmd,void*arg);

传感器的控制就是依靠这个接口函数实现的,通过判断传入的命令字的不同执行不同的操作,目前支持以下命令字:

1#defineRT_SENSOR_CTRL_GET_ID(0)/*读设备ID*/2#defineRT_SENSOR_CTRL_GET_INFO(1)/*获取设备信息(由框架实现,在驱动中不需要实现)*/3#defineRT_SENSOR_CTRL_SET_RANGE(2)/*设置传感器测量范围*/4#defineRT_SENSOR_CTRL_SET_ODR(3)/*设置传感器数据输出速率,unitisHZ*/5#defineRT_SENSOR_CTRL_SET_MODE(4)/*设置工作模式*/6#defineRT_SENSOR_CTRL_SET_POWER(5)/*设置电源模式*/7#defineRT_SENSOR_CTRL_SELF_TEST(6)/*自检*/

需要在驱动里实现这个函数,如下所示:

1staticrt_err_txxx_acc_control(structrt_sensor_device*sensor,intcmd,void*args)2{3rt_err_tresult=RT_EOK;45switch(cmd)6{7caseRT_SENSOR_CTRL_GET_ID:8result=_xxx_acc_get_id(sensor,args);9break;10caseRT_SENSOR_CTRL_SET_RANGE:11result=_xxx_acc_set_range(sensor,(rt_int32_t)args);12break;13caseRT_SENSOR_CTRL_SET_ODR:14result=_xxx_acc_set_odr(sensor,(rt_uint32_t)args0xffff);15break;16caseRT_SENSOR_CTRL_SET_MODE:17result=_xxx_acc_set_mode(sensor,(rt_uint32_t)args0xff);18break;19caseRT_SENSOR_CTRL_SET_POWER:20result=_xxx_acc_set_power(sensor,(rt_uint32_t)args0xff);21break;22caseRT_SENSOR_CTRL_SELF_TEST:23break;24default:25return-RT_ERROR;26}27returnresult;28}

注意事项:

这里需要注意传来参数的数据类型是由structrt_sensor_config这个结构体规定的,因此

RT_SENSOR_CTRL_SET_RANGE

这个命令传来的参数是

rt_int32_t

类型的,需要经过强转一次,才可以得到正确的参数。

然后实现一个设备接口的结构体ops存储上面的接口函数,

1staticstructrt_sensor_opsxxx_ops=2{3xxx_acc_fetch_data,4xxx_acc_control5};

设备注册

完成Sensor的ops的对接之后还要注册一个sensor设备,这样上层才能找到这个传感器设备,进而进行控制。

设备的注册一般需要这样的步骤:创建一个rt_sensor_t的结构体指针,然后为结构体分配内存,并完成相关初始化,最后调用rt_hw_sensor_register完成传感器设备的注册。

1intrt_hw_xxx_init(constchar*name,structrt_sensor_config*cfg)2{3rt_int8_tresult;4rt_sensor_tsensor=RT_NULL;56sensor=rt_calloc(1,sizeof(structrt_sensor_device));7if(sensor==RT_NULL)8return-1;sensor-info.type=RT_SENSOR_CLASS_ACCE;11sensor-info.vendor=RT_SENSOR_VENDOR_STM;12sensor-info.model=xxx_acce;13sensor-info.unit=RT_SENSOR_UNIT_MG;14sensor-info.intf_type=RT_SENSOR_INTF_I2C;15sensor-info.range_max=SENSOR_ACC_RANGE_16G;16sensor-info.range_min=SENSOR_ACC_RANGE_2G;17sensor-info.period_min=;rt_memcpy(sensor-config,cfg,sizeof(structrt_sensor_config));20sensor-ops=sensor_ops;result=rt_hw_sensor_register(sensor,name,RT_DEVICE_FLAG_RDWR

RT_DEVICE_FLAG_FIFO_RX,RT_NULL);23if(result!=RT_EOK)24{25LOG_E(deviceregistererrcode:%d,result);26rt_free(sensor);27return-RT_ERROR;28}LOG_I(accsensorinitsuccess);31return0;32}

注意事项:

-

rt_hw_sensor_register

会为传入的name自动添加前缀,如

加速度计

类型的传感器会自动添加

acce_

的前缀。由于系统默认的设备名最长为7个字符,因此如果传入的名称超过3个字符的话会被裁掉。-注册时如传感器支持FIFO的话,需要添加RT_DEVICE_FLAG_FIFO_RX的标志位。-如果两个设备有耦合的话,需要利用module解耦。初始化一个module,将两个传感器的设备控制块赋值到里面,并将module的地址赋值给两个传感器设备。框架会自动完成module锁的创建。

其中传入参数

structrt_sensor_config*cfg

是用来解耦硬件的通讯接口的,通过在底层驱动初始化的时候传入这个参数,实现硬件接口的配置。里面包含

structrt_sensor_intf

这个结构体,

1structrt_sensor_intf2{3char*dev_name;/*Thenameofthe

1
查看完整版本: RTThread传感器驱动开发指南