概述
本文檔旨在詳細(xì)介紹如何配置和讀取LSM6DSOW傳感器的FIFO數(shù)據(jù)。LSM6DSOW是一款高性能的6軸IMU(慣性測(cè)量單元),集成了三軸加速度計(jì)和三軸陀螺儀。FIFO(先進(jìn)先出)緩沖區(qū)是LSM6DSOW的重要功能之一,它能夠有效地存儲(chǔ)傳感器數(shù)據(jù),減少主機(jī)的讀取頻率,從而降低功耗和提高數(shù)據(jù)采集效率。
最近在弄ST和瑞薩RA的課程,需要樣片的可以加群申請(qǐng):615061293 。
視頻教學(xué)
https://www.bilibili.com/video/BV1Dw4m1r712/
樣品申請(qǐng)
https://www.wjx.top/vm/OhcKxJk.aspx#
源碼下載
https://download.csdn.net/download/qq_24312945/89592307
硬件準(zhǔn)備
首先需要準(zhǔn)備一個(gè)開(kāi)發(fā)板,這里我準(zhǔn)備的是自己繪制的開(kāi)發(fā)板,需要的可以進(jìn)行申請(qǐng)。 主控為STM32H503CB,陀螺儀為L(zhǎng)SM6DSOW,磁力計(jì)為L(zhǎng)IS2MDL。
主要內(nèi)容
- 初始化LSM6DSOW傳感器并檢查其設(shè)備ID
- 恢復(fù)傳感器默認(rèn)配置并設(shè)置必要的參數(shù)
- 配置FIFO模式和水印閾值
- 設(shè)置加速度計(jì)和陀螺儀的數(shù)據(jù)速率
- 連續(xù)讀取FIFO中的傳感器數(shù)據(jù)并解析輸出
LSM6DSOW支持六種不同的FIFO模式,每種模式適用于不同的應(yīng)用場(chǎng)景:
- Bypass Mode(旁路模式):
○ 在旁路模式下,F(xiàn)IFO不運(yùn)行,傳感器數(shù)據(jù)直接輸出,不存儲(chǔ)在FIFO中。該模式常用于實(shí)時(shí)數(shù)據(jù)讀取。 - FIFO Mode(FIFO模式):
○ 在FIFO模式下,數(shù)據(jù)連續(xù)存儲(chǔ)到FIFO中,直到FIFO滿。當(dāng)FIFO滿時(shí),舊數(shù)據(jù)將被新數(shù)據(jù)覆蓋。適用于需要連續(xù)存儲(chǔ)數(shù)據(jù)供后續(xù)處理的情況。 - Continuous Mode(連續(xù)模式):
○ 在連續(xù)模式下,F(xiàn)IFO始終保存最新的數(shù)據(jù),當(dāng)FIFO滿時(shí),舊數(shù)據(jù)被丟棄,新數(shù)據(jù)繼續(xù)寫(xiě)入FIFO。適用于需要實(shí)時(shí)監(jiān)控最新數(shù)據(jù)的應(yīng)用。 - Continuous to FIFO Mode(連續(xù)到FIFO模式):
○ 開(kāi)始時(shí)處于連續(xù)模式,當(dāng)檢測(cè)到某個(gè)事件時(shí)切換到FIFO模式。適用于在特定事件發(fā)生后保存數(shù)據(jù)。 - Bypass to Continuous Mode(旁路到連續(xù)模式):
○ 開(kāi)始時(shí)處于旁路模式,當(dāng)檢測(cè)到某個(gè)事件時(shí)切換到連續(xù)模式。適用于事件發(fā)生后開(kāi)始實(shí)時(shí)數(shù)據(jù)監(jiān)控。 - Bypass to FIFO Mode(旁路到FIFO模式):
○ 開(kāi)始時(shí)處于旁路模式,當(dāng)檢測(cè)到某個(gè)事件時(shí)切換到FIFO模式,開(kāi)始存儲(chǔ)數(shù)據(jù)。適用于事件發(fā)生后開(kāi)始數(shù)據(jù)記錄。
生成STM32CUBEMX
用STM32CUBEMX生成例程,這里使用MCU為STM32H503CB。
配置時(shí)鐘樹(shù),配置時(shí)鐘為250M。
串口配置
查看原理圖,PA9和PA10設(shè)置為開(kāi)發(fā)板的串口。
配置串口,速率為2000000。
IIC配置
LSM6DSOW最大IIC通訊速率為400k。
配置IIC速度為400k
CS和SA0設(shè)置
由于還有一個(gè)磁力計(jì),需要把該CS也使能。
INT設(shè)置
配置為輸入檢測(cè)模式。
ICASHE
修改堆棧
串口重定向
打開(kāi)魔術(shù)棒,勾選MicroLIB
在main.c中,添加頭文件,若不添加會(huì)出現(xiàn) identifier "FILE" is undefined報(bào)錯(cuò)。
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
函數(shù)聲明和串口重定向:
/* USER CODE BEGIN PFP */
int fputc(int ch, FILE *f){
HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/* USER CODE END PFP */
參考驅(qū)動(dòng)程序
https://github.com/STMicroelectronics/lsm6dso-pid
初始化管腳
由于需要向LSM6DSO_I2C_ADD_L寫(xiě)入以及為IIC模式。
所以使能CS為高電平,配置為IIC模式。 配置SA0為低電平。
printf("HELLO!n");
HAL_GPIO_WritePin(CS1_GPIO_Port, CS1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(SA0_GPIO_Port, SA0_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(CS2_GPIO_Port, CS2_Pin, GPIO_PIN_SET);
HAL_Delay(100);
stmdev_ctx_t dev_ctx;
/* Initialize mems driver interface */
dev_ctx.write_reg = platform_write;
dev_ctx.read_reg = platform_read;
dev_ctx.mdelay = platform_delay;
dev_ctx.handle = &SENSOR_BUS;
/* Init test platform */
// platform_init();
/* Wait sensor boot time */
platform_delay(BOOT_TIME);
獲取ID
可以向WHO_AM_I (0Fh)獲取固定值,判斷是否為0x6C
lsm6dso_device_id_get為獲取函數(shù)。
對(duì)應(yīng)的獲取ID驅(qū)動(dòng)程序,如下所示。
/* Check device ID */
lsm6dso_device_id_get(&dev_ctx, &whoamI);
printf("LSM6DSO_ID=0x%x,whoamI=0x%x",LSM6DSO_ID,whoamI);
if (whoamI != LSM6DSO_ID)
while (1);
復(fù)位操作
可以向CTRL3 (12h)的SW_RESET寄存器寫(xiě)入1進(jìn)行復(fù)位。
lsm6dso_reset_set為重置函數(shù)。
對(duì)應(yīng)的驅(qū)動(dòng)程序,如下所示。
/* Restore default configuration */
lsm6dso_reset_set(&dev_ctx, PROPERTY_ENABLE);
do {
lsm6dso_reset_get(&dev_ctx, &rst);
} while (rst);
關(guān)閉I3C
/* Disable I3C interface */
lsm6dso_i3c_disable_set(&dev_ctx, LSM6DSO_I3C_DISABLE);
BDU設(shè)置
在很多傳感器中,數(shù)據(jù)通常被存儲(chǔ)在輸出寄存器中,這些寄存器分為兩部分:MSB和LSB。這兩部分共同表示一個(gè)完整的數(shù)據(jù)值。例如,在一個(gè)加速度計(jì)中,MSB和LSB可能共同表示一個(gè)加速度的測(cè)量值。
連續(xù)更新模式(BDU = ‘0’):在默認(rèn)模式下,輸出寄存器的值會(huì)持續(xù)不斷地被更新。這意味著在你讀取MSB和LSB的時(shí)候,寄存器中的數(shù)據(jù)可能會(huì)因?yàn)樾碌臏y(cè)量數(shù)據(jù)而更新。這可能導(dǎo)致一個(gè)問(wèn)題:當(dāng)你讀取MSB時(shí),如果寄存器更新了,接下來(lái)讀取的LSB可能就是新的測(cè)量值的一部分,而不是與MSB相對(duì)應(yīng)的值。這樣,你得到的就是一個(gè)“拼湊”的數(shù)據(jù),它可能無(wú)法準(zhǔn)確代表任何實(shí)際的測(cè)量時(shí)刻。
塊數(shù)據(jù)更新(BDU)模式(BDU = ‘1’):當(dāng)激活BDU功能時(shí),輸出寄存器中的內(nèi)容不會(huì)在讀取MSB和LSB之間更新。這就意味著一旦開(kāi)始讀取數(shù)據(jù)(無(wú)論是先讀MSB還是LSB),寄存器中的那一組數(shù)據(jù)就被“鎖定”,直到兩部分都被讀取完畢。這樣可以確保你讀取的MSB和LSB是同一測(cè)量時(shí)刻的數(shù)據(jù),避免了讀取到代表不同采樣時(shí)刻的數(shù)據(jù)。
簡(jiǎn)而言之,BDU位的作用是確保在讀取數(shù)據(jù)時(shí),輸出寄存器的內(nèi)容保持穩(wěn)定,從而避免讀取到拼湊或錯(cuò)誤的數(shù)據(jù)。這對(duì)于需要高精度和穩(wěn)定性的應(yīng)用尤為重要。
可以向CTRL3 (12h)的BDU寄存器寫(xiě)入1進(jìn)行開(kāi)啟。
對(duì)應(yīng)的驅(qū)動(dòng)程序,如下所示。
/* Enable Block Data Update */
lsm6dso_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
設(shè)置量程和速率
速率可以通過(guò)CTRL1 (10h)設(shè)置加速度速率和CTRL2 (11h)進(jìn)行設(shè)置角速度速率。
設(shè)置加速度量程可以通過(guò)CTRL1 (10h)進(jìn)行設(shè)置。
設(shè)置角速度量程可以通過(guò)CTRL2 (11h)進(jìn)行設(shè)置。
設(shè)置加速度和角速度的量程和速率可以使用如下函數(shù)。
/* Set Output Data Rate */
lsm6dso_xl_data_rate_set(&dev_ctx, LSM6DSO_XL_ODR_12Hz5);
lsm6dso_gy_data_rate_set(&dev_ctx, LSM6DSO_GY_ODR_12Hz5);
/* Set full scale */
lsm6dso_xl_full_scale_set(&dev_ctx, LSM6DSO_2g);
lsm6dso_gy_full_scale_set(&dev_ctx, LSM6DSO_2000dps);
設(shè)置FIFO水印
可編程FIFO閾值可以通過(guò)FIFO_CTRL1(07h)和FIFO_CTRL2(08h)寄存器中的WTM8[0]位設(shè)置。為了監(jiān)視FIFO狀態(tài),可以讀取專用寄存器(FIFO_STATUS1(3Ah),F(xiàn)IFO_STATUS2(3Bh)),以檢測(cè)FIFO溢出事件、FIFO滿狀態(tài)、FIFO空狀態(tài)、FIFO水位狀態(tài)和FIFO中存儲(chǔ)的未讀樣本數(shù)。
LSM6DSOW傳感器通過(guò)一系列控制寄存器來(lái)配置和管理FIFO。通過(guò)配置WTM,用戶可以靈活地管理傳感器數(shù)據(jù)的批處理。當(dāng)數(shù)據(jù)量達(dá)到設(shè)定的閾值時(shí),主處理器可以一次性讀取大量數(shù)據(jù),提高數(shù)據(jù)讀取效率,減少頻繁的I/O操作。 1 LSB = 1傳感器(6字節(jié)) + TAG(1字節(jié))寫(xiě)入FIFO
/* Set FIFO watermark (number of unread sensor data TAG + 6 bytes
* stored in FIFO) to 10 samples
*/
lsm6dso_fifo_watermark_set(&dev_ctx, 10);
FIFO_CTRL3寄存器用于選擇陀螺儀和加速度計(jì)數(shù)據(jù)在FIFO中的批處理數(shù)據(jù)速率(BDR)。每個(gè)傳感器都有獨(dú)立的控制位,可以設(shè)置不同的批處理數(shù)據(jù)速率,從而控制數(shù)據(jù)寫(xiě)入FIFO的頻率。
/* Set FIFO batch XL/Gyro ODR to 12.5Hz */
lsm6dso_fifo_xl_batch_set(&dev_ctx, LSM6DSO_XL_BATCHED_AT_12Hz5);
lsm6dso_fifo_gy_batch_set(&dev_ctx, LSM6DSO_GY_BATCHED_AT_12Hz5);
FIFO_CTRL4寄存器用于配置LSM6DSOW傳感器的FIFO模式、時(shí)間戳批處理和溫度數(shù)據(jù)批處理速率。該寄存器包含多個(gè)字段,每個(gè)字段的功能如下所述。
FIFO_MODE[2:0]: FIFO模式選擇
● 用于選擇FIFO的工作模式。
● 000: Bypass mode(旁路模式),F(xiàn)IFO禁用
● 001: FIFO mode(FIFO模式),F(xiàn)IFO滿時(shí)停止收集數(shù)據(jù)
● 010: 保留
● 011: Continuous-to-FIFO mode(連續(xù)到FIFO模式),連續(xù)模式直到觸發(fā)器釋放,然后進(jìn)入FIFO模式
● 100: Bypass-to-continuous mode(旁路到連續(xù)模式),旁路模式直到觸發(fā)器釋放,然后進(jìn)入連續(xù)模式
● 101: 保留
● 110: Continuous mode(連續(xù)模式),F(xiàn)IFO滿時(shí)新數(shù)據(jù)覆蓋舊數(shù)據(jù)
● 111: Bypass-to-FIFO mode(旁路到FIFO模式),旁路模式直到觸發(fā)器釋放,然后進(jìn)入FIFO模式
/* Set FIFO mode to Stream mode (aka Continuous Mode) */
lsm6dso_fifo_mode_set(&dev_ctx, LSM6DSO_STREAM_MODE);
設(shè)置中斷
COUNTER_BDR_REG1寄存器用于配置批處理數(shù)據(jù)速率計(jì)數(shù)器的相關(guān)參數(shù)。該寄存器允許用戶選擇數(shù)據(jù)準(zhǔn)備模式、重置內(nèi)部計(jì)數(shù)器以及選擇批處理事件的觸發(fā)器。以下是COUNTER_BDR_REG1寄存器的詳細(xì)描述。
COUNTER_BDR_REG1寄存器位字段
● dataready_pulsed: 啟用脈沖數(shù)據(jù)準(zhǔn)備模式
○ 0: 數(shù)據(jù)準(zhǔn)備鎖存模式(默認(rèn)),僅在接口讀取后返回0;
○ 1: 數(shù)據(jù)準(zhǔn)備脈沖模式(數(shù)據(jù)準(zhǔn)備脈沖持續(xù)時(shí)間為75微秒)。
INT1_CTRL寄存器用于配置INT1引腳的控制信號(hào)。該寄存器的每個(gè)位可以啟用一個(gè)信號(hào),當(dāng)MIPI I3CSM動(dòng)態(tài)地址未分配時(shí),信號(hào)可以通過(guò)INT1引腳傳輸。一些位還可以在使用MIPI I3CSM接口時(shí)觸發(fā)IBI(帶內(nèi)中斷)。引腳的輸出是此處選擇的信號(hào)與MD1_CFG(5Eh)中的信號(hào)的或組合。
INT1_CTRL寄存器字段描述
● DEN_DRDY_flag: 發(fā)送DEN_DRDY(DEN標(biāo)記在傳感器數(shù)據(jù)標(biāo)志上)到INT1引腳。
● INT1_CNT_BDR: 啟用COUNTER_BDR_IA中斷在INT1引腳上。
● INT1_FIFO_FULL: 啟用FIFO滿中斷在INT1引腳上。當(dāng)使用MIPI I3CSM接口時(shí),它還可以用于觸發(fā)IBI。
● INT1_FIFO_OVR: 啟用FIFO溢出中斷在INT1引腳上。當(dāng)使用MIPI I3CSM接口時(shí),它還可以用于觸發(fā)IBI。
● INT1_FIFO_TH: 啟用FIFO閾值中斷在INT1引腳上。當(dāng)使用MIPI I3CSM接口時(shí),它還可以用于觸發(fā)IBI。
● INT1_BOOT: 啟用引導(dǎo)狀態(tài)在INT1引腳上。
● INT1_DRDY_G: 啟用陀螺儀數(shù)據(jù)準(zhǔn)備中斷在INT1引腳上。當(dāng)使用MIPI I3CSM接口時(shí),它還可以用于觸發(fā)IBI。
● INT1_DRDY_XL: 啟用加速度計(jì)數(shù)據(jù)準(zhǔn)備中斷在INT1引腳上。當(dāng)使用MIPI I3CSM接口時(shí),它還可以用于觸發(fā)IBI。
lsm6dso_pin_int1_route_get(&dev_ctx, &int1_route);
int1_route.fifo_th = PROPERTY_ENABLE;
lsm6dso_pin_int1_route_set(&dev_ctx, int1_route);
獲取FIFO數(shù)據(jù)
FIFO_STATUS寄存器用于監(jiān)控LSM6DSOW傳感器FIFO的狀態(tài)。它們包括FIFO_STATUS1(3Ah)和FIFO_STATUS2(3Bh),分別用于報(bào)告未讀數(shù)據(jù)和FIFO狀態(tài)信息。
當(dāng)FIFO中的數(shù)據(jù)量達(dá)到或超過(guò)預(yù)設(shè)的水位線時(shí),F(xiàn)IFO_WTM_IA位將被置為1。這意味著主處理器可以通過(guò)讀取該位的狀態(tài)來(lái)確定何時(shí)需要處理FIFO中的數(shù)據(jù)。例如,當(dāng)數(shù)據(jù)量達(dá)到水位線時(shí),觸發(fā)一次中斷,主處理器讀取并處理FIFO中的數(shù)據(jù),然后繼續(xù)下一輪數(shù)據(jù)采集。
DIFF_FIFO 位于 FIFO_STATUS1 (3Ah) 和 FIFO_STATUS2 (3Bh) 寄存器中,用于指示FIFO中未讀傳感器數(shù)據(jù)的數(shù)量。它包括兩個(gè)部分:
● DIFF_FIFO7:07:07:0: 位于 FIFO_STATUS1 寄存器中,表示未讀數(shù)據(jù)的低8位。
● DIFF_FIFO9:89:89:8: 位于 FIFO_STATUS2 寄存器中,表示未讀數(shù)據(jù)的高2位。
DIFF_FIFO字段用于跟蹤FIFO中未讀的數(shù)據(jù)量。通過(guò)讀取DIFF_FIFO,可以確定FIFO中當(dāng)前存儲(chǔ)了多少數(shù)據(jù),這對(duì)于決定何時(shí)讀取FIFO中的數(shù)據(jù)非常重要。該字段的值在數(shù)據(jù)從FIFO中讀取時(shí)會(huì)自動(dòng)更新。
FIFO_DATA_OUT_TAG (78h)寄存器用于標(biāo)識(shí)FIFO中的傳感器數(shù)據(jù)來(lái)源。該寄存器包含標(biāo)識(shí)符(TAG),用于指示數(shù)據(jù)是由哪個(gè)傳感器生成的,并幫助用戶正確地解析FIFO中的數(shù)據(jù)。
TAG_SENSOR: 標(biāo)識(shí)FIFO中的傳感器數(shù)據(jù)源。根據(jù)傳感器類型和數(shù)據(jù)源,該字段值表示具體的傳感器數(shù)據(jù)。詳細(xì)見(jiàn)下表。
FIFO_DATA_OUT_TAG 寄存器提供了數(shù)據(jù)標(biāo)簽,用于識(shí)別FIFO中存儲(chǔ)的數(shù)據(jù)來(lái)源。這對(duì)于解析和處理從FIFO中讀取的數(shù)據(jù)非常重要。通過(guò)TAG字段,用戶可以區(qū)分不同傳感器的數(shù)據(jù),并采取適當(dāng)?shù)奶幚泶胧?/p>
FIFO_DATA_OUT_X, FIFO_DATA_OUT_Y 和 FIFO_DATA_OUT_Z 寄存器,這些寄存器用于讀取LSM6DSOW傳感器的FIFO中的X、Y和Z軸數(shù)據(jù)。每個(gè)軸的數(shù)據(jù)由兩個(gè)寄存器組成:一個(gè)低字節(jié)寄存器(_L)和一個(gè)高字節(jié)寄存器(_H)。
為了從FIFO中讀取加速度計(jì)或陀螺儀的X、Y、Z軸數(shù)據(jù),需要依次讀取對(duì)應(yīng)的低字節(jié)和高字節(jié)寄存器,并將它們組合成一個(gè)完整的16位數(shù)據(jù)。
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
uint16_t num = 0;
uint8_t wmflag = 0;
lsm6dso_fifo_tag_t reg_tag;
axis3bit16_t dummy;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0))
{
/* Read watermark flag */
lsm6dso_fifo_wtm_flag_get(&dev_ctx, &wmflag);
if (wmflag > 0) {
/* Read number of samples in FIFO */
lsm6dso_fifo_data_level_get(&dev_ctx, &num);
while (num--) {
/* Read FIFO tag */
lsm6dso_fifo_sensor_tag_get(&dev_ctx, ®_tag);
switch (reg_tag) {
case LSM6DSO_XL_NC_TAG:
memset(data_raw_acceleration.u8bit, 0x00, 3 * sizeof(int16_t));
lsm6dso_fifo_out_raw_get(&dev_ctx, data_raw_acceleration.u8bit);
acceleration_mg[0] =
lsm6dso_from_fs2_to_mg(data_raw_acceleration.i16bit[0]);
acceleration_mg[1] =
lsm6dso_from_fs2_to_mg(data_raw_acceleration.i16bit[1]);
acceleration_mg[2] =
lsm6dso_from_fs2_to_mg(data_raw_acceleration.i16bit[2]);
printf("Acceleration [mg]:%4.2ft%4.2ft%4.2frn",
acceleration_mg[0], acceleration_mg[1], acceleration_mg[2]);
break;
case LSM6DSO_GYRO_NC_TAG:
memset(data_raw_angular_rate.u8bit, 0x00, 3 * sizeof(int16_t));
lsm6dso_fifo_out_raw_get(&dev_ctx, data_raw_angular_rate.u8bit);
angular_rate_mdps[0] =
lsm6dso_from_fs2000_to_mdps(data_raw_angular_rate.i16bit[0]);
angular_rate_mdps[1] =
lsm6dso_from_fs2000_to_mdps(data_raw_angular_rate.i16bit[1]);
angular_rate_mdps[2] =
lsm6dso_from_fs2000_to_mdps(data_raw_angular_rate.i16bit[2]);
printf("Angular rate [mdps]:%4.2ft%4.2ft%4.2frn",
angular_rate_mdps[0], angular_rate_mdps[1], angular_rate_mdps[2]);
break;
default:
/* Flush unused samples */
memset(dummy.u8bit, 0x00, 3 * sizeof(int16_t));
lsm6dso_fifo_out_raw_get(&dev_ctx, dummy.u8bit);
break;
}
}
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
演示
-
mems
+關(guān)注
關(guān)注
128文章
3854瀏覽量
189703 -
fifo
+關(guān)注
關(guān)注
3文章
382瀏覽量
43335 -
三軸陀螺儀
+關(guān)注
關(guān)注
2文章
27瀏覽量
20178 -
stm32cubemx
+關(guān)注
關(guān)注
5文章
278瀏覽量
14585
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論