一、簡介
BMA423 採用內部加速計的原始數據並在內部處理數據,從而爲開發人員提供有用的結果。這可爲微控制器減掉一些負載並加快開發速度。當在可穿戴健身應用中使用時,它可以檢測用戶是靜止不動、跑步還是走路。
Bosch Sensortec 爲其所有傳感器提供固件。在給 BMA423 上電時,它會經歷一個內部上電覆位 (POR) 序列。在系統 POR 之後,微控制器應運行 Bosch 的 BMA423 初始化程序,以正確配置芯片。
初始化程序首先讀取內部芯片 ID,並把該 ID 與存儲在固件中的芯片 ID 進行比較。這將驗證 BMA423 是否可用並與微控制器正確通信。接下來,初始化程序運行短自檢以驗證能否正常運行,自檢結果被髮送回微控制器。設備初始化後,會處於性能模式,這是傳感器的最高功率和最高性能狀態。
BMA423 具有許多用於低功耗運行的特性,包括 1024 字節寬的 FIFO。這讓加速計能夠在微控制器處於低功耗或休眠模式時檢測和存儲數據。由於不需要微控制器不斷地與 BMA423 通信,這在非實時應用中節省了功耗。一旦 FIFO 中的加速計數據達到預編程的 FIFO 級別,就會產生中斷以喚醒微控制器,然後微控制器轉而執行驅動子程序以讀取 FIFO 數據。
BMA423 的最低功耗模式是掛起模式。在掛起模式期間,不執行內部加速計測量,同時保持 FIFO 和內部寄存器的狀態。
爲了降低非實時應用中的運行功耗,應將 BMA423 置於低功耗模式而不是默認的性能模式。這會關閉 BMA423 的各個部分,包括外部 I2C 和 SPI 接口,同時將數據記錄到 FIFO 中。在低功耗模式下,BMA423 會根據固件編程佔空比設定的採樣率在性能模式和休眠模式之間定期切換。採樣率越低,BMA423 的功耗越低。調整此佔空比可針對傳感器功耗調整所需的精度。
二、硬件連接
功能口 | 引腳 |
---|---|
SCL | 5 |
SDA | 4 |
INT1 | 3 |
三、添加I2C驅動
查看 NRF52832學習筆記(19)——TWI(I2C)接口使用
四、移植文件
注意:以下出現缺失common.h文件錯誤,去除即可。uint8改爲uint8_t或unsigned char或自己宏定義
鏈接:https://pan.baidu.com/s/1JbNEZ81bGOaumLIKiPumRw 提取碼:r1y8
將 board_bma423.c 、 board_bma423.h 和 bma423下所有文件,board_gpi.c、board_gpi.h 加入工程的Application文件夾下
4.1 board_bma423.c
/*********************************************************************
* INCLUDES
*/
#include "nrf_delay.h"
#include "nrf_log.h"
#include "board_bma423.h"
#include "board_i2c.h"
#include "common.h"
#include "bma423.h"
#include "bma4_defs.h"
/*********************************************************************
* LOCAL VARIABLES
*/
static struct bma4_dev s_bma423;
static struct bma4_accel_config s_accelConfig = {0};
static struct bma4_fifo_frame s_fifoFrame = {0};
static uint8 s_fifoBuffer[255] = {0};
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/**
@brief BMA423三軸加速計驅動初始化
@param 無
@return 無
*/
void BMA423_Init(void)
{
// ------------ 傳感器I2C初始化 ------------
/* Modify the parameters */
s_bma423.dev_addr = BMA4_I2C_ADDR_PRIMARY;
s_bma423.interface = BMA4_I2C_INTERFACE;
s_bma423.bus_read = I2C_ReadData;
s_bma423.bus_write = I2C_WriteData;
s_bma423.delay = nrf_delay_ms;
s_bma423.read_write_len = 8;
/* Initialize the instance */
bma423_init(&s_bma423);
bma4_set_command_register(0xB6, &s_bma423); // 軟復位
/* Enable the accelerometer */
bma4_set_accel_enable(BMA4_ENABLE, &s_bma423);
bma423_write_config_file(&s_bma423); // 更新配置參數
uint8 value = 0;
while(value != 0x01)
{
I2C_ReadData(BMA4_I2C_ADDR_PRIMARY, BMA4_INTERNAL_STAT, &value, 1);
DelayMs(10);
if(value != 0x01) // ASIC初始化完成
{
NVIC_SystemReset();
}
}
DelayMs(10);
// ------------ 配置加速度 ------------
/* Assign the desired settings */
s_accelConfig.odr = BMA4_OUTPUT_DATA_RATE_50HZ;
s_accelConfig.range = BMA4_ACCEL_RANGE_4G;
s_accelConfig.perf_mode = BMA4_DISABLE; // averaging mode
s_accelConfig.bandwidth = BMA4_ACCEL_OSR4_AVG1;
/* Set the configuration */
bma4_set_accel_config(&s_accelConfig, &s_bma423);
DelayMs(1);
// ------------ 配置FIFO ------------
/* Modify the FIFO buffer instance and link to the device instance */
s_fifoFrame.data = s_fifoBuffer;
s_fifoFrame.length = 40;
s_fifoFrame.fifo_data_enable = BMA4_ENABLE;
s_fifoFrame.fifo_header_enable = BMA4_ENABLE;
s_bma423.fifo = &s_fifoFrame;
/* Disable the advanced power save mode to configure the FIFO buffer */
bma4_set_advance_power_save(BMA4_DISABLE, &s_bma423);
/* Configure the FIFO buffer */
bma4_set_fifo_config((BMA4_FIFO_ACCEL | BMA4_FIFO_HEADER), BMA4_ENABLE, &s_bma423);
DelayMs(1);
// ------------ 配置運動/非運動檢測 ------------
struct bma423_anymotion_config anymotionConfig;
bma423_get_any_motion_config(&anymotionConfig, &s_bma423);
anymotionConfig.duration = 0x10; // 定義中斷必須遵守threshold條件的連續數據點的數目
anymotionConfig.nomotion_sel = 0x7;
anymotionConfig.threshold = 0x7FFF; // 運動檢測的斜率閾值
/* Configure the Any motion feature */
bma423_set_any_motion_config(&anymotionConfig, &s_bma423);
/*Enable the axis as per requirement for Any/no-motion. Here all axis has been enabled */
bma423_anymotion_enable_axis(BMA423_ALL_AXIS_EN, &s_bma423);
/* Enable/select the Any-motion feature */
bma423_feature_enable(BMA423_ANY_MOTION, BMA4_ENABLE, &s_bma423);
DelayMs(1);
// ------------ 配置中斷 ------------
struct bma4_int_pin_config intPinCofig;
intPinCofig.edge_ctrl = BMA4_LEVEL_TRIGGER; // 電平觸發
intPinCofig.lvl = BMA4_ACTIVE_LOW;
intPinCofig.input_en = BMA4_INPUT_DISABLE;
intPinCofig.od = BMA4_OPEN_DRAIN;
intPinCofig.output_en = BMA4_OUTPUT_ENABLE; // 輸出使能
/* Set the electrical behaviour of interrupt pin1 */
bma4_set_int_pin_config(&intPinCofig, BMA4_INTR1_MAP, &s_bma423);
bma4_set_interrupt_mode(BMA4_NON_LATCH_MODE, &s_bma423);
/* Map the Any-No-motion out interupt to INT pin1 */
bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_ANY_NO_MOTION_INT, BMA4_ENABLE, &s_bma423);
DelayMs(10);
bma4_set_advance_power_save(BMA4_ENABLE, &s_bma423); // 進入低功耗模式
}
/**
@brief BMA423讀取FIFO傳感數據
@param pAccelData -[in&out] 加速計數據緩衝區,存儲FIFO中的數據
@param pAccelLen -[in&out] 加速度數據條數
@return 0 - 成功;非0 - 失敗
*/
uint16 BMA423_ReadFifoData(struct bma4_accel *pAccelData, uint16 *pAccelLen)
{
uint16 result = BMA4_OK;
/* Read data from the sensor FIFO buffer */
result |= bma4_read_fifo_data(&s_bma423); // Read FIFO data
/* Exit the program in case of a failure */
if(result != BMA4_OK)
{
return result;
}
/* Reset the maximum number of requried sensor data instances */
*pAccelLen = 36;
/* Parse the FIFO until there are less frames than requested */
while(*pAccelLen == 36)
{
/* Parse the FIFO buffer and extract requried number of accelerometer data frames */
result |= bma4_extract_accel(pAccelData, pAccelLen, &s_bma423);
/* Exit the program in case of a failure */
if(result != BMA4_OK)
{
return result;
}
}
return result;
}
/**
@brief BMA423讀取三軸加速度數據
@param pAccelData -[in&out] 加速計數據緩衝區
@return 0 - 成功;非0 - 失敗
*/
uint16 BMA423_ReadAccelData(struct bma4_accel *pAccelData)
{
return bma4_read_accel_xyz(pAccelData, &s_bma423);
}
/****************************************************END OF FILE****************************************************/
4.2 board_si522.h
#ifndef _BOARD_BMA423_H_
#define _BOARD_BMA423_H_
/*********************************************************************
* INCLUDES
*/
#include "bma4.h"
#include "common.h"
/*********************************************************************
* API FUNCTIONS
*/
void BMA423_Init(void);
uint16 BMA423_ReadFifoData(struct bma4_accel *pAccelData, uint16 *pAccelLen);
uint16 BMA423_ReadAccelData(struct bma4_accel *pAccelData);
#endif /* _BOARD_BMA423_H_ */
4.3 board_gpi.c
/*********************************************************************
* INCLUDES
*/
#include "nrf_drv_gpiote.h"
#include "app_error.h"
#include "board_gpi.h"
#include "user_bma423.h"
#include "common.h"
static void irqCallbackFunc(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action);
/*********************************************************************
* LOCAL VARIABLES
*/
static uint8 s_irqValue; // 中斷值
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/**
@brief BMA423中斷初始化函數
@param 無
@return 無
*/
void Board_Bma423IrqInit(void)
{
ret_code_t errCode;
// 需先調用nrf_drv_gpiote_init(),但如果有其他GPIOE中斷程序已調用,在這裏可以不調用
if(!nrf_drv_gpiote_is_init())
{
errCode = nrf_drv_gpiote_init(); // GPIOE驅動初始化
APP_ERROR_CHECK(errCode);
}
nrf_drv_gpiote_in_config_t inConfig = GPIOTE_CONFIG_IN_SENSE_HITOLO(false); // 下降沿觸發
inConfig.pull = NRF_GPIO_PIN_PULLUP; // 默認上拉
errCode = nrf_drv_gpiote_in_init(BMA423_IRQ_IO, &inConfig, irqCallbackFunc);
APP_ERROR_CHECK(errCode);
nrf_drv_gpiote_in_event_enable(BMA423_IRQ_IO, true);
}
/*********************************************************************
* LOCAL FUNCTIONS
*/
/**
@brief 中斷觸發回調函數
@param pin -[in] 產生中斷的引腳
@return 無
*/
static void irqCallbackFunc(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
s_irqValue = 0; // 清除中斷值
if(pin == BMA423_IRQ_IO)
{
s_irqValue |= BMA423_IRQ_VALUE; // 保存中斷值
}
BMA423_HandleIrq(s_irqValue);
}
/****************************************************END OF FILE****************************************************/
4.4 board_gpi.h
#ifndef _BOARD_GPI_H_
#define _BOARD_GPI_H_
/*********************************************************************
* INCLUDES
*/
#include "common.h"
/*********************************************************************
* DEFINITIONS
*/
#define BMA423_IRQ_IO 3
#define BMA423_IRQ_VALUE 0x0001 // 中斷值
/*********************************************************************
* API FUNCTIONS
*/
void Board_Bma423IrqInit(void);
#endif /* _BOARD_GPI_H_ */
五、API調用
需包含頭文件 board_bma423.h、board_gpi.h
BMA423_Init
功能 | BMA423初始化函數 |
---|---|
函數定義 | void BMA423_Init(void) |
參數 | 無 |
返回 | 無 |
Board_Bma423IrqInit
功能 | BMA423的中斷引腳初始化函數 |
---|---|
函數定義 | void Board_Bma423IrqInit(void) |
參數 | 無 |
返回 | 無 |
BMA423_ReadFifoData
功能 | BMA423讀取FIFO傳感數據 |
---|---|
函數定義 | uint16 BMA423_ReadFifoData(struct bma4_accel *pAccelData, uint16 *pAccelLen) |
參數 | pAccelData:加速計數據緩衝區,存儲FIFO中的數據 pAccelLen:加速度數據條數 |
返回 | 0 - 成功;非0 - 失敗 |
BMA423_ReadAccelData
功能 | BMA423讀取三軸加速度數據 |
---|---|
函數定義 | uint16 BMA423_ReadAccelData(struct bma4_accel *pAccelData) |
參數 | pAccelData:加速計數據緩衝區 |
返回 | 0 - 成功;非0 - 失敗 |
六、使用例子
6.1 初始化
1)添加頭文件
#include "board_bma423.h"
#include "board_gpi.h"
2)添加初始化代碼(main.c的main函數中)
/**@brief Function for application main entry.
*/
int main(void)
{
bool erase_bonds;
/*-------------------------- 外設驅初始化 ---------------------------*/
// Initialize.
log_init(); // 日誌驅動初始化
timers_init(); // 定時器驅動初始化(在此加入自定義定時器)
I2C_Init(); // I2C驅動初始化
BMA423_Init(); // BMA423三軸加速計驅動初始化
I2C_Disable(); // 禁用I2C,進入低功耗模式,等待讀加速度時再開啓
Board_Bma423IrqInit(); // BMA423三軸加速計中斷初始化
···
···
/*-------------------------- 開啓應用 ---------------------------*/
// Start execution.
NRF_LOG_INFO("Template example started.");
···
}
6.2 檢測初始化完成
#include "bma4.h"
I2C_Enable();
DelayMs(20);
struct bma4_accel sensorDataTemp;
BMA423_ReadAccelData(&sensorDataTemp);
if((abs(sensorDataTemp.x) + abs(sensorDataTemp.x) + abs(sensorDataTemp.x)) > 10)
{
NRF_LOG_INFO("G-Sensor OK");
}
else
{
NRF_LOG_INFO("G-Sensor Error---------");
}
I2C_Disable();
6.3 讀FIFO數據和立即採集一條數據
uint8 i = 0;
struct bma4_accel sensorDataBuf[36] = {0};
uint16 sensorDataNum = 0;
BMA423_ReadFifoData(sensorDataBuf, &sensorDataNum);
if(sensorDataNum > 0)
{
for(i = 0; (i < sensorDataNum && i < 5); i++)
{
NRF_LOG_INFO("FX:%d, FY:%d, FZ:%d", sensorDataBuf[i].x, sensorDataBuf[i].y, sensorDataBuf[i].z);
}
}
if(sensorDataNum < 5)
{
struct bma4_accel sensorDataTemp;
BMA423_ReadAccelData(&sensorDataTemp);
NRF_LOG_INFO("accel:X:%d, Y:%d, Z:%d", sensorDataTemp.x, sensorDataTemp.y, sensorDataTemp.z);
}
6.4 中斷處理,傳感器有動作產生
void BMA423_HandleIrq(uint8 irqValue)
{
uint8 value;
if(irqValue & BMA423_IRQ_VALUE)
{
I2C_Enable();
DelayMs(20); // I2C開啓到讀取數據至少延遲20毫秒
I2C_ReadData(BMA4_I2C_ADDR_PRIMARY, BMA4_INT_STAT_0_ADDR, &value, 1);
I2C_Disable();
// INT_STATUS_0寄存器第6bit置1則有動作產生,0則無動作
if(value & 0x40)
{
NRF_LOG_INFO("any_motion \r\n" );
}
}
}
• 由 Leung 寫於 2020 年 6 月 1 日
• 參考:BMA4xy Sensor API
博世BMA400傳感器API (中文說明)
BMA423 DataSheet【siui】