/* * Acc_ADXL355.c * * Created on: July 12, 2020 * Author: lqh */ #include "Acc_ADXL355.h" #include "main.h" /* ADXL355 registers addresses */ #define ADXL355_DEVID_AD 0x00 #define ADXL355_DEVID_MST 0x01 #define ADXL355_PARTID 0x02 #define ADXL355_REVID 0x03 #define ADXL355_STATUS 0x04 #define ADXL355_FIFO_ENTRIES 0x05 #define ADXL355_TEMP2 0x06 #define ADXL355_TEMP1 0x07 #define ADXL355_XDATA3 0x08 #define ADXL355_XDATA2 0x09 #define ADXL355_XDATA1 0x0A #define ADXL355_YDATA3 0x0B #define ADXL355_YDATA2 0x0C #define ADXL355_YDATA1 0x0D #define ADXL355_ZDATA3 0x0E #define ADXL355_ZDATA2 0x0F #define ADXL355_ZDATA1 0x10 #define ADXL355_FIFO_DATA 0x11 #define ADXL355_OFFSET_X_H 0x1E #define ADXL355_OFFSET_X_L 0x1F #define ADXL355_OFFSET_Y_H 0x20 #define ADXL355_OFFSET_Y_L 0x21 #define ADXL355_OFFSET_Z_H 0x22 #define ADXL355_OFFSET_Z_L 0x23 #define ADXL355_ACT_EN 0x24 #define ADXL355_ACT_THRESH_H 0x25 #define ADXL355_ACT_THRESH_L 0x26 #define ADXL355_ACT_COUNT 0x27 #define ADXL355_FILTER 0x28 #define ADXL355_FIFO_SAMPLES 0x29 #define ADXL355_INT_MAP 0x2A #define ADXL355_SYNC 0x2B #define ADXL355_RANGE 0x2C #define ADXL355_POWER_CTL 0x2D #define ADXL355_SELF_TEST 0x2E #define ADXL355_RESET 0x2F /** 初始化ADXL加速度计*/ int Acc_ADXL355_init(Acc_ADXL355_t *Acc, const char *name, SPI_DEV_t *dev, GPIO_EXIT_t *exti) { int rslt; uint8_t TxdBuf[4]; uint8_t RxdBuf[4]; uint8_t ChipId, MemsId, PartId; //Read ADXL355 Chip Infomation rslt = 0; Acc->name = name; Acc->_dev = dev; Acc->exti = exti; Acc->Ax = 0; Acc->Ay = 0; Acc->Az = 0; Acc->At = 0; Acc->read_cnt = 0; Acc->exti->cnt = 0; Acc->cnt = 0; Acc->last_cnt = 0; Acc->pps = 0; SPI_DEV_begin(Acc->_dev, -1); /* Quick verification test for boards */ TxdBuf[0] = ((ADXL355_DEVID_AD << 1) | 0x01); //Read ChipId/MemsId/PartId, Lowbit = 1 means Read SPI_DEV_select(dev); SPI_DEV_transfer(dev, TxdBuf, 4, RxdBuf, 4, 2); SPI_DEV_unselect(dev); ChipId = RxdBuf[1]; MemsId = RxdBuf[2]; PartId = RxdBuf[3]; //If Target Chip is ADXL355, Set Chip Range & Turn on Accelerometer Mode if ((ChipId == 0xAD) && (MemsId == 0x1D) && (PartId == 0xED)) { TxdBuf[0] = ADXL355_RANGE << 1; //Write ADXL355_POWER_CTL, Lowbit 0 means write TxdBuf[1] = 0x83; //RANG +-8G, High speed mode, Int1/Int2 active low Acc->lsb_per_g = 64000.0f; SPI_DEV_select(dev); SPI_DEV_transfer(dev, TxdBuf, 2, NULL, 0, 2); SPI_DEV_unselect(dev); //Set LowPass Filter & ODR TxdBuf[0] = ADXL355_FILTER << 1; //Write ADXL355_POWER_CTL, Lowbit 0 means write TxdBuf[1] = 0x02; //Disable HPF, LPF=250Hz, ODR=1000Hz SPI_DEV_select(dev); SPI_DEV_transfer(dev, TxdBuf, 2, NULL, 0, 2); SPI_DEV_unselect(dev); /* Turn On Meas Accelerometer Mode */ TxdBuf[0] = ADXL355_POWER_CTL << 1; //Write ADXL355_POWER_CTL, Lowbit 0 means write TxdBuf[1] = 0; //STANDBY bit = 0, Means Turn on Measure Mode SPI_DEV_select(dev); SPI_DEV_transfer(dev, TxdBuf, 2, NULL, 0, 2); SPI_DEV_unselect(dev); } else { rslt = -1; } SPI_DEV_end(Acc->_dev); if (!rslt) { int i; float N[3]; float Temp[1]; TxdBuf[0] = ADXL355_SELF_TEST << 1; //Write ADXL355_POWER_CTL, Lowbit 0 means write TxdBuf[1] = 1; // test mode 1, test force 0 SPI_DEV_begin(Acc->_dev, -1); SPI_DEV_select(Acc->_dev); SPI_DEV_transfer(Acc->_dev, TxdBuf, 2, NULL, 0, 2); SPI_DEV_unselect(Acc->_dev); SPI_DEV_end(Acc->_dev); for (i=0;i<5;++i) { HAL_Delay(5); Acc_ADXL355_update(Acc); } for (i=0;i<3;++i) { N[i] = 9999; } Temp[0] = 9999; Acc_ADXL355_read(Acc, N, Temp); for (i=0;i<3;++i) { if (N[i] > 0.2f || N[i] < -0.2f) { rslt |= (1>>i); } } if (Temp[0] > 150.0f || Temp[0] < -40.0f) { rslt |= (1>>3); } TxdBuf[0] = ADXL355_SELF_TEST << 1; //Write ADXL355_POWER_CTL, Lowbit 0 means write TxdBuf[1] = 3; // test mode 1, test force 0 SPI_DEV_begin(Acc->_dev, -1); SPI_DEV_select(Acc->_dev); SPI_DEV_transfer(Acc->_dev, TxdBuf, 2, NULL, 0, 2); SPI_DEV_unselect(Acc->_dev); SPI_DEV_end(Acc->_dev); for (i=0;i<5;++i) { HAL_Delay(5); Acc_ADXL355_update(Acc); } for (i=0;i<3;++i) { N[i] = 9999; } Temp[0] = 9999; Acc_ADXL355_read(Acc, N, Temp); if (N[0] > 0.5f || N[0] < 0.2f) { rslt |= (1>>0); } if (N[1] > 0.5f || N[1] < 0.2f) { rslt |= (1>>1); } if (N[2] > 1.5f || N[2] < 1.1f) { rslt |= (1>>2); } if (Temp[0] > 150.0f || Temp[0] < -40.0f) { rslt |= (1>>3); } TxdBuf[0] = ADXL355_SELF_TEST << 1; //Write ADXL355_POWER_CTL, Lowbit 0 means write TxdBuf[1] = 0; // test mode 1, test force 0 SPI_DEV_begin(Acc->_dev, -1); SPI_DEV_select(Acc->_dev); SPI_DEV_transfer(Acc->_dev, TxdBuf, 2, NULL, 0, 2); SPI_DEV_unselect(Acc->_dev); SPI_DEV_end(Acc->_dev); } return rslt; } /** 关闭ADXL355芯片 */ bool Acc_ADXL355_Standby(Acc_ADXL355_t *Acc) { uint8_t TxdBuf[2]; TxdBuf[0] = ADXL355_POWER_CTL << 1; //Write ADXL355_POWER_CTL, Lowbit 0 means write TxdBuf[1] = 1; //STANDBY bit = 1, turn to standby mode 待机模式 if (!SPI_DEV_begin(Acc->_dev, 10)) { return false; } SPI_DEV_select(Acc->_dev); SPI_DEV_transfer(Acc->_dev, TxdBuf, 2, NULL, 0, 2); SPI_DEV_unselect(Acc->_dev); SPI_DEV_end(Acc->_dev); return true; } /** 重新启动ADXL355 */ bool Acc_ADXL355_Awake(Acc_ADXL355_t *Acc) { uint8_t TxdBuf[2]; TxdBuf[0] = ADXL355_POWER_CTL << 1; //Write ADXL355_POWER_CTL, Lowbit 0 means write TxdBuf[1] = 0; //STANDBY bit = 0, turn to measurement mode 测量模式 if (!SPI_DEV_begin(Acc->_dev, 10)) { return false; } SPI_DEV_select(Acc->_dev); SPI_DEV_transfer(Acc->_dev, TxdBuf, 2, NULL, 0, 2); SPI_DEV_unselect(Acc->_dev); SPI_DEV_end(Acc->_dev); return true; } /** 读取ADXL355值 */ bool Acc_ADXL355_update(Acc_ADXL355_t *Acc) { uint8_t TxdBuf[16]; uint8_t RxdBuf[16]; int i; int32_t TempAcceleratorData; bool rslt; if (SPI_DEV_begin(Acc->_dev, 0)) //进入临界区 { TxdBuf[0] = ((ADXL355_TEMP2 << 1) | 1); //Read PARTID, Lowbit = 1 means Read for (i = 1; i < 12; i++) { TxdBuf[i] = 0xAA; //Dummy Byte 虚拟字节 } SPI_DEV_select(Acc->_dev); rslt = SPI_DEV_transfer(Acc->_dev, TxdBuf, 12, RxdBuf, 12, 3); SPI_DEV_unselect(Acc->_dev); SPI_DEV_end(Acc->_dev); //退出临界区 Acc->exti->cnt = 0; //中断计数清零 if (rslt) { Acc->cnt++; taskENTER_CRITICAL(); Acc->read_cnt++; //Data combination for Ax Raw Data TempAcceleratorData = (((RxdBuf[3] << 16) | (RxdBuf[4] << 8) | RxdBuf[5]) >> 4); if ((TempAcceleratorData & 0x00080000) != 0) //Sign-extending for raw data { TempAcceleratorData |= 0xFFF00000; } Acc->Ax += TempAcceleratorData; //Accumulated Value of ax x轴 //Data combination for Ay Raw Data TempAcceleratorData = (((RxdBuf[6] << 16) | (RxdBuf[7] << 8) | RxdBuf[8]) >> 4); if ((TempAcceleratorData & 0x00080000) != 0) //Sign-extending for raw data { TempAcceleratorData |= 0xFFF00000; } Acc->Ay += TempAcceleratorData; //Accumulated Value of ay y轴 //Data combination for Az Raw Data TempAcceleratorData = (((RxdBuf[9] << 16) | (RxdBuf[10] << 8) | RxdBuf[11]) >> 4); if ((TempAcceleratorData & 0x00080000) != 0) //Sign-extending for raw data { TempAcceleratorData |= 0xFFF00000; } Acc->Az += TempAcceleratorData; //Accumulated Value of az z轴 //Data combination for Temperature Raw Data TempAcceleratorData = ((RxdBuf[1] << 8) | RxdBuf[2]); if ((TempAcceleratorData & 0x00000800) != 0) //Sign-extending for raw data { TempAcceleratorData |= 0xFFFFF000; } Acc->At += TempAcceleratorData; //Accumulated Value of Temperature 温度 taskEXIT_CRITICAL(); } } else { rslt = false; } return rslt; } int Acc_ADXL355_read(Acc_ADXL355_t *Acc, float N[3], float Temp[1]) { int cnt = Acc->read_cnt; if (cnt > 0) //采样次数完成,ADXL355待机,准备上报数据 { taskENTER_CRITICAL(); N[0] = Acc->Ax / (cnt * Acc->lsb_per_g); //ax N[1] = Acc->Ay / (cnt * Acc->lsb_per_g); //ay N[2] = Acc->Az / (cnt * Acc->lsb_per_g); //az Temp[0] = 25 - (((Acc->At / cnt) - 1852) / 9.05f); //temp Acc->Ax = 0; Acc->Ay = 0; Acc->Az = 0; Acc->At = 0; Acc->read_cnt = 0; taskEXIT_CRITICAL(); } return cnt; } void Acc_ADXL355_stats(Acc_ADXL355_t *Acc) { Acc->pps = Acc->cnt - Acc->last_cnt; Acc->last_cnt = Acc->cnt; }