Thread传感器驱动开发指南
时间:2019-03-05 18:41 来源:百度新闻 作者:巧天工 点击:次
开发指南 开发一个传感器驱动一般需要下面的几个步骤:调研与准备、开发、测试、提交。 开发过程可以参考已经支持的传感器,如果需要获取传感器列表请直接留言即可。 调研与准备 根据 datasheet 或其他途径,传感器的特性,并记录下来,如下面几种: 传感器类型通讯接口(i2c/spi/…)测量范围最短测量周期支持几种工作模式、电源模式开发 开发的主要任务就是对接 Sensor 驱动框架的 ops 接口,然后注册为 Sensor 设备,进而能够通过驱动框架控制传感器的相关行为。 ops 接口对接 sensor 框架共给出了两个接口( fetch_data / control ),需要在驱动中实现这两个接口。 fetchdata 作用: 获取传感器的数据。接口原型: 1rt_size_t (*fetch_data)(struct rt_sensor_deice *sensor, oid *buf, rt_size_t len); Sensor 驱动框架当前默认支持 轮询(POLLING)、中断(INT)、FIFO 这三种工作模式。如果要开发的传感器支持 中断 和 FIFO 的工作模式,需要在这里判断传感器的工作模式,然后再根据不同的模式返回传感器数据。 如下所示: 1static rt_size_t xxx_acc_fetch_data(struct rt_sensor_deice *sensor, oid *buf, rt_size_t len)2{ 3 if (sensor->config.mode == RT_SENSOR_MODE_POLLING) 4 { 5 return _xxx_acc_polling_get_data(sensor, buf, len); 6 } 7 else if (sensor->config.mode == RT_SENSOR_MODE_INT) 8 { 9 return _xxx_acc_int_get_data(sensor, buf, len);10 }11 else if (sensor->config.mode == RT_SENSOR_MODE_FIFO)12 {13 return _xxx_acc_fifo_get_data(sensor, buf, len);14 }15 else16 return 0;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)(struct rt_sensor_deice *sensor, int cmd, oid *arg); 传感器的控制就是依靠这个接口函数实现的,通过判断传入的命令字的不同执行不同的操作,目前支持以下命令字: 1#define RT_SENSOR_CTRL_GET_ (0) /* 读设备 */2#define RT_SENSOR_CTRL_GET_INFO (1) /* 获取设备信息(由框架实现,在驱动中不需要实现)*/3#define RT_SENSOR_CTRL_SET_RANGE (2) /* 设置传感器测量范围 */4#define RT_SENSOR_CTRL_SET_ODR (3) /* 设置传感器数据输出速率,unit is HZ */5#define RT_SENSOR_CTRL_SET_MODE (4) /* 设置工作模式 */6#define RT_SENSOR_CTRL_SET_POWER (5) /* 设置电源模式 */7#define RT_SENSOR_CTRL_SELF_TEST (6) /* 自检 */ 需要在驱动里实现这个函数,如下所示: 1static rt_err_t xxx_acc_control(struct rt_sensor_deice *sensor, int cmd, oid *args)2{ 3 rt_err_t result = RT_EOK; 4 5 switch (cmd) 6 { 7 case RT_SENSOR_CTRL_GET_: 8 result = _xxx_acc_get_id(sensor, args); 9 break;10 case RT_SENSOR_CTRL_SET_RANGE:11 result = _xxx_acc_set_range(sensor, (rt_int32_t)args);12 break;13 case RT_SENSOR_CTRL_SET_ODR:14 result = _xxx_acc_set_odr(sensor, (rt_uint32_t)args & 0xffff);15 break;16 case RT_SENSOR_CTRL_SET_MODE:17 result = _xxx_acc_set_mode(sensor, (rt_uint32_t)args & 0xff);18 break;19 case RT_SENSOR_CTRL_SET_POWER:20 result = _xxx_acc_set_power(sensor, (rt_uint32_t)args & 0xff);21 break;22 case RT_SENSOR_CTRL_SELF_TEST:23 break;24 default:25 return -RT_ERROR;26 }27 return result;28} 注意事项: 这里需要注意传来参数的数据类型是由 struct rt_sensor_config 这个结构体规定的,因此 RT_SENSOR_CTRL_SET_RANGE 这个命令传来的参数是 rt_int32_t 类型的,需要经过强转一次,才可以得到正确的参数。 然后 实现一个设备接口的结构体 ops 存储上面的接口函数, 1static struct rt_sensor_ops xxx_ops =2{3 xxx_acc_fetch_data,4 xxx_acc_control5}; 设备注册 完成 Sensor 的 ops 的对接之后还要注册一个 sensor 设备,这样上层才能找到这个传感器设备,进而进行控制。 设备的注册一般需要这样的步骤:创建一个 rt_sensor_t 的结构体指针,然后为结构体分配内存,并完成相关初始化,最后调用 rt_hw_sensor_register 完成传感器设备的注册。 1int rt_hw_xxx_init(const char *name, struct rt_sensor_config *cfg)2{ 3 rt_int8_t result; 4 rt_sensor_t sensor = RT_NULL; 5 6 sensor = rt_calloc(1, sizeof(struct rt_sensor_deice)); 7 if (sensor == RT_NULL) 8 return -1; 910 sensor->info.type = RT_SENSOR_CLASS_ACCE;11 sensor->info.endor = RT_SENSOR_ENDOR_STM;12 sensor->info.model = "xxx_acce";13 sensor->info.unit = RT_SENSOR_UNIT_MG;14 sensor->info.intf_type = RT_SENSOR_INTF_I2C;15 sensor->info.range_max = SENSOR_ACC_RANGE_16G;16 sensor->info.range_min = SENSOR_ACC_RANGE_2G;17 sensor->info.period_min = 100;1819 rt_memcpy(&sensor->config, cfg, sizeof(struct rt_sensor_config));20 sensor->ops = &sensor_ops;2122 result = rt_hw_sensor_register(sensor, name, RT_DEICE_FLAG_RDWR | RT_DEICE_FLAG_FIFO_RX, RT_NULL);23 if (result != RT_EOK)24 {25 LOG_E("deice register err code: %d", result);26 rt_free(sensor);27 return -RT_ERROR;28 }2930 LOG_I("acc sensor init success");31 return 0;32} 注意事项: - rt_hw_sensor_register 会为传入的 name 自动添加前缀,如 加速度计 类型的传感器会自动添加 acce_ (责任编辑:波少) |