Introdução
A identificação de queda livre é uma aplicação frequente em sistemas com acelerômetros, sendo muito utilizada em dispositivos como smartphones, wearables e sistemas de segurança. Essa técnica permite que dispositivos reconheçam quando estão em uma queda, o que pode disparar uma série de ações automáticas, como a ativação de alarmes de emergência ou sistemas de proteção.
Neste terceiro artigo com o acelerômetro LIS3DH, vamos implementar a detecção de queda livre que acionará um LED e exibirá a informação pela Serial.
Circuito:
Configuração CubeMx
- Abra STM32Cube, crie um novo projeto e selecione o microcontrolador “STM32C011F6P6”.
- Vá para a página de configurações de relógio e em HCLK digite 48 MHz para a frequência de saída desejada do sistema. Depois volte para a página de configuração dos pinos, selecione “Trace and Debug” e habilite “Serial Wire.
- Para configurar a UART, selecione o pino PA10 como “USART1_RX” e PA9 como “USART1_TX”. Em “Connectivity” selecione a opção “USART1” e em Mode escolha o “Asynchronous”. As demais configurações deixe padrão.
- Para a configuração do SPI, vá em “Connectivity’ > “SPI”, habilite o modo “FullDuplex Master” e mude o “Clock Parameter” > “Prescaler (Baud Rate)” para 32. Os demais parâmetros de configuração não será necessário modificar.
- O pino de CS é necessário configurar manualmente, então, selecione o PA4 como “GPIO_Output”.
- Configure também o pino PB6 como “GPIO_Output”, nele está conectado o LED.
- Por fim, gere o código em “Project” > “Generate Code”.
Implementação Código
- Crie em “Inc” “lis3dh.h” e em “Src” crie “lis3dh.c”.

- Em lis3dh.h, adicione algumas definições (#define) dos registradores do acelerômetro LIS3DH, assim como os protótipos das funções que serão implementadas em lis3dh.c:
#include <stdint.h>
#define LIS3DH_CTRL_REG1 0x20
#define LIS3DH_CTRL_REG3 0x22
#define LIS3DH_CTRL_REG4 0x23
#define LIS3DH_INT1_CFG 0x30
#define LIS3DH_INT1_SRC 0x31
#define LIS3DH_INT1_THS 0x32
#define LIS3DH_INT1_DURATION 0x33
/* Public APIs */
uint8_t LIS3DH_ReadReg(uint8_t address);
void LIS3DH_WriteReg(uint8_t address, uint8_t data);
void LIS3DH_FreeFallConfig();
void freeFallStatus();- Em li3dh.c, adicione a inclusão das bibliotecas e seguintes variáveis:
#include "lis3dh.h"
#include "stdio.h"
#include "string.h"
extern SPI_HandleTypeDef hspi1;
extern UART_HandleTypeDef huart1;
uint8_t msg[] = "Queda livre detectada! \r\n";- Depois, adicione as funções de leitura e escrita por SPI:
// Leitura por SPI
uint8_t LIS3DH_ReadReg(uint8_t address) {
uint8_t txData[2];
uint8_t rxData[2];
txData[0] = address | 0x80 ; // Set read bit (MSB = 1)
txData[1] = 0x00; // Dummy byte
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // CS low
// delay to ensure CS is correctly registered
HAL_Delay(1);
if (HAL_SPI_TransmitReceive(&hspi1, txData, rxData, 2, HAL_MAX_DELAY) != HAL_OK) {
char error_msg[] = "SPI Transmit/Receive Error\r\n";
HAL_UART_Transmit(&huart1, (uint8_t *)error_msg, strlen(error_msg), 1000);
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // CS high
return rxData[1]; // The second byte received is the actual data
}
// Escrita por SPI
void LIS3DH_WriteReg(uint8_t address, uint8_t data) {
uint8_t txData[2];
txData[0] = address;
txData[1] = data;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // CS low
// delay to ensure CS is correctly registered
HAL_Delay(1);
if (HAL_SPI_Transmit(&hspi1, txData, 2, HAL_MAX_DELAY) != HAL_OK) {
char error_msg[] = "SPI Write Error\r\n";
HAL_UART_Transmit(&huart1, (uint8_t *)error_msg, strlen(error_msg), 1000);
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // CS high
}
- Em seguida, crie as funções de configuração dos registradores no LIS3DH para trabalhar com identificação de queda livre:
// Função para configurar o LIS3DH para detecção de queda livre
void LIS3DH_FreeFallConfig(void) {
LIS3DH_WriteReg(LIS3DH_CTRL_REG1, 0x97); // CTRL_REG1: Ativar XYZ, 50 Hz ODR
LIS3DH_WriteReg(LIS3DH_CTRL_REG4, 0x88); // CTRL_REG4: High resolution, BDU enabled, ±2g
LIS3DH_WriteReg(LIS3DH_CTRL_REG3, 0x40); // CTRL_REG3: AOI1 interrupt on INT1 pin
LIS3DH_WriteReg(LIS3DH_INT1_CFG, 0x95); // INT1_CFG: 6 direction movement recognition
LIS3DH_WriteReg(LIS3DH_INT1_THS, 0x16); // INT1_THS: Threshold = 350 mg
LIS3DH_WriteReg(LIS3DH_INT1_DURATION, 0x03); // INT1_DURATION: Minimum event duration = 1/OD
}
- CTRL_REG1: Ative o sensor e defina a taxa de dados (ODR). Por exemplo, para configurar uma taxa de 50Hz com todos os eixos ativos, envie: 0x97 (10010111).
- CTRL_REG3: Configure as interrupções. Para roteá-las para o pino INT1, envie: 0x40 (01000000).
- CTRL_REG4 (0x23): Configure a faixa de medição, se necessário. Para uma faixa de ±2g, por exemplo, envie: 0x88 (10001000).
- INT1_CFG (0x30): Configure o tipo de evento para gerar a interrupção. Para detecção de queda livre, você deve monitorar quando todas as acelerações nos eixos caem abaixo de um determinado limiar. Configure: 0x95 (10010101) para habilitar a interrupção em todos os eixos com “6-direction movement recognition”.
- INT1_THS: Defina o limiar de aceleração para detectar queda livre. Valores baixos, como 0x10 (0010000).
- INT1_DURATION: Defina a duração mínima para considerar como queda livre. Um valor baixo, como 0x03 é suficiente para detectar quedas rápidas.
- Ainda no arquivo li3dh.c, crie a função para identificar queda livre:
// Função para verificar o status da interrupção de queda livre
void freeFallStatus() {
uint8_t int1Src;
int1Src = LIS3DH_ReadReg(LIS3DH_INT1_SRC);
// Verifica se o bit de queda livre foi ativado
if (int1Src & 0x40) {
// Verifique se todos os bits XLow, YLow e ZLow estão setados
if ((int1Src & 0x01) && (int1Src & 0x04) && (int1Src & 0x10)) {
// Queda livre detectada: Todos os eixos estão abaixo do limiar configurado
HAL_UART_Transmit(&huart1, msg, (sizeof(msg)-1), 1000); // Transmite mensagem serial pela UART
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_6); //muda estado led
}
}
}
Essa função verifica se houve uma queda livre lendo o registrador de interrupção do acelerômetro. Primeiro, checa se o bit que indica uma interrupção de queda livre está ativado. Se estiver, a função então verifica se os eixos X, Y e Z estão todos abaixo do limite configurado. Se sim, a função aciona envia uma mensagem pela UART e alterna o estado de um LED.
- Veja na imagem abaixo o código do arquivo lis3dh.c
- Depois da finalização do código em lis3dh.c, acesse main.c. Nele incluímos a biblioteca “lis3dh.h” adicionando ao ínicio do código:
#include "lis3dh.h"- Depois modificamos o int main com:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
HAL_Delay(500);
LIS3DH_FreeFallConfig();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
freeFallStatus();
}
/* USER CODE END 3 */
}
Nessa etapa, é chamado a configuração do acelerômetro com LIS3DH_FreeFallConfig e depois é lido continuamente o estado com freeFallStatus.
Gravação
Ao finalizar o código, partiremos para gravação. Nessa etapa você pode utilizar o ST-Link seguindo as conexões da imagem abaixo e clicando em “run” no STM32CubeIde.
Ou você pode optar por utilizar um cabo usb e gravar conforme explicado no seguinte tutorial: gravar-franzininho-c0-via-stm32cubeprogrammer
Funcionamento
Para testar o funcionamento simule um queda, como jogar a placa.

Desafio extra
No exemplo deste artigo estamos verificando constantemente o status da queda livre dentro no loop infinito. No entanto, essa não é a melhor abordagem, como desafio, configure um pino na Franzininho C0 para interrupção externa e o conecte no “INT1” do acelerômetro, então chame a verificação do status da queda livre sempre que houver interrupção no pino. Em caso de dúvidas temos um artigo explicando como configurar interrupção externa, acesse: https://embarcados.com.br/aprendendo-a-trabalhar-com-interrupcoes-externas-e-usart-na-franzininho-c0/
Conclusão
Neste artigo, demonstramos como configurar o acelerômetro LIS3DH para detectar quedas livres usando a Franzininho C0. Configuramos os registradores necessários e a implementamos o código para verificar o status de queda, acionando um LED e enviando uma mensagem pela Serial. Essa solução básica permite a identificação de quedas de forma simples e pode ser expandida com o uso de interrupções para otimizar o desempenho do sistema.





