概述
本文檔旨在詳細介紹如何配置和讀取LSM6DSOW傳感器的FIFO數據。LSM6DSOW是一款高性能的6軸IMU(慣性測量單元),集成了三軸加速度計和三軸陀螺儀。FIFO(先進先出)緩沖區是LSM6DSOW的重要功能之一,它能夠有效地存儲傳感器數據,減少主機的讀取頻率,從而降低功耗和提高數據采集效率。
最近在弄ST和瑞薩RA的課程,需要樣片的可以加群申請:615061293 。
視頻教學
https://www.bilibili.com/video/BV1Dw4m1r712/
樣品申請
https://www.wjx.top/vm/OhcKxJk.aspx#
源碼下載
https://download.csdn.net/download/qq_24312945/89592307
硬件準備
首先需要準備一個開發板,這里我準備的是自己繪制的開發板,需要的可以進行申請。 主控為STM32H503CB,陀螺儀為LSM6DSOW,磁力計為LIS2MDL。
主要內容
- 初始化LSM6DSOW傳感器并檢查其設備ID
- 恢復傳感器默認配置并設置必要的參數
- 配置FIFO模式和水印閾值
- 設置加速度計和陀螺儀的數據速率
- 連續讀取FIFO中的傳感器數據并解析輸出
LSM6DSOW支持六種不同的FIFO模式,每種模式適用于不同的應用場景:
- Bypass Mode(旁路模式):
○ 在旁路模式下,FIFO不運行,傳感器數據直接輸出,不存儲在FIFO中。該模式常用于實時數據讀取。 - FIFO Mode(FIFO模式):
○ 在FIFO模式下,數據連續存儲到FIFO中,直到FIFO滿。當FIFO滿時,舊數據將被新數據覆蓋。適用于需要連續存儲數據供后續處理的情況。 - Continuous Mode(連續模式):
○ 在連續模式下,FIFO始終保存最新的數據,當FIFO滿時,舊數據被丟棄,新數據繼續寫入FIFO。適用于需要實時監控最新數據的應用。 - Continuous to FIFO Mode(連續到FIFO模式):
○ 開始時處于連續模式,當檢測到某個事件時切換到FIFO模式。適用于在特定事件發生后保存數據。 - Bypass to Continuous Mode(旁路到連續模式):
○ 開始時處于旁路模式,當檢測到某個事件時切換到連續模式。適用于事件發生后開始實時數據監控。 - Bypass to FIFO Mode(旁路到FIFO模式):
○ 開始時處于旁路模式,當檢測到某個事件時切換到FIFO模式,開始存儲數據。適用于事件發生后開始數據記錄。
生成STM32CUBEMX
用STM32CUBEMX生成例程,這里使用MCU為STM32H503CB。
配置時鐘樹,配置時鐘為250M。
串口配置
查看原理圖,PA9和PA10設置為開發板的串口。
配置串口,速率為2000000。
IIC配置
LSM6DSOW最大IIC通訊速率為400k。
配置IIC速度為400k
CS和SA0設置
由于還有一個磁力計,需要把該CS也使能。
INT設置
配置為輸入檢測模式。
ICASHE
修改堆棧
串口重定向
打開魔術棒,勾選MicroLIB
在main.c中,添加頭文件,若不添加會出現 identifier "FILE" is undefined報錯。
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
函數聲明和串口重定向:
/* 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 */
參考驅動程序
https://github.com/STMicroelectronics/lsm6dso-pid
初始化管腳
由于需要向LSM6DSO_I2C_ADD_L寫入以及為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為獲取函數。
對應的獲取ID驅動程序,如下所示。
/* 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);
復位操作
可以向CTRL3 (12h)的SW_RESET寄存器寫入1進行復位。
lsm6dso_reset_set為重置函數。
對應的驅動程序,如下所示。
/* Restore default configuration */
lsm6dso_reset_set(&dev_ctx, PROPERTY_ENABLE);
do {
lsm6dso_reset_get(&dev_ctx, &rst);
} while (rst);
關閉I3C
/* Disable I3C interface */
lsm6dso_i3c_disable_set(&dev_ctx, LSM6DSO_I3C_DISABLE);
BDU設置
在很多傳感器中,數據通常被存儲在輸出寄存器中,這些寄存器分為兩部分:MSB和LSB。這兩部分共同表示一個完整的數據值。例如,在一個加速度計中,MSB和LSB可能共同表示一個加速度的測量值。
連續更新模式(BDU = ‘0’):在默認模式下,輸出寄存器的值會持續不斷地被更新。這意味著在你讀取MSB和LSB的時候,寄存器中的數據可能會因為新的測量數據而更新。這可能導致一個問題:當你讀取MSB時,如果寄存器更新了,接下來讀取的LSB可能就是新的測量值的一部分,而不是與MSB相對應的值。這樣,你得到的就是一個“拼湊”的數據,它可能無法準確代表任何實際的測量時刻。
塊數據更新(BDU)模式(BDU = ‘1’):當激活BDU功能時,輸出寄存器中的內容不會在讀取MSB和LSB之間更新。這就意味著一旦開始讀取數據(無論是先讀MSB還是LSB),寄存器中的那一組數據就被“鎖定”,直到兩部分都被讀取完畢。這樣可以確保你讀取的MSB和LSB是同一測量時刻的數據,避免了讀取到代表不同采樣時刻的數據。
簡而言之,BDU位的作用是確保在讀取數據時,輸出寄存器的內容保持穩定,從而避免讀取到拼湊或錯誤的數據。這對于需要高精度和穩定性的應用尤為重要。
可以向CTRL3 (12h)的BDU寄存器寫入1進行開啟。
對應的驅動程序,如下所示。
/* Enable Block Data Update */
lsm6dso_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
設置量程和速率
速率可以通過CTRL1 (10h)設置加速度速率和CTRL2 (11h)進行設置角速度速率。
設置加速度量程可以通過CTRL1 (10h)進行設置。
設置角速度量程可以通過CTRL2 (11h)進行設置。
設置加速度和角速度的量程和速率可以使用如下函數。
/* 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);
設置FIFO水印
可編程FIFO閾值可以通過FIFO_CTRL1(07h)和FIFO_CTRL2(08h)寄存器中的WTM8[0]位設置。為了監視FIFO狀態,可以讀取專用寄存器(FIFO_STATUS1(3Ah),FIFO_STATUS2(3Bh)),以檢測FIFO溢出事件、FIFO滿狀態、FIFO空狀態、FIFO水位狀態和FIFO中存儲的未讀樣本數。
LSM6DSOW傳感器通過一系列控制寄存器來配置和管理FIFO。通過配置WTM,用戶可以靈活地管理傳感器數據的批處理。當數據量達到設定的閾值時,主處理器可以一次性讀取大量數據,提高數據讀取效率,減少頻繁的I/O操作。 1 LSB = 1傳感器(6字節) + TAG(1字節)寫入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寄存器用于選擇陀螺儀和加速度計數據在FIFO中的批處理數據速率(BDR)。每個傳感器都有獨立的控制位,可以設置不同的批處理數據速率,從而控制數據寫入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模式、時間戳批處理和溫度數據批處理速率。該寄存器包含多個字段,每個字段的功能如下所述。
FIFO_MODE[2:0]: FIFO模式選擇
● 用于選擇FIFO的工作模式。
● 000: Bypass mode(旁路模式),FIFO禁用
● 001: FIFO mode(FIFO模式),FIFO滿時停止收集數據
● 010: 保留
● 011: Continuous-to-FIFO mode(連續到FIFO模式),連續模式直到觸發器釋放,然后進入FIFO模式
● 100: Bypass-to-continuous mode(旁路到連續模式),旁路模式直到觸發器釋放,然后進入連續模式
● 101: 保留
● 110: Continuous mode(連續模式),FIFO滿時新數據覆蓋舊數據
● 111: Bypass-to-FIFO mode(旁路到FIFO模式),旁路模式直到觸發器釋放,然后進入FIFO模式
/* Set FIFO mode to Stream mode (aka Continuous Mode) */
lsm6dso_fifo_mode_set(&dev_ctx, LSM6DSO_STREAM_MODE);
設置中斷
COUNTER_BDR_REG1寄存器用于配置批處理數據速率計數器的相關參數。該寄存器允許用戶選擇數據準備模式、重置內部計數器以及選擇批處理事件的觸發器。以下是COUNTER_BDR_REG1寄存器的詳細描述。
COUNTER_BDR_REG1寄存器位字段
● dataready_pulsed: 啟用脈沖數據準備模式
○ 0: 數據準備鎖存模式(默認),僅在接口讀取后返回0;
○ 1: 數據準備脈沖模式(數據準備脈沖持續時間為75微秒)。
INT1_CTRL寄存器用于配置INT1引腳的控制信號。該寄存器的每個位可以啟用一個信號,當MIPI I3CSM動態地址未分配時,信號可以通過INT1引腳傳輸。一些位還可以在使用MIPI I3CSM接口時觸發IBI(帶內中斷)。引腳的輸出是此處選擇的信號與MD1_CFG(5Eh)中的信號的或組合。
INT1_CTRL寄存器字段描述
● DEN_DRDY_flag: 發送DEN_DRDY(DEN標記在傳感器數據標志上)到INT1引腳。
● INT1_CNT_BDR: 啟用COUNTER_BDR_IA中斷在INT1引腳上。
● INT1_FIFO_FULL: 啟用FIFO滿中斷在INT1引腳上。當使用MIPI I3CSM接口時,它還可以用于觸發IBI。
● INT1_FIFO_OVR: 啟用FIFO溢出中斷在INT1引腳上。當使用MIPI I3CSM接口時,它還可以用于觸發IBI。
● INT1_FIFO_TH: 啟用FIFO閾值中斷在INT1引腳上。當使用MIPI I3CSM接口時,它還可以用于觸發IBI。
● INT1_BOOT: 啟用引導狀態在INT1引腳上。
● INT1_DRDY_G: 啟用陀螺儀數據準備中斷在INT1引腳上。當使用MIPI I3CSM接口時,它還可以用于觸發IBI。
● INT1_DRDY_XL: 啟用加速度計數據準備中斷在INT1引腳上。當使用MIPI I3CSM接口時,它還可以用于觸發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數據
FIFO_STATUS寄存器用于監控LSM6DSOW傳感器FIFO的狀態。它們包括FIFO_STATUS1(3Ah)和FIFO_STATUS2(3Bh),分別用于報告未讀數據和FIFO狀態信息。
當FIFO中的數據量達到或超過預設的水位線時,FIFO_WTM_IA位將被置為1。這意味著主處理器可以通過讀取該位的狀態來確定何時需要處理FIFO中的數據。例如,當數據量達到水位線時,觸發一次中斷,主處理器讀取并處理FIFO中的數據,然后繼續下一輪數據采集。
DIFF_FIFO 位于 FIFO_STATUS1 (3Ah) 和 FIFO_STATUS2 (3Bh) 寄存器中,用于指示FIFO中未讀傳感器數據的數量。它包括兩個部分:
● DIFF_FIFO7:07:07:0: 位于 FIFO_STATUS1 寄存器中,表示未讀數據的低8位。
● DIFF_FIFO9:89:89:8: 位于 FIFO_STATUS2 寄存器中,表示未讀數據的高2位。
DIFF_FIFO字段用于跟蹤FIFO中未讀的數據量。通過讀取DIFF_FIFO,可以確定FIFO中當前存儲了多少數據,這對于決定何時讀取FIFO中的數據非常重要。該字段的值在數據從FIFO中讀取時會自動更新。
FIFO_DATA_OUT_TAG (78h)寄存器用于標識FIFO中的傳感器數據來源。該寄存器包含標識符(TAG),用于指示數據是由哪個傳感器生成的,并幫助用戶正確地解析FIFO中的數據。
TAG_SENSOR: 標識FIFO中的傳感器數據源。根據傳感器類型和數據源,該字段值表示具體的傳感器數據。詳細見下表。
FIFO_DATA_OUT_TAG 寄存器提供了數據標簽,用于識別FIFO中存儲的數據來源。這對于解析和處理從FIFO中讀取的數據非常重要。通過TAG字段,用戶可以區分不同傳感器的數據,并采取適當的處理措施。
FIFO_DATA_OUT_X, FIFO_DATA_OUT_Y 和 FIFO_DATA_OUT_Z 寄存器,這些寄存器用于讀取LSM6DSOW傳感器的FIFO中的X、Y和Z軸數據。每個軸的數據由兩個寄存器組成:一個低字節寄存器(_L)和一個高字節寄存器(_H)。
為了從FIFO中讀取加速度計或陀螺儀的X、Y、Z軸數據,需要依次讀取對應的低字節和高字節寄存器,并將它們組合成一個完整的16位數據。
/* 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
+關注
關注
129文章
3958瀏覽量
191107 -
fifo
+關注
關注
3文章
389瀏覽量
43863 -
三軸陀螺儀
+關注
關注
2文章
28瀏覽量
20398 -
stm32cubemx
+關注
關注
5文章
284瀏覽量
15006
發布評論請先 登錄
相關推薦
評論