Recently engaged in a project related to the accelerometer, so contact with more sensors, now write a summary, to prevent the later and I like to walk so many detours.
The first thing to see is the pin graph, if the driver should not first troubleshoot the hardware problem:
SPI Connection method
IIc Connection method
We then focus on a few registers:
sensor Name (read/write) |
Register number |
function |
Chipid (R) |
0x00 |
The ID of the chip, generally used to see if the driver is normal, fixed value 0xd1 |
Pmu_status (R) |
0x03 |
Display the current power mode of each sensor, divided into three modes normal\low_power\suspend |
Acc_conf (RW) |
0x40 |
Set the output data rate, bandwidth, and acceleration sensor read mode |
Acc_range |
0x41 |
Allowable acceleration g range of choice |
Gyr_conf (RW) |
0x42 |
Set the output data rate, bandwidth, and gyro read mode in the sensor. |
Gyr_range (RW) |
0x43 |
Defining the BMI160 angular velocity measurement range |
Int_en (RW) |
0x50-0x52 |
Enable a variety of interrupts, including acceleration data, angular velocity data and a variety of special functions of the interrupt, so that can be mapped to the INT1 on the output, you can trigger the MCU external interrupt. |
Int_out_ctrl (RW) |
0x53 |
Output control, including output enable, trigger level, edge, and output mode (push-pull and open-drain) |
Int_latch (RW) |
0x54 |
Set the interrupt latch mode (not very understand, the first is the lock, so there is no interruption of output ..., and then turn it off) |
CMD (R) |
0x7E |
The command register triggers operations such as Softreset, NVM programming, and so on. Special such as: Start_foc, Acc_set_pmu_mode, Gyr_set_pmu_mode, Mag_set_pmu_mode, PROG_NVM, Fifo_flush, Int_reset, Softreset, step _cnt_clr |
Next is a variety of special function registers, not much to say, which configuration that can be
Focus on the function of the pedometer , now also compare fire:
sensor Name (read/write) |
Register number |
function |
Step_conf (RW) |
0x7a-0x7b |
Configuration of step detection, including normal mode,sensitive Mode,robust mode three can also be configured |
STEP_CNT (R) |
0x78-0x79 |
Read the number of steps directly from the two registers, note that the range is -32768--32768 |
The following code slice is the initialization of the step, using the stm32f405:
void Bmi160_init (void) {uint8_t ui8status = 0;
uint8_t ui8attempts = 20;
uint8_t device_id;
Bmi160_spi_init ();
kprintf ("BMI160 Init ok.\n"); Bmi160_cs=1;
SPI chip Select Cancel//Reset the BMI160 sensor Bmi160_reset ();
Put Accel and Gyro in normal mode. while (ui8status! = 0x20 && ui8attempts--) {Bmi160_write_reg (am_devices_bmi160_cmd, 0x12);//Set acceleration
Calculated as Low_power bmi160_write_reg (Am_devices_bmi160_cmd, 0x14);//Set gyroscope suspend Delay_ms (1);
Ui8status = Bmi160_read_reg (am_devices_bmi160_pmu_status);//read acceleration and gyroscope initialized to Low_power suspend}
BMI160 not in correct power mode if (!ui8attempts) {return;
} kprintf ("pmu_status:0x%x \ r \ n", ui8status); Bmi160_write_reg (Am_devices_bmi160_step_conf_0, 0x15);//Pedometer function Bmi160_write_reg (am_devices_bmi160_step_conf_1, 0x0
B); Bmi160_write_reg (Am_devices_bmi160_acc_range, 0x05);/Set Accelerometer +-4g//Read status register to clear it.
Ui8status = Bmi160_read_reg (Am_devices_bmi160_err_reg);//Read error status Register clear Ui8status/Enable INT 1 output as active high Bmi160_write_reg (Am_devices_bmi160_int_out_ctrl, 0x0A);//output enable INT1 pin, high active//int1 Set//Map INT1 to the Step detection Interrupt Bmi160_write_reg (am_devices_bmi160_int_map_1, 0x80);//Map INT1 to watermark interrupt//Ena BLE INT 1 as FIFO Watermark Bmi160_write_reg (am_devices_bmi160_int_en_1, 0x10);//Enable Data-ready}//Get step number void bmi160
_getstep (short *rawstep) {uint8_t buf[2];
buf[0]= Bmi160_read_reg (am_devices_bmi160_step_cnt_1);
buf[1]= Bmi160_read_reg (AM_DEVICES_BMI160_STEP_CNT_0);
*rawstep= ((uint16_t) buf[0]<<8) |buf[1]; }
SPI initialization (I started with the EEPROM SPI configuration read and write, and so on, has not been able to drive, and then suddenly found that the problem is SPI):
The following is BMI160 driver////////////////////void bmi160_spi_init (void) {Gpio_inittypedef gpio_initstructure
;
Spi_inittypedef spi_initstructure; Rcc_ahb1periphclockcmd (Rcc_ahb1periph_gpioa, enable);//enable Gpioa clock Rcc_apb2periphclockcmd (RCC_APB2PERIPH_SPI1, enable); SPI1 clock//GPIOF9,F10 initialization setting Gpio_initstructure.gpio_pin = gpio_pin_5| gpio_pin_6| Gpio_pin_7;//pb3~5 multiplexing function Output Gpio_initstructure.gpio_mode = gpio_mode_af;//multiplexing function Gpio_initstructure.gpio_otype = GPIO_OTy pe_pp;//push-Pull output gpio_initstructure.gpio_speed = Gpio_speed_50mhz;//100mhz GPIO_INITSTRUCTURE.GPIO_PUPD = GPIO_PuPd_UP;/ /Pull Gpio_init (Gpioa, &gpio_initstructure);//Initialize Gpio_pinafconfig (GPIOA,GPIO_PINSOURCE5,GPIO_AF_SPI1); PI1 for SPI1 gpio_pinafconfig (GPIOA,GPIO_PINSOURCE6,GPIO_AF_SPI1); PI2 for SPI1 gpio_pinafconfig (GPIOA,GPIO_PINSOURCE7,GPIO_AF_SPI1); PI3 multiplexing for SPI1//Here only for SPI Port initialization rcc_apb2periphresetcmd (rcc_apb2periph_spi1,enable);//Reset SPI1 Rcc_apb2periphreset CMD (Rcc_apb2periph_spi1,disable);//Stop Reset SPI1 spi_i2s_deinit (SPI1); Spi_initstructure.spi_direction = Spi_direction_2lines_fullduplex; Set SPI unidirectional or bidirectional data mode: SPI set to double-line bidirectional full duplex spi_initstructure.spi_mode = Spi_mode_master; Set SPI operating mode: set to primary SPI spi_initstructure.spi_datasize = spi_datasize_8b; Set the data size of the SPI: SPI send receive 8-bit frame structure Spi_initstructure.spi_cpol = Spi_cpol_high; The idle state of the serial Sync clock is high spi_initstructure.spi_cpha = Spi_cpha_2edge; The second hop edge (up or down) data of the serial synchronization clock is sampled spi_initstructure.spi_nss = Spi_nss_soft; NSS signals are managed by hardware (NSS pins) or software (using SSI bits): internal NSS signal with SSI bit control Spi_initstructure.spi_baudrateprescaler = spi_baudrateprescaler_64 ; Defines the value of the baud rate Prescaler: The baud rate prescaler value is Spi_initstructure.spi_firstbit = SPI_FIRSTBIT_MSB; Specifies whether the data transfer begins with the MSB bit or the LSB bit: The data transfer begins with the MSB bit spi_initstructure.spi_crcpolynomial = 7; Polynomial spi_init of CRC value calculation (SPI1, &spi_initstructure); Initializes the peripheral Spix register spi_cmd (SPI1, ENABLE) based on the parameters specified in the spi_initstruct; Enable SPI peripheral spi1_readwritebyte (0xff);//Start transmission}//spi1 SpeedDegree set function//spi speed =fapb2/divide factor//@ref spi_baudrate_prescaler:spi_baudrateprescaler_2~spi_baudrateprescaler_256// The fAPB2 clock is generally 84mhz:void spi1_setspeed (U8 spi_baudrateprescaler) {Assert_param (Is_spi_baudrate_prescaler (SPI_ Baudrateprescaler));//validity spi1->cr1&=0xffc7;//bit 3-5 cleared to set the baud rate spi1->cr1|=spi_baudrateprescaler; Set SPI1 speed Spi_cmd (spi1,enable); Enable SPI1}//spi1 read and write a byte//txdata: bytes to write//return value: bytes read U8 spi1_readwritebyte (U8 txdata) {U8 Result,retry=0;//result: return Back to SPI Read and write results;
Retry: Failed retry count while (Spi_i2s_getflagstatus (SPI1,SPI_I2S_FLAG_TXE) ==reset) {retry++;
if (retry>200) return 0;
} spi_i2s_senddata (SPI1, TxData);
while (Spi_i2s_getflagstatus (spi1,spi_i2s_flag_rxne) ==reset) {retry++;
if (retry>200) return 0;
} return Spi_i2s_receivedata (SPI1);
Spi_i2s_clearflag (SPI1,SPI_I2S_FLAG_RXNE);
}//Read SPI Register value//reg: Register to read U8 Bmi160_read_reg (U8 reg) {U8 reg_val; Bmi160_cs = 0; Enable SPI to transmit Delay_ms (1); Spi1_readwritebyte (reg|0x80); 1. Send register number//ored with "read request" bit reg_val=spi1_readwritebyte (0XFF);//Read register contents//Send a value of 0 to read the F
Irst byte Returned:delay_ms (1); Bmi160_cs = 1; Disable SPI transmission return (REG_VAL);
Return status Value}//SPI write register//reg: Specify register Address//value: Write value U8 bmi160_write_reg (U8 reg,u8 value) {U8 status; bmi160_cs=0; Enable SPI to transmit status =spi1_readwritebyte (reg&0x7f);//2. Send register number Spi1_readwritebyte (value); The value of the write register is Bmi160_cs=1; Disable SPI transmission return (status); Return status Value}