概述
Zephyr在sensor.h中定义了统一的传感器驱动接口,由sensor_sample_fetch从指定传感器读取数据到内存,由sensor_channel_get来获取指fetch的数据。对于传感器阈值通知的情况,Zephyr也提供了sensor_trigger_set,注册callback函数,在传感器打到阈值时被执行。
由于不同的传感器测量物理特性值不一样,同一个传感器也会有不同物理特性测量值,zephyr 将不同的物理量抽象为channel,一个channel对应一个物理测量量。
统一接口
统一API列表
传感器统一接口一共5个1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22//从传感器获取所有数据放到内存
__syscall int sensor_sample_fetch(struct device *dev);
//从传感器获取指定channel的数据到内存
__syscall int sensor_sample_fetch_chan(struct device *dev,
enum sensor_channel type);
//从内存获取指定channel的数据
__syscall int sensor_channel_get(struct device *dev,
enum sensor_channel chan,
struct sensor_value *val);
//设定传感器指定channel的参数,例如采样频率,触发阈值等
__syscall int sensor_attr_set(struct device *dev,
enum sensor_channel chan,
enum sensor_attribute attr,
const struct sensor_value *val);
//设置传感器触发
static inline int sensor_trigger_set(struct device *dev,
struct sensor_trigger *trig,
sensor_trigger_handler_t handler)
统一参数
物理量channel
zephyr在enum sensor_channel定义了几乎所有可测量的物理量1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52enum sensor_channel {
SENSOR_CHAN_ACCEL_X, //X轴加速度,m/s^2
SENSOR_CHAN_ACCEL_Y, //y轴加速度,m/s^2
SENSOR_CHAN_ACCEL_Z, //z轴加速度,m/s^2
SENSOR_CHAN_ACCEL_XYZ, //任意加速度
SENSOR_CHAN_ACCEL_ANY = SENSOR_CHAN_ACCEL_XYZ,
SENSOR_CHAN_GYRO_X, //绕X轴角速度,radians/s
SENSOR_CHAN_GYRO_Y, //绕y轴角速度,radians/s
SENSOR_CHAN_GYRO_Z, //绕z轴角速度,radians/s
SENSOR_CHAN_GYRO_XYZ, //任意角速度
SENSOR_CHAN_GYRO_ANY = SENSOR_CHAN_GYRO_XYZ,
SENSOR_CHAN_MAGN_X, //X轴地磁, Gauss
SENSOR_CHAN_MAGN_Y, //y轴地磁, Gauss
SENSOR_CHAN_MAGN_Z, //z轴地磁, Gauss
SENSOR_CHAN_MAGN_XYZ, //任意轴地磁
SENSOR_CHAN_MAGN_ANY = SENSOR_CHAN_MAGN_XYZ,
SENSOR_CHAN_TEMP, //温度,摄氏度
SENSOR_CHAN_DIE_TEMP, //器件温度,摄氏度
SENSOR_CHAN_AMBIENT_TEMP, //环境温度,摄氏度
SENSOR_CHAN_PRESS, //大气压, 千帕
SENSOR_CHAN_PROX, //距离(靠近)传感器,1表示接近
SENSOR_CHAN_HUMIDITY, //湿度, 百分比
SENSOR_CHAN_LIGHT, //可见光强, lux
SENSOR_CHAN_IR, //红外光强, lux
SENSOR_CHAN_RED, //红色光强,lux
SENSOR_CHAN_GREEN, //绿色光强,lux
SENSOR_CHAN_BLUE, //蓝色光强,lux
SENSOR_CHAN_ALTITUDE, //高度传感器, m
SENSOR_CHAN_PM_1_0, //PM1.0传感器,ug/m^3
SENSOR_CHAN_PM_2_5, //PM2.5传感器,ug/m^3
SENSOR_CHAN_PM_10, //PM2.5传感器,ug/m^3
SENSOR_CHAN_DISTANCE, //距离传感器,m
SENSOR_CHAN_CO2, //CO2传感器, ppm
SENSOR_CHAN_VOC, //VOC传感器, ppm
SENSOR_CHAN_VOLTAGE, //电压, V
SENSOR_CHAN_CURRENT, //电流, A
SENSOR_CHAN_ALL,
};
传感器数据格式
为了避免传递浮点数,zephyr使用结构体来表示一个传感器的浮点测量值1
2
3
4struct sensor_value {
s32_t val1; //整数
s32_t val2; //小数
};
val = val1 + val2 * 10^(-6) 例如1
2
3
4* 0.5: val1 = 0, val2 = 500000
* -0.5: val1 = 0, val2 = -500000
* -1.0: val1 = -1, val2 = 0
* -1.5: val1 = -1, val2 = -500000
传感器参数
一般情况下zephy在编译的时候就已经确定传感器的工作参数,但也存在运行时改变传感器工作参数的情况,sensor_attribute用于指示设置传感器的那种参数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18enum sensor_attribute {
SENSOR_ATTR_SAMPLING_FREQUENCY, //传感器采样频率(具体含义由实际驱动实现决定,例如:一秒测量多少次)
SENSOR_ATTR_LOWER_THRESH, //低触发阈值
SENSOR_ATTR_UPPER_THRESH, //高触发阈值
SENSOR_ATTR_SLOPE_TH, //斜率(任意运动)触发
SENSOR_ATTR_SLOPE_DUR, //斜率维持超过一定时间触发
SENSOR_ATTR_OVERSAMPLING, //过采样参数
SENSOR_ATTR_FULL_SCALE, //传感器量程
SENSOR_ATTR_OFFSET, //传感器值校正,sensor_channel_get返回的传感器值将被改值偏置final_value = sensor_value + offset
SENSOR_ATTR_CALIB_TARGET, //传感器自身校正,用芯片内部的算法校正传感器的某个或者所有轴(传感器内部校正功能)
};
传感器触发方式
对于有中断输出的传感器,通常有不同的触发方式或者在实现驱动中有thread驱动的传感器1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16enum sensor_trigger_type {
SENSOR_TRIG_TIMER, //定时触发
SENSOR_TRIG_DATA_READY, //传感器数据准备好触发
SENSOR_TRIG_DELTA, //通道量有连续变化时触发(需设置SENSOR_ATTR_SLOPE_TH和SENSOR_ATTR_SLOPE_DUR)
SENSOR_TRIG_NEAR_FAR, //接近或者远离触发
SENSOR_TRIG_THRESHOLD, //超过配置阈值触发(需设置SENSOR_ATTR_LOWER_THRESH和SENSOR_ATTR_UPPER_THRESH)
SENSOR_TRIG_TAP, //单击触发
SENSOR_TRIG_DOUBLE_TAP, //双击触发
};
统一接口使用方法
主动获取传感器数据
1 | void main(void) |
Trigger获取传感器数据
1 | static void trigger_handler(struct device *dev, struct sensor_trigger *trig) |
统一接口下驱动实现方式
驱动接口模型
在sensor.h中定义了统一接口驱动模型1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22typedef int (*sensor_attr_set_t)(struct device *dev,
enum sensor_channel chan,
enum sensor_attribute attr,
const struct sensor_value *val);
typedef int (*sensor_trigger_set_t)(struct device *dev,
const struct sensor_trigger *trig,
sensor_trigger_handler_t handler);
typedef int (*sensor_sample_fetch_t)(struct device *dev,
enum sensor_channel chan);
typedef int (*sensor_channel_get_t)(struct device *dev,
enum sensor_channel chan,
struct sensor_value *val);
struct sensor_driver_api {
sensor_attr_set_t attr_set;
sensor_trigger_set_t trigger_set;
sensor_sample_fetch_t sample_fetch;
sensor_channel_get_t channel_get;
};
驱动模型实现
对上由系统调用实现呼叫驱动实现,例如(其它三个API也类似):1
2
3
4
5
6
7
8static inline int _impl_sensor_channel_get(struct device *dev,
enum sensor_channel chan,
struct sensor_value *val)
{
const struct sensor_driver_api *api = dev->driver_api;
return api->channel_get(dev, chan, val);
}
驱动实现
对下,在实现驱动时按照sensor_driver_api成员的接口和功能定义进行实现,例如dht.c(其它三个API也类似):1
2
3
4
5
6static int dht_channel_get(struct device *dev,
enum sensor_channel chan,
struct sensor_value *val)
{
...
}
在驱动初始化的时候将对应的sensor_driver_api注册,上层驱动模型就可以通过device name来寻找到驱动实现1
2
3
4
5
6static const struct sensor_driver_api dht_api = {
.sample_fetch = &dht_sample_fetch,
.channel_get = &dht_channel_get,
};
DEVICE_AND_API_INIT(dht_dev, DHT11, &dht_init, &dht_data,
NULL, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &dht_api);
驱动实现范围
struct sensor_driver_api中sample_fetch和channel_get必须实现,而attr_set和trigger_set可选,但应用层一定要注意使用同一接口时可选的驱动方法可能无效