123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657 |
- /*Includes ----------------------------------------------*/
- #include "nrf_delay.h"
- #include "drv_iic_middle.h"
- #include "drv_qma7981.h"
- /*Private macro ------------------------------------------------*/
- #define ADO 0 // I2C Address pin, 0 for low and 1 for high
- #define QMA7981_ADDRESS_LEN 1
- #if ADO == 1
- #define I2C_ADDRESS (0x13 << 1) //0b0010011 Device address when ADO = 1
- #else
- #define I2C_ADDRESS (0x12 << 1) //0b0010010 Device address when ADO = 0
- #endif
- /*qma7981 full scale range*/
- #define RANGE_2G 0x01
- #define RANGE_4G 0x02
- #define RANGE_8G 0x04
- #define RANGE_16G 0x08
- #define RANGE_32G 0x0F
- /*qma7981 bandwidth*/
- #define MCLK_DIV_BY_7695 0x00
- #define MCLK_DIV_BY_3855 0x01
- #define MCLK_DIV_BY_1935 0x02
- #define MCLK_DIV_BY_975 0x03
- #define MCLK_DIV_BY_15375 0x05
- #define MCLK_DIV_BY_30735 0x06
- #define MCLK_DIV_BY_61455 0x07
- /*qma7981 clock freq*/
- #define CLK_500_KHZ 0x01
- #define CLK_333_KHZ 0x00
- #define CLK_200_KHZ 0x02
- #define CLK_100_KHZ 0x03
- #define CLK_50_KHZ 0x04
- #define CLK_25_KHZ 0x05
- #define CLK_12_KHZ_5 0x06
- #define CLK_5_KHZ 0x07
- /*qma7981 no motion duration*/
- #define NO_MOTION_1_SEC 0x00
- #define NO_MOTION_2_SEC 0x01
- #define NO_MOTION_3_SEC 0x02
- #define NO_MOTION_5_SEC 0x04
- #define NO_MOTION_10_SEC 0x09
- #define NO_MOTION_15_SEC 0x0E
- #define NO_MOTION_30_SEC 0x12
- #define NO_MOTION_1_MIN 0x18
- #define NO_MOTION_2_MIN 0x22
- #define NO_MOTION_3_MIN 0x28
- #define NO_MOTION_4_MIN 0x2E
- /*qma7981 any motion samples*/
- #define NUM_SAMPLES_1 0x00
- #define NUM_SAMPLES_2 0x01
- #define NUM_SAMPLES_3 0x02
- #define NUM_SAMPLES_4 0x03
- /*qma7981 mode*/
- #define MODE_STANDBY 0x00
- #define MODE_ACTIVE 0x01
- /*qma7981 motion_detect*/
- #define MOTION_DETECT_NOTHING 0x00
- #define MOTION_DETECT_ANY_MOTION 0x01
- #define MOTION_DETECT_NO_MOTION 0x02
- /*STRUCTION -----------------------------------------------------*/
- typedef enum qma7981_mode
- {
- Qma7981_Mode_Standby = 0,
-
- Qma7981_Mode_Active = 1,
-
- } Qma7981_Mode_t;
- typedef int32_t (*qma_write_ptr)(void *, uint8_t, const uint8_t *, uint16_t);
- typedef int32_t (*qma_read_ptr)(void *, uint8_t, uint8_t *, uint16_t);
- typedef struct
- {
- /** Component mandatory fields **/
- qma_write_ptr write_reg;
-
- qma_read_ptr read_reg;
-
- } qma_ctx_t;
- typedef struct drv_qma7981
- {
- qma_ctx_t ctx; //抽象层接口(如I2C/SPI,外部不可操作,属于私有成员)
-
- qma_data_t cur_data; //当前QMA数据
-
- drv_qma_config_param_t cur_param; //当前QMA配置
-
- } Drv_Qma7981_t;
- /*Local Variable ----------------------------------------------*/
- static Drv_Qma7981_t ob_qma7981;
- static qma_data_t data_raw_acceleration; //临时存储加速度原始数据
- /*Local Functions ----------------------------------------------*/
- static void platform_delay_ms(uint32_t ms)
- {
- nrf_delay_ms(ms);
- }
- static int32_t qma7981_platform_write(void *handle, uint8_t reg, const uint8_t *bufp, uint16_t len)
- {
- int32_t ierror = 0;
-
- if(IIC_MIDDLE_WriteBytes(I2C_ADDRESS,reg,(uint8_t *)bufp,len) != true)
- {
- ierror = -1;
- }
-
- return ierror;
- }
- static int32_t qma7981_platform_read(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len)
- {
- int32_t ierror = 0;
-
- if(IIC_MIDDLE_ReadBytes(I2C_ADDRESS,reg,bufp,len) != true)
- {
- ierror = -1;
- }
-
- return ierror;
- }
- static int read_accel_axis(uint8_t address_msb, int16_t *result)
- {
- int ret;
- int16_t data;
- uint8_t accel_axis_buf[2];
-
- ret = ob_qma7981.ctx.read_reg(0,address_msb,accel_axis_buf,2);
- if(ret == -1)return -1;
-
- data = (accel_axis_buf[0]&0xFC) | (accel_axis_buf[1]<< 8);
-
- data = data / 4; // divide the result by 4 to maintain the sign, since the data is 14 bits
-
- *result = data;
-
- return 0;
- }
- static int get_accel_x(int16_t *result)
- {
- int ret;
- int16_t data;
-
- ret = read_accel_axis(0x01, &data);
- if(ret == -1)return -1;
-
- *result = data;
-
- return 0;
- }
- static int get_accel_y(int16_t *result)
- {
- int ret;
- int16_t data;
-
- ret = read_accel_axis(0x03, &data);
- if(ret == -1)return -1;
-
- *result = data;
-
- return 0;
- }
- static int get_accel_z(int16_t *result)
- {
- int ret;
- int16_t data;
-
- ret = read_accel_axis(0x05, &data);
- if(ret == -1)return -1;
-
- *result = data;
-
- return 0;
- }
- static void set_bit(uint8_t *byte, uint8_t n, bool value)
- {
- *byte = (*byte & ~(1UL << n)) | (value << n);
- }
- static void get_bit(uint8_t *byte, uint8_t n, bool *p_value)
- {
- if((*byte & (1UL << n)) > 0)
- {
- *p_value = true;
- }
- else
- {
- *p_value = false;
- }
- }
- static int soft_reset(void)
- {
- int ret;
- uint8_t data;
-
- data = 0xB6;
- ret = ob_qma7981.ctx.write_reg(0,0x36,&data,1); //0xB6, soft reset all of the registers.
- if(ret == -1)return 1;
-
- data = 0x00;
- ret = ob_qma7981.ctx.write_reg(0,0x36,&data,1); //After soft-reset, user should write 0x00 back
- if(ret == -1)return 1;
-
- return 0;
- }
- static int set_mode(Qma7981_Mode_t mode)
- {
- int ret;
- uint8_t data;
-
- ret = ob_qma7981.ctx.read_reg(0,0x11,&data,1);
- if(ret == -1)return -1;
-
- set_bit(&data,7,mode);
-
- ret = ob_qma7981.ctx.write_reg(0,0x11,&data,1);
- if(ret == -1)return -1;
-
- return 0;
- }
- static int get_mode(Qma7981_Mode_t *p_mode)
- {
- int ret;
- uint8_t data;
- bool is_set;
-
- ret = ob_qma7981.ctx.read_reg(0,0x11,&data,1);
- if(ret == -1)return -1;
-
- get_bit(&data, 7, &is_set);
-
- if(is_set)
- {
- *p_mode = Qma7981_Mode_Active;
- }
- else
- {
- *p_mode = Qma7981_Mode_Standby;
- }
- return 0;
- }
- static int set_clock_freq(uint8_t freq)
- {
- int ret;
- uint8_t data;
-
- ret = ob_qma7981.ctx.read_reg(0,0x11,&data,1);
- if(ret == -1)return -1;
-
- data &= 0xF0;
- data |= (freq & 0x0F);
-
- ret = ob_qma7981.ctx.write_reg(0,0x11,&data,1);
- if(ret == -1)return -1;
-
- return 0;
- }
- static int get_clock_freq(uint8_t *p_freq)
- {
- int ret;
- uint8_t data;
-
- ret = ob_qma7981.ctx.read_reg(0,0x11,&data,1);
- if(ret == -1)return -1;
-
- *p_freq = (data & 0x0F);
-
- return 0;
- }
- static int set_bandwidth(uint8_t bandwidth)
- {
- int ret;
- uint8_t data;
-
- data = 0xE0;
- data |= (bandwidth & 0x07);
-
- ret = ob_qma7981.ctx.write_reg(0,0x10,&data,1);
- if(ret == -1)return -1;
-
- return 0;
- }
- static int get_bandwidth(uint8_t *p_bandwidth)
- {
- int ret;
- uint8_t data;
-
- ret = ob_qma7981.ctx.read_reg(0,0x10,&data,1);
- if(ret == -1)return -1;
-
- data &= 0x07;
-
- *p_bandwidth = data;
-
- return 0;
- }
- static int set_interrupt_pin_1_type(bool open_drain, bool active_high)
- {
- int ret;
- uint8_t data;
-
- ret = ob_qma7981.ctx.read_reg(0,0x20,&data,1);
- if(ret == -1)return -1;
-
- set_bit(&data, 0, active_high);
- set_bit(&data, 1, open_drain);
-
- ret = ob_qma7981.ctx.write_reg(0,0x20,&data,1);
- if(ret == -1)return -1;
-
- return 0;
- }
- static int set_full_scale_range(uint8_t range)
- {
- int ret;
- uint8_t data;
-
- ret = ob_qma7981.ctx.read_reg(0,0x0F,&data,1);
- if(ret == -1)return -1;
-
- data &= 0xF0;
- data |= (range & 0x0F);
-
- ret = ob_qma7981.ctx.write_reg(0,0x0F,&data,1);
- if(ret == -1)return -1;
-
- return 0;
- }
- static int get_full_scale_range(uint8_t *p_range)
- {
- int ret;
- uint8_t data;
-
- ret = ob_qma7981.ctx.read_reg(0,0x0F,&data,1);
- if(ret == -1)return -1;
-
- data &= 0x0F;
-
- *p_range = data;
-
- return 0;
- }
- /*API ----------------------------------------------*/
- /**
- @brief 初始化QMA驱动
- @param 无
- @return 错误代码 - [out] -1失败,0成功
- */
- int drv_qma_Init(void)
- {
- int ret;
- //初始化结构体
- memset(&ob_qma7981.cur_data,0,sizeof(ob_qma7981.cur_data));
- ob_qma7981.cur_param.acc_fs = QMA_ACC_FS_2G;
- ob_qma7981.cur_param.acc_odr = QMA_ACC_ODR_OFF;
- ob_qma7981.ctx.read_reg = qma7981_platform_read;
- ob_qma7981.ctx.write_reg = qma7981_platform_write;
- //供电
- nrf_gpio_cfg(
- PIN_QMA7981_POWER,
- NRF_GPIO_PIN_DIR_OUTPUT,
- NRF_GPIO_PIN_INPUT_DISCONNECT,
- NRF_GPIO_PIN_NOPULL,
- NRF_GPIO_PIN_H0H1,
- NRF_GPIO_PIN_NOSENSE);
- nrf_gpio_pin_write(PIN_QMA7981_POWER,0);
- platform_delay_ms(200);
-
- nrf_gpio_pin_write(PIN_QMA7981_POWER,1);
-
- nrf_gpio_cfg_output(PIN_QMA7981_AD0);
- nrf_gpio_pin_write(PIN_QMA7981_AD0,ADO);
-
- nrf_gpio_cfg_output(PIN_QMA7981_nCS);
- nrf_gpio_pin_write(PIN_QMA7981_nCS,1);
-
- platform_delay_ms(200);
- IIC_MIDDLE_Init();
- ret = soft_reset(); //soft reset all of the registers, need to at least delay 10ms after called the function.
- if(ret == -1)return -1;
-
- return 0;
- }
- /**
- @brief QMA断电
- @param 无
- @return 错误代码 - [out] -1失败,0成功
- */
- int drv_qma_power_off(void)
- {
- //断电,清空qma配置
- nrf_gpio_cfg(
- PIN_QMA7981_POWER,
- NRF_GPIO_PIN_DIR_OUTPUT,
- NRF_GPIO_PIN_INPUT_DISCONNECT,
- NRF_GPIO_PIN_NOPULL,
- NRF_GPIO_PIN_H0H1,
- NRF_GPIO_PIN_NOSENSE);
-
- nrf_gpio_cfg_output(PIN_QMA7981_AD0);
- nrf_gpio_cfg_output(PIN_QMA7981_SDA);
- nrf_gpio_cfg_output(PIN_QMA7981_SCLK);
- nrf_gpio_cfg_output(PIN_QMA7981_nCS);
-
- nrf_gpio_pin_write(PIN_QMA7981_AD0,0);
- nrf_gpio_pin_write(PIN_QMA7981_SDA,0);
- nrf_gpio_pin_write(PIN_QMA7981_SCLK,0);
- nrf_gpio_pin_write(PIN_QMA7981_nCS,0);
-
- nrf_gpio_pin_write(PIN_QMA7981_POWER,0);
-
- return 0;
- }
- /**
- @brief QMA上电(默认配置挂起)
- @param 无
- @return 错误代码 - [out] -1失败,0成功
- */
- int drv_qma_power_on(void)
- {
- int ret;
-
- nrf_gpio_cfg(
- PIN_QMA7981_POWER,
- NRF_GPIO_PIN_DIR_OUTPUT,
- NRF_GPIO_PIN_INPUT_DISCONNECT,
- NRF_GPIO_PIN_NOPULL,
- NRF_GPIO_PIN_H0H1,
- NRF_GPIO_PIN_NOSENSE);
-
- nrf_gpio_pin_write(PIN_QMA7981_POWER,1);
-
- nrf_gpio_cfg_output(PIN_QMA7981_AD0);
-
- nrf_gpio_pin_write(PIN_QMA7981_AD0,ADO);
- nrf_gpio_cfg_output(PIN_QMA7981_nCS);
- nrf_gpio_pin_write(PIN_QMA7981_nCS,1);
-
- IIC_MIDDLE_Init();
-
- //初始化结构体
- memset(&ob_qma7981.cur_data,0,sizeof(ob_qma7981.cur_data));
- ob_qma7981.cur_param.acc_fs = QMA_ACC_FS_2G;
- ob_qma7981.cur_param.acc_odr = QMA_ACC_ODR_OFF;
-
- // platform_delay_ms(10);
-
- ret = soft_reset(); //soft reset all of the registers, need to at least delay 10ms after called the function.
- if(ret == -1)return -1;
-
- return 0;
- }
- /**
- @brief 设置ACC量程
- @param acc_fs - [in] ACC量程
- @return 错误代码 - [out] -1失败,0成功
- */
- int drv_qma_set_acc_fs(QMA_ACC_FS_e acc_fs)
- {
- int ret;
- uint8_t range;
-
- if(ob_qma7981.cur_param.acc_fs != acc_fs)
- {
- switch(acc_fs)
- {
- case QMA_ACC_FS_2G:
- ret = set_full_scale_range(RANGE_2G); //set full scale acceleration range
- if(ret == -1)return -1;
-
- ret = get_full_scale_range(&range);
- if(ret == -1)return -1;
-
- if(range != RANGE_2G)return -1;
-
- ob_qma7981.cur_param.acc_fs = QMA_ACC_FS_2G;
- break;
- case QMA_ACC_FS_16G:
- ret = set_full_scale_range(RANGE_16G); //set full scale acceleration range
- if(ret == -1)return -1;
-
- ret = get_full_scale_range(&range);
- if(ret == -1)return -1;
-
- if(range != RANGE_16G)return -1;
-
- ob_qma7981.cur_param.acc_fs = QMA_ACC_FS_16G;
- break;
- }
- }
-
- return 0;
- }
- /**
- @brief 设置ACC采样频率
- @param acc_odr - [in] ACC采样频率
- @return 错误代码 - [out] -1失败,0成功
- */
- int drv_qma_set_acc_odr(QMA_ACC_ODR_e acc_odr)
- {
- int ret;
- uint8_t freq, bandwidth;
- Qma7981_Mode_t mode;
-
- if(ob_qma7981.cur_param.acc_odr != acc_odr)
- {
- switch(acc_odr)
- {
- case QMA_ACC_ODR_OFF:
- ret = set_mode(Qma7981_Mode_Standby); //sleep mode
- if(ret == -1)return -1;
- ret = get_mode(&mode);
- if(ret == -1)return -1;
-
- if(mode != Qma7981_Mode_Standby)return -1;
-
- ob_qma7981.cur_param.acc_odr = QMA_ACC_ODR_OFF;
- break;
- case QMA_ACC_ODR_12HZ5:
- ret = set_mode(Qma7981_Mode_Active); //bring out of sleep mode
- if(ret == -1)return -1;
-
- ret = get_mode(&mode);
- if(ret == -1)return -1;
-
- if(mode != Qma7981_Mode_Active)return -1;
-
- //odr = 2 * BW; odr = 2 * (12.5KHZ / 1935) = 12.91HZ;
-
- ret = set_clock_freq(CLK_12_KHZ_5); //set digital clock freq
- if(ret == -1)return -1;
-
- ret = get_clock_freq(&freq);
- if(ret == -1)return -1;
-
- if(freq != CLK_12_KHZ_5)return -1;
-
- ret = set_bandwidth(MCLK_DIV_BY_1935); //set bandwitch (samples per sec)
- if(ret == -1)return -1;
- ret = get_bandwidth(&bandwidth);
- if(ret == -1)return -1;
-
- if(bandwidth != MCLK_DIV_BY_1935)return -1;
-
- ob_qma7981.cur_param.acc_odr = QMA_ACC_ODR_12HZ5;
- break;
- case QMA_ACC_ODR_104HZ:
- ret = set_mode(Qma7981_Mode_Active); //bring out of sleep mode
- if(ret == -1)return -1;
-
- ret = get_mode(&mode);
- if(ret == -1)return -1;
-
- if(mode != Qma7981_Mode_Active)return -1;
-
- //odr = 2 * BW; odr = 2 * (200KHZ / 3855) = 103.76HZ;
-
- ret = set_clock_freq(CLK_200_KHZ); //set digital clock freq
- if(ret == -1)return -1;
-
- ret = get_clock_freq(&freq);
- if(ret == -1)return -1;
-
- if(freq != CLK_200_KHZ)return -1;
-
- ret = set_bandwidth(MCLK_DIV_BY_3855); //set bandwitch (samples per sec)
- if(ret == -1)return -1;
- ret = get_bandwidth(&bandwidth);
- if(ret == -1)return -1;
-
- if(bandwidth != MCLK_DIV_BY_3855)return -1;
-
- ob_qma7981.cur_param.acc_odr = QMA_ACC_ODR_104HZ;
- break;
- }
- }
-
- return 0;
- }
- /**
- @brief 获取QMA配置参数
- @param param - [in] QMA配置参数
- @return 错误代码 - [out] -1失败,0成功
- */
- int drv_qma_get_config_param(drv_qma_config_param_t *p_param)
- {
- *p_param = ob_qma7981.cur_param;
-
- return 0;
- }
- /**
- @brief 获取QMA的ACC数据
- @param p_data - [out] 返回的ACC三轴数据
- @return 错误代码 - [out] -1失败,0成功
- */
- int drv_qma_get_acc_data(qma_data_t *p_data)
- {
- int ret;
-
- if(ob_qma7981.cur_param.acc_odr != QMA_ACC_ODR_OFF)
- {
- memset( &data_raw_acceleration, 0, sizeof(data_raw_acceleration));
-
- ret = get_accel_x(&data_raw_acceleration.acc[0]);
- if(ret == -1)return -1;
-
- ret = get_accel_y(&data_raw_acceleration.acc[1]);
- if(ret == -1)return -1;
-
- ret = get_accel_z(&data_raw_acceleration.acc[2]);
- if(ret == -1)return -1;
-
- p_data->acc[0] = data_raw_acceleration.acc[0];
- p_data->acc[1] = data_raw_acceleration.acc[1];
- p_data->acc[2] = data_raw_acceleration.acc[2];
- }
- else
- {
- return -1;
- }
-
- return 0;
- }
|