本帖最后由 littleshrimp 于 2021-2-28 18:21 编辑
通过前面帖子对ST传感器的Standard C驱动和read_data_polling有了一个大概了解,接下来我将继续对read_data_polling例程做更深入的介绍。
https://bbs.eeworld.com.cn/thread-1157700-1-1.html
lsm6dso_read_data_polling函数里在对传感器复位并判断复位成功后会对传感器进行配置,首先执行了lsm6dso_i3c_disable_set函数,这个函数是用来配置和禁止I3C功能,至于什么是I3C可以自行搜索“MIPI I3C”。例程里禁用了I3C功能,查看lsm6dso_i3c_disable_set函数看到里边还是有些复杂的,我们先来看看函数参数中val ,它对应的枚举类型lsm6dso_i3c_disable_t,LSM6DSO_I3C_DISABLE是关闭I3C,剩下的是ENABLE和对应的时间,LSM6DSO_I3C_DISABLE的数值是0x80,其它分别为0,1,2,3。回到lsm6dso_i3c_disable_set函数,函数里首先执行lsm6dso_read_reg读取CTRL9_XL寄存器,然后对ctrl9_xl.i3c_disabl进行设置,((uint8_t)val & 0x80U) >> 7作用是当val第7位为1时(LSM6DSO_I3C_DISABLE)为1,否则为0。这里也可以使用其它方法,比如val == LSM6DSO_I3C_DISABLE ? 1 : 0,或者((uint8_t)val & 0x80U) == 0x80U等等。查看数据手册看到CTRL9_XL的I3C_disable位就是用来使能或禁止I3C接口的,为1时禁止。
在配置好CTRL9_XL 的i3c_disable 后又通过lsm6dso_read_reg函数读取了I3C_BUS_AVB寄存器,然后将val 的0-1位赋给i3c_bus_avb_sel,查看数据手册的I3C_BUS_AVB它对应了50us、2ms、1ms和5ms,这个参数和I3C有关我也不是很了解,这里就不解释了。
再回到lsm6dso_read_data_polling函数,执行完lsm6dso_i3c_disable_set关闭I3C功能后又执行了lsm6dso_block_data_update_set,这个函数很多传感器都会使用。查看lsm6dso_block_data_update_set内部, 看到他是用来设置CTRL3_C的bdu位,同样是先读取再设置。BDU全称Block Data Update,因为传感器分辨率为16位,每一组数据由高字节MSB和低字节LSB组成,比如正巧MCU在刚读完第一个数据的MSB或者LSB后,传感器的这两个寄存器数据就马上更新了,然后MCU再读取到的另外一个字节(MSB或者LSB)实际上已经是第二个数据了,这样再用这两个字节拼成的 16位数据相当于包含了第一数据和第二个数据。为防止这种情况发生,可以将BDU设置为1,这样传感器会判断一组寄存器的MSB和LSB是否已经被全部读取,只有在被全部读取后才会更新这两个寄存器。
说完BDU剩下的代码就比较容易理解了,lsm6dso_xl_data_rate_set是用来设置加速度的ODR,lsm6dso_gy_data_rate_set是用来设置陀螺仪的ODR,lsm6dso_xl_full_scale_set是设置加速度的full scale,lsm6dso_gy_full_scale_set是用来设置陀螺仪的full scale。驱动头文件lsm6dso_reg.h里已经做好了定义,只要把相应的定义作为参数传递给对应的函数就能实现对应的配置。
设置好传感器的数据输出速率和满量程,最后又对传感器的滤波器进行配置。lsm6dso_xl_hp_path_on_out_set函数的输入参数是LSM6DSO_LP_ODR_DIV_100,从字面上理解是设置加速度低通滤波(Low Pass)频率为ODR/100,因为之前将ODR设置成了12.5Hz,所以波滤器允许低于0.125Hz的信号通过。lsm6dso_xl_hp_path_on_out_set分别设置了CTRL8_XL的hp_slope_xl_en、hp_ref_mode_xl和hpcf_xl,查看数据手册的CTRL8_XL,和AN5192应用笔记,HP_SLOPE_ XL_EN是高通滤波器使能,为1时为高通波滤,0时为低通滤波。hp_ref_mode_xl是高通波滤器参考模式,使能此模式同时还要将HP_SLOPE_ XL_EN置1(高通模式),并且 HPCF_XL数值不能为0(也就是说不支持ODR / 4 (slope filter))。使能参考模式后传感器会保存当前的加速度值,并且之后再读取的数据都是当时的值差去当前值。举个例子更容易理解,假设参考模式使能时加速度的值为X=0,Y=0,Z=1000mg,这个值会被一直保存,然后如果传感器保持不动,再获得到的数据理论上还是X=0,Y=0,Z=1000mg,此时读取到的数据为X=0,Y=0,Z=0,是2组数据相减的结果。hpcf_xl对应CTRL8_XL的BIT7-BIT5,占用3个位,对应的截止频率为ODR/4到ODR/800。
接着执行了lsm6dso_xl_filter_lp2_set函数,将能数是PROPERTY_ENABLE,通过观察lsm6dso_xl_filter_lp2_set函数发现它用来设置CTRL1_XL寄存器的lpf2_xl_en位。通过下图中的表格可以看到lpf2_xl_en只对低通滤波器有效,为0时相当于把LPF2给屏蔽掉了。
至此整个例程的传感器配置工具就已经完成了,剩下的代码都在while块里重复执行,这部分也比较容易理解,lsm6dso_xl_flag_data_ready_get函数用来读取STATUS_REG寄存器的xlda位,STATUS_REG的2、1、0位分别对应温度数据有效、角速度数据有效和加速度数据有效。xlda表示加速度数据有效,为1时表示加速度数据转换完成。接着使用memset把data_raw_acceleration的数据清零,然后通过lsm6dso_acceleration_raw_get函数读取加速度的x,y,z轴数据到data_raw_acceleration。
lsm6dso_acceleration_raw_get函数从OUTX_L_A寄存器开始一次读取6个字节数据,对应分别对应X,Y,Z的LSB和MSB,然后分别将2个字节合并成一个16位数据。再接下来是通过lsm6dso_from_fs2_to_mg函数将读取出的16位加速度原数据转换成对应的以mg为单位的加速度数值。注意这里的代码并没有对加速度的量程做判断,而是使用了一种固定的写法,lsm6dso_from_fs2_to_mg即只有在量程为2g时才有效,如果量程是4g就需要用到lsm6dso_from_fs4_to_mg函数,这里如果想灵活一些网友可以自己使用宏定义,或者在配置量程时保存量程信息再做判断,方便日后修改代码。lsm6dso_from_fs2_to_mg是用当前读取到的16位加速度原数据乘以0.061f,这个0.061怎么来的可以在数据手册中找到,就是下边的最后一个图片。最后通过sprintf将浮点类型的加速度数据转换成字符串形式并通过tx_com将数据发送到上位机进行分析。
剩下的陀螺仪和温度的数据的有效判断、读取、转换和发送都和加速度类型,这里就不重复介绍了。到此为止整个read_data_polling例程就已经全部介绍完了,有问题的网友欢迎发回帖交流。