Environment: windows 10, STM32CubeIDE 1.8.0
In this tutorial we will use uart4 through PA0
and PA1
pins.
Project Initialization
First, Create a new stm32f407g project in CubeIDE, and name the project lis302dl_test.
Set up uart4 according to Using Uart on Stm32f407g.
Next, set PE3
as GPIO_Output and PE0
as GPIO_EXT0 according to the figure below.
Set PA5
, PA6
, PA7
as the following figure and enable SPI1.
Enable EXTI line0 interrupt and set its priority:
Press Ctrl+S to automatically generate the code.
Check WHO_AM_I_ADDR
LIS302DL has many registers for reading and writing. For specific numbers and functions, please refer to the official datasheet or refer to lis302dl.h. If you want to directly include lis302dl.h, please manually complete or delete the missing dependent libraries.
Here are the registers used in this tutorial, which can be defined as private macros under /* USER CODE BEGIN PM */:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* USER CODE BEGIN PM */
#define LIS302DL_WHO_AM_I_ADDR 0x0F
#define LIS302DL_CTRL_REG1_ADDR 0x20
#define LIS302DL_CTRL_REG2_ADDR 0x21
#define LIS302DL_CTRL_REG3_ADDR 0x22
#define LIS302DL_STATUS_REG_ADDR 0x27
#define LIS302DL_OUT_X_ADDR 0x29
#define LIS302DL_OUT_Y_ADDR 0x2B
#define LIS302DL_OUT_Z_ADDR 0x2D
#define LIS302DL_FF_WU_CFG1_REG_ADDR 0x30
#define LIS302DL_FF_WU_SRC1_REG_ADDR 0x31
#define LIS302DL_FF_WU_THS1_REG_ADDR 0x32
#define LIS302DL_FF_WU_DURATION1_REG_ADDR 0x33
/* USER CODE END PM */
Next, implement the functions for reading and writing SPI1 in /* USER CODE BEGIN 0 */:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* USER CODE BEGIN 0 */
void MEMS_Write(uint8_t address, uint8_t data){
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1,&address,1,10);
HAL_SPI_Transmit(&hspi1,&data,1,10);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);
}
void MEMS_Read(uint8_t address, uint8_t *data){
address |= 0x80;
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_3, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1,&address,1,10);
HAL_SPI_Receive(&hspi1,data,1,10);
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_3, GPIO_PIN_SET);
}
/* USER CODE END 0 */
Then rewrite the while loop of the main function of the project as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
uint8_t data;
MEMS_Read(LIS302DL_WHO_AM_I_ADDR, &data);
if(data == 0x3B)
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
If the three-axis accelerometer model is LIS302DL, the green LED on the board will blink continuously.
Test Printing X, Y, Z Values
Reference datasheet:
Use the following code to set CTRL_REG1
. The code means setting output rate to 400 Hz and enabling X, Y, Z:
1
2
3
/* USER CODE BEGIN 2 */
MEMS_Write(LIS302DL_CTRL_REG1_ADDR, 0x47);
/* USER CODE END 2 */
CTRL_REG2
needs no change.
CTRL_REG3
and subsequent registers are only needed when using external interrupt in this tutorial later.
Next, rewrite the while loop to continuously print out the acceleration of the X, Y, and Z axes every 0.1 seconds through uart4:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
uint8_t x, y, z;
MEMS_Read(LIS302DL_OUT_X_ADDR, &x);
MEMS_Read(LIS302DL_OUT_Y_ADDR, &y);
MEMS_Read(LIS302DL_OUT_Z_ADDR, &z);
char Monitor_data[100];
memset(Monitor_data,'\0',sizeof(Monitor_data));
sprintf(Monitor_data, "%3d %3d %3d\n\r", x, y, z);
HAL_UART_Transmit(&huart4, (uint8_t *)Monitor_data, strlen(Monitor_data), HAL_MAX_DELAY);
HAL_Delay(100);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
After executing, the uart4 will be like this:
Test Using External Interrupt
Also refer to the datasheet and set the following registers, the effects of the code are shown comments:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* USER CODE BEGIN 2 */
MEMS_Write(LIS302DL_CTRL_REG1_ADDR, 0x47);
MEMS_Write(LIS302DL_CTRL_REG2_ADDR, 0x00);
// use FF_WU_1 to trigger interrupt on INT1
MEMS_Write(LIS302DL_CTRL_REG3_ADDR, 0x01);
// enable interrupt on X high, Y high
MEMS_Write(LIS302DL_FF_WU_CFG1_REG_ADDR, 0x0A);
// free-fall/wake-up threshold (7 bit)
MEMS_Write(LIS302DL_FF_WU_THS1_REG_ADDR, 0x55);
// free-fall/wake-up duration (8 bit)
// Step 2.5 msec, from 0 to 637.5 msec if ODR=400Hz,
// else step 10 msec, from 0 to 2.55 sec when ODR=100Hz.
MEMS_Write(LIS302DL_FF_WU_DURATION1_REG_ADDR, 0x04);
/* USER CODE END 2 */
Implement HAL_GPIO_EXTI_Callback
in main.c:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* USER CODE BEGIN 0 */
// ...
int is_handling = 0, count = 0;
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (is_handling) {
return;
}
is_handling = 1;
char Monitor_data[100];
memset(Monitor_data,'\0', sizeof(Monitor_data));
sprintf(Monitor_data, "interrupt! %d\n\r", count++);
HAL_UART_Transmit(&huart4, (uint8_t *)Monitor_data, strlen(Monitor_data), HAL_MAX_DELAY);
is_handling = 0;
}
/* USER CODE END 0 */
After execution, uart4 will print “interrupt!” and the current number of interrupts every time it is expected to shake left and right:
Comments powered by Disqus.