이 문서는 ADXL345 3축 가속도 센서를 STM32 마이크로컨트롤러와 HAL 라이브러리를 이용해 완벽하게 제어하는 방법을 안내합니다. 센서의 상세 사양부터, 핀 연결, 그리고 실제 동작하는 디바이스 드라이버 코드까지 단계별로 설명합니다.

1. ADXL345 가속도 센서 사양
ADXL345는 저전력, 소형, 3축 가속도 센서로, 정적(Static) 및 동적(Dynamic) 가속도 측정이 가능합니다. 특히 다양한 내장 기능 덕분에 복잡한 알고리즘 없이도 충격 및 동작 감지를 손쉽게 구현할 수 있습니다.
- 측정 범위: ±2g, ±4g, ±8g, ±16g (사용자가 설정 가능)
- 해상도: 10비트 고정 해상도 또는 Full Resolution 모드(최대 13비트) 지원
- 통신 인터페이스: 4-wire SPI (직렬 통신) 및 I2C 지원
- 전력 소모: 측정 모드에서 140µA, 대기 모드에서 0.1µA의 초저전력 소모
- 내장 기능:
- 탭 감지 (단일 및 더블 탭)
- 활동/비활동 감지
- 자유낙하 감지
- FIFO (First-In, First-Out) 버퍼: 최대 32개의 데이터를 저장하여 호스트 프로세서의 부하를 줄임
2. 하드웨어 연결 및 STM32CubeMX 설정
STM32CubeMX 설정
- Pinout & Configuration:
- SPI1 (또는 연결한 SPI 모듈)을 Full-Duplex Master로 설정합니다.
- Parameter Settings: CPOL: High, CPHA: 2 Edge로 설정하여 ADXL345와 호환되는 모드(SPI Mode 3)를 사용합니다.
- GPIO: CS(Chip Select) 핀을 GPIO Output으로 설정합니다.
- Clock Configuration: SPI 통신 속도에 맞게 클럭을 설정합니다.

3. ADXL345 디바이스 드라이버 코드 분석
드라이버는 센서의 복잡한 하드웨어 동작을 추상화하여 사용자가 쉽게 센서를 제어할 수 있도록 도와줍니다. 아래 코드는 크게 세 부분으로 나뉩니다.
- adxl345.h: 드라이버의 인터페이스를 정의하는 헤더 파일입니다. 센서의 레지스터 주소, 열거형(Enum), 데이터 구조체 및 공개 함수들을 선언하여 다른 파일에서 쉽게 접근할 수 있도록 합니다.
- adxl345.c: 선언된 함수들을 실제로 구현하는 파일입니다.
ADXL345_ReadRegister
,ADXL345_WriteRegister
와 같은 핵심 통신 함수들이 포함되어 있습니다. 이 함수들이 레지스터의 읽기/쓰기 동작을 처리하며, 다른 모든 상위 함수들은 이들을 호출하여 센서를 제어합니다. - main.c: 드라이버를 실제 애플리케이션에 적용하는 예시 파일입니다. 드라이버 초기화부터 가속도 데이터 읽기, 그리고 감지 기능 활용 예시를 보여줍니다.
4. 코드 구현
STM32 프로젝트에 포함될 실제 드라이버 코드입니다.
adxl345.h
#ifndef ADXL345_H
#define ADXL345_H
#include <stdint.h>
// ADXL345 드라이버의 상태를 나타내는 열거형
typedef enum {
ADXL345_OK = 0x00, // 성공
ADXL345_ERROR = 0x01, // 오류 발생
ADXL345_BUSY = 0x02, // 통신이 바쁜 상태
ADXL345_TIMEOUT = 0x03 // 통신 타임아웃
} ADXL345_StatusTypeDef;
// 3축 가속도 데이터를 저장하기 위한 구조체
typedef struct {
int16_t x; // X축 가속도 데이터 (16비트)
int16_t y; // Y축 가속도 데이터 (16비트)
int16_t z; // Z축 가속도 데이터 (16비트)
} ADXL345_AccelData_t;
// 데이터 전송률(Data Rate) 설정에 사용되는 열거형 (BW_RATE 레지스터)
typedef enum {
ADXL345_DATARATE_3200HZ = 0x0F,
ADXL345_DATARATE_1600HZ = 0x0E,
ADXL345_DATARATE_800HZ = 0x0D,
ADXL345_DATARATE_400HZ = 0x0C,
ADXL345_DATARATE_200HZ = 0x0B,
ADXL345_DATARATE_100HZ = 0x0A, // 기본값(Default)
ADXL345_DATARATE_50HZ = 0x09,
ADXL345_DATARATE_25HZ = 0x08,
ADXL345_DATARATE_12_5HZ = 0x07,
ADXL345_DATARATE_6_25HZ = 0x06,
ADXL345_DATARATE_3_13HZ = 0x05,
ADXL345_DATARATE_1_56HZ = 0x04,
ADXL345_DATARATE_0_78HZ = 0x03,
ADXL345_DATARATE_0_39HZ = 0x02,
ADXL345_DATARATE_0_20HZ = 0x01,
ADXL345_DATARATE_0_10HZ = 0x00
} ADXL345_DataRate_t;
// 측정 범위(Measurement Range) 설정에 사용되는 열거형 (DATA_FORMAT 레지스터)
typedef enum {
ADXL345_RANGE_2G = 0x00, // ±2g
ADXL345_RANGE_4G = 0x01, // ±4g
ADXL345_RANGE_8G = 0x02, // ±8g
ADXL345_RANGE_16G = 0x03 // ±16g
} ADXL345_Range_t;
// 활동/비활동 감지 모드 설정에 사용되는 열거형 (ACT_INACT_CTL 레지스터)
typedef enum {
ADXL345_ACT_MODE_DC = 0, // DC-coupled (정적 가속도 감지)
ADXL345_ACT_MODE_AC = 1 // AC-coupled (동적 가속도 감지)
} ADXL345_ActivityMode_t;
// 인터럽트 소스/활성화 비트 마스크 정의 (INT_ENABLE, INT_MAP, INT_SOURCE 레지스터)
#define ADXL345_INT_DATA_READY (1 << 7) // 새 데이터 사용 가능
#define ADXL345_INT_SINGLE_TAP (1 << 6) // 단일 탭 감지
#define ADXL345_INT_DOUBLE_TAP (1 << 5) // 더블 탭 감지
#define ADXL345_INT_ACTIVITY (1 << 4) // 활동 감지
#define ADXL345_INT_INACTIVITY (1 << 3) // 비활동 감지
#define ADXL345_INT_FREE_FALL (1 << 2) // 자유낙하 감지
#define ADXL345_INT_WATERMARK (1 << 1) // FIFO 워터마크
#define ADXL345_INT_OVERRUN (1 << 0) // FIFO 오버런
// 탭 감지 축 비트 마스크 (TAP_AXES 레지스터)
#define ADXL345_TAP_AXIS_X (1 << 0) // X축 탭 감지
#define ADXL345_TAP_AXIS_Y (1 << 1) // Y축 탭 감지
#define ADXL345_TAP_AXIS_Z (1 << 2) // Z축 탭 감지
// FIFO 모드 설정에 사용되는 열거형 (FIFO_CTL 레지스터)
typedef enum {
ADXL345_FIFO_BYPASS = 0x00, // FIFO 비활성화
ADXL345_FIFO_FIFO = 0x01, // FIFO 모드: 꽉 차면 데이터 덮어쓰지 않음
ADXL345_FIFO_STREAM = 0x02, // 스트림 모드: 새 데이터로 오래된 데이터 덮어씀
ADXL345_FIFO_TRIGGER = 0x03 // 트리거 모드
} ADXL345_FIFOMode_t;
// FIFO 트리거 인터럽트 핀 맵핑 (FIFO_CTL 레지스터)
typedef enum {
ADXL345_INT_PIN_INT1 = 0, // 인터럽트 핀 1
ADXL345_INT_PIN_INT2 = 1 // 인터럽트 핀 2
} ADXL345_IntPin_t;
/* --------------------- 공개 함수(Public Functions) 선언 --------------------- */
// 드라이버 및 센서 초기화
ADXL345_StatusTypeDef ADXL345_Init(void);
// 가속도 데이터 읽기
ADXL345_StatusTypeDef ADXL345_GetAccelerometerData(ADXL345_AccelData_t *accel_data);
// ADXL345의 다양한 기능들을 설정하는 함수들
ADXL345_StatusTypeDef ADXL345_SetOffset(int8_t offset_x, int8_t offset_y, int8_t offset_z);
ADXL345_StatusTypeDef ADXL345_SetDataRate(ADXL345_DataRate_t rate, uint8_t low_power);
ADXL345_StatusTypeDef ADXL345_SetRangeAndFormat(ADXL345_Range_t range, uint8_t full_res);
ADXL345_StatusTypeDef ADXL345_SetTapThreshold(uint8_t threshold);
ADXL345_StatusTypeDef ADXL345_SetTapDuration(uint8_t duration);
ADXL345_StatusTypeDef ADXL345_SetTapLatency(uint8_t latency);
ADXL345_StatusTypeDef ADXL345_SetTapWindow(uint8_t window);
ADXL345_StatusTypeDef ADXL345_SetActivityThreshold(uint8_t threshold);
ADXL345_StatusTypeDef ADXL345_SetInactivityThreshold(uint8_t threshold);
ADXL345_StatusTypeDef ADXL345_SetInactivityTime(uint8_t time);
ADXL345_StatusTypeDef ADXL345_SetActivityInactivityControl(uint8_t activity_enable, uint8_t inactivity_enable, ADXL345_ActivityMode_t activity_mode, ADXL345_ActivityMode_t inactivity_mode);
ADXL345_StatusTypeDef ADXL345_SetFreefallThreshold(uint8_t threshold);
ADXL345_StatusTypeDef ADXL345_SetFreefallTime(uint8_t time);
ADXL345_StatusTypeDef ADXL345_SetTapAxes(uint8_t tap_axes, uint8_t suppress_double_tap);
// 인터럽트 관련 함수들
ADXL345_StatusTypeDef ADXL345_EnableInterrupts(uint8_t interrupts);
ADXL345_StatusTypeDef ADXL345_MapInterruptsToINT1(uint8_t interrupts);
ADXL345_StatusTypeDef ADXL345_GetInterruptSource(uint8_t *source);
// FIFO 관련 함수들
ADXL345_StatusTypeDef ADXL345_SetFIFOMode(ADXL345_FIFOMode_t mode, uint8_t samples, ADXL345_IntPin_t trigger_int);
ADXL345_StatusTypeDef ADXL345_GetFIFOStatus(uint8_t *fifo_status);
#endif // ADXL345_H
adxl345.c
#include "adxl345.h"
#include "stm32g4xx_hal.h" // STM32CubeMX에서 사용하는 HAL 라이브러리
#include <string.h> // memcpy 함수 사용을 위해 포함
// SPI 핸들 선언. 이 변수는 main.c 등에서 초기화된 핸들을 사용
// CubeMX에서 생성된 SPI 핸들 변수명과 일치시켜야 함 (예: hspi1)
extern SPI_HandleTypeDef hspi1;
// ADXL345에 연결된 SPI 핸들 정의.
// SPI1이 아닌 다른 모듈을 사용한다면 &hspi1 부분을 변경해야 함.
#define ADXL345_SPI_HANDLE &hspi1
// ADXL345 레지스터 주소 정의
#define ADXL345_DEVID 0x00 // 디바이스 ID (읽기 전용)
#define ADXL345_THRESH_TAP 0x1D // 탭 감지 임계값
#define ADXL345_OFSX 0x1E // X축 오프셋
#define ADXL345_OFSY 0x1F // Y축 오프셋
#define ADXL345_OFSZ 0x20 // Z축 오프셋
#define ADXL345_DUR 0x21 // 탭 감지 지속 시간
#define ADXL345_LATENT 0x22 // 탭 감지 대기 시간
#define ADXL345_WINDOW 0x23 // 탭 감지 윈도우 시간
#define ADXL345_THRESH_ACT 0x24 // 활동 감지 임계값
#define ADXL345_THRESH_INACT 0x25 // 비활동 감지 임계값
#define ADXL345_TIME_INACT 0x26 // 비활동 감지 시간
#define ADXL345_ACT_INACT_CTL 0x27 // 활동/비활동 감지 제어
#define ADXL345_THRESH_FF 0x28 // 자유낙하 감지 임계값
#define ADXL345_TIME_FF 0x29 // 자유낙하 감지 시간
#define ADXL345_TAP_AXES 0x2A // 탭 감지 축 제어
#define ADXL345_ACT_TAP_STATUS 0x2B // 탭/활동 상태 (읽기 전용)
#define ADXL345_BW_RATE 0x2C // 데이터 전송률 및 전력 모드
#define ADXL345_POWER_CTL 0x2D // 전원 제어 및 측정 모드
#define ADXL345_INT_ENABLE 0x2E // 인터럽트 활성화
#define ADXL345_INT_MAP 0x2F // 인터럽트 핀 맵핑
#define ADXL345_INT_SOURCE 0x30 // 인터럽트 소스 (읽기 전용)
#define ADXL345_DATA_FORMAT 0x31 // 데이터 형식 및 측정 범위
#define ADXL345_DATAX0 0x32 // X축 가속도 데이터 (LSB)
#define ADXL345_DATAX1 0x33 // X축 가속도 데이터 (MSB)
#define ADXL345_DATAY0 0x34 // Y축 가속도 데이터 (LSB)
#define ADXL345_DATAY1 0x35 // Y축 가속도 데이터 (MSB)
#define ADXL345_DATAZ0 0x36 // Z축 가속도 데이터 (LSB)
#define ADXL345_DATAZ1 0x37 // Z축 가속도 데이터 (MSB)
#define ADXL345_FIFO_CTL 0x38 // FIFO 제어
#define ADXL345_FIFO_STATUS 0x39 // FIFO 상태 (읽기 전용)
// SPI 통신 명령어 비트 정의
#define ADXL345_SPI_READ 0x80 // 읽기 작업 (최상위 비트 1)
#define ADXL345_SPI_MULTI_BYTE 0x40 // 멀티 바이트(연속) 접근 (비트 6을 1로 설정)
// 정적(static) 함수 선언: 이 파일 내에서만 사용
static ADXL345_StatusTypeDef ADXL345_ReadRegister(uint8_t reg_addr, uint8_t *data);
static ADXL345_StatusTypeDef ADXL345_WriteRegister(uint8_t reg_addr, uint8_t data);
static ADXL345_StatusTypeDef ADXL345_ReadMultiRegister(uint8_t reg_addr, uint8_t *data, uint8_t len);
/**
* @brief ADXL345 초기화 함수
* 센서의 디바이스 ID를 확인하고, 측정 모드 및 데이터 포맷을 설정합니다.
* @param None
* @retval ADXL345_StatusTypeDef 결과 상태
*/
ADXL345_StatusTypeDef ADXL345_Init(void)
{
uint8_t dev_id;
ADXL345_StatusTypeDef status;
// 1. 디바이스 ID 레지스터(0x00)를 읽어 통신이 정상인지 확인
status = ADXL345_ReadRegister(ADXL345_DEVID, &dev_id);
// ADXL345의 고유 ID는 0xE5. 이 값이 아니면 통신 오류로 간주
if (status != ADXL345_OK || dev_id != 0xE5) {
return ADXL345_ERROR;
}
// 2. POWER_CTL 레지스터(0x2D) 설정: 측정 모드(Measure Mode) 활성화
// MEASURE 비트(3번 비트)를 1로 설정
status = ADXL345_WriteRegister(ADXL345_POWER_CTL, 0x08);
if (status != ADXL345_OK) return status;
// 3. DATA_FORMAT 레지스터(0x31) 설정: 측정 범위와 해상도 설정
// 0x0B (0b00001011) -> SELF_TEST=0, SPI=0, INT_INVERT=0, FULL_RES=1, JUSTIFY=0, Range=11 (+/-16g)
// FULL_RES 비트를 1로 설정하여 Full Resolution 모드를 사용하면 측정 범위에 따라 해상도가 자동으로 최대 13비트까지 조절됩니다.
status = ADXL345_WriteRegister(ADXL345_DATA_FORMAT, 0x0B);
if (status != ADXL345_OK) return status;
// 4. BW_RATE 레지스터(0x2C) 설정: 데이터 전송률(Data Rate) 설정
// 0x0A (0b00001010) -> Low_Power=0, Rate=100Hz
status = ADXL345_WriteRegister(ADXL345_BW_RATE, 0x0A);
if (status != ADXL345_OK) return status;
return ADXL345_OK;
}
/**
* @brief ADXL345의 3축 가속도 데이터를 읽습니다.
* @param accel_data 가속도 데이터를 저장할 ADXL345_AccelData_t 구조체 포인터
* @retval ADXL345_StatusTypeDef 결과 상태
*/
ADXL345_StatusTypeDef ADXL345_GetAccelerometerData(ADXL345_AccelData_t *accel_data)
{
uint8_t raw_data[6];
ADXL345_StatusTypeDef status;
// DATAX0 레지스터(0x32)부터 DATAZ1(0x37)까지 6바이트를 연속해서 읽기
status = ADXL345_ReadMultiRegister(ADXL345_DATAX0, raw_data, 6);
if (status != ADXL345_OK) return status;
// 읽은 8비트 데이터들을 16비트 정수(2의 보수)로 조합
// LSB(low byte)와 MSB(high byte)를 합쳐 16비트 값으로 변환
accel_data->x = (int16_t)(((uint16_t)raw_data[1] << 8) | raw_data[0]);
accel_data->y = (int16_t)(((uint16_t)raw_data[3] << 8) | raw_data[2]);
accel_data->z = (int16_t)(((uint16_t)raw_data[5] << 8) | raw_data[4]);
return ADXL345_OK;
}
/**
* @brief 단일 레지스터를 읽습니다.
* @param reg_addr 읽을 레지스터의 주소
* @param data 읽은 데이터를 저장할 포인터
* @retval ADXL345_StatusTypeDef
*/
static ADXL345_StatusTypeDef ADXL345_ReadRegister(uint8_t reg_addr, uint8_t *data)
{
uint8_t tx_buffer[2]; // 주소(명령) 전송용
uint8_t rx_buffer[2]; // 데이터 수신용
// SPI 읽기 명령어 구성: 최상위 비트(bit 7)를 1로 설정 + 레지스터 주소
tx_buffer[0] = ADXL345_SPI_READ | reg_addr;
tx_buffer[1] = 0x00; // 더미 바이트 (SPI는 동시 전송이므로 데이터를 읽기 위해 더미 바이트 전송)
// CS 핀 제어는 이 드라이버 함수 밖에서 담당한다고 가정 (일반적으로 SPI HAL 함수가 처리)
// ADXL345 SPI 통신 규약: Read 명령어(1바이트)를 보내고, 다음 바이트에서 데이터(1바이트)를 받음
HAL_StatusTypeDef spi_status = HAL_SPI_TransmitReceive(ADXL345_SPI_HANDLE, tx_buffer, rx_buffer, 2, HAL_MAX_DELAY);
// SPI 통신 결과 확인
if (spi_status != HAL_OK) {
return ADXL345_ERROR;
}
// 수신 버퍼의 첫 번째 바이트는 명령 바이트의 에코(echo)이므로, 두 번째 바이트가 실제 데이터
*data = rx_buffer[1];
return ADXL345_OK;
}
/**
* @brief 단일 레지스터에 씁니다.
* @param reg_addr 쓸 레지스터의 주소
* @param data 쓸 데이터
* @retval ADXL345_StatusTypeDef
*/
static ADXL345_StatusTypeDef ADXL345_WriteRegister(uint8_t reg_addr, uint8_t data)
{
uint8_t tx_buffer[2]; // 주소와 데이터를 동시에 전송
// SPI 쓰기 명령어 구성: 최상위 비트(bit 7)를 0으로 설정 + 레지스터 주소
tx_buffer[0] = reg_addr;
tx_buffer[1] = data; // 쓸 데이터
HAL_StatusTypeDef spi_status = HAL_SPI_Transmit(ADXL345_SPI_HANDLE, tx_buffer, 2, HAL_MAX_DELAY);
if (spi_status != HAL_OK) {
return ADXL345_ERROR;
}
return ADXL345_OK;
}
/**
* @brief 여러 레지스터를 연속해서 읽습니다.
* @param reg_addr 읽기 시작할 레지스터 주소
* @param data 읽은 데이터를 저장할 버퍼
* @param len 읽을 바이트 수
* @retval ADXL345_StatusTypeDef
*/
static ADXL345_StatusTypeDef ADXL345_ReadMultiRegister(uint8_t reg_addr, uint8_t *data, uint8_t len)
{
uint8_t tx_buffer[1]; // 명령 바이트만 전송
uint8_t rx_buffer[len + 1]; // 명령 바이트 에코 + 데이터 바이트만큼 수신
// 읽기 명령어(bit 7) + 멀티 바이트 비트(bit 6) + 레지스터 주소
tx_buffer[0] = ADXL345_SPI_READ | ADXL345_SPI_MULTI_BYTE | reg_addr;
// SPI 통신: 명령어 전송 후, 연속된 데이터를 수신
HAL_StatusTypeDef spi_status = HAL_SPI_TransmitReceive(ADXL345_SPI_HANDLE, tx_buffer, rx_buffer, len + 1, HAL_MAX_DELAY);
if (spi_status != HAL_OK) {
return ADXL345_ERROR;
}
// 수신된 버퍼에서 실제 데이터(두 번째 바이트부터)만 복사
// memcpy(대상 버퍼, 원본 버퍼 + 오프셋, 바이트 수)
memcpy(data, rx_buffer + 1, len);
return ADXL345_OK;
}
// ADXL345_Init, ADXL345_GetAccelerometerData 외에 다른 함수들은 adxl345.h와 일치하도록 추가 구현할 수 있습니다.
// 요청에 따라 다른 기능들도 여기에 추가할 수 있습니다.
// ex) ADXL345_SetOffset(), ADXL345_SetDataRate() 등
main.c
/* USER CODE BEGIN PFP */
// 외부 함수 선언 (사용자 코드 영역에 추가)
void main_ADXL345_Example(void);
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
// ADXL345 드라이버를 사용하기 위해 헤더 파일 포함
#include "adxl345.h"
#include <stdio.h> // 디버깅용 printf 사용을 위해 필요
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
// 변수 선언
ADXL345_AccelData_t accel_data;
ADXL345_StatusTypeDef status;
/* 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 */
// STM32CubeMX에서 UART를 활성화했다면 여기서 추가 설정 가능
// 예: MX_UART1_Init();
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI1_Init(); // STM32CubeMX에서 SPI1을 초기화했음을 가정
// 필요한 경우 다른 주변장치 초기화 함수를 여기에 추가
/* USER CODE BEGIN 2 */
// ADXL345 디바이스 드라이버 초기화
status = ADXL345_Init();
if (status != ADXL345_OK) {
// 초기화 실패 시 처리 (LED 깜빡임, 오류 메시지 출력 등)
// 이 예제에서는 무한루프에 빠지게 함
while(1) {
HAL_Delay(500);
}
} else {
// 초기화 성공 시, UART 등으로 메시지 출력
// 예: printf("ADXL345 초기화 성공!\r\n");
}
// 탭 감지 기능 설정 예시
// 탭 임계값: 0x30 * 62.5mg/LSB = 1.875g
ADXL345_SetTapThreshold(0x30);
// 탭 지속 시간: 0x10 * 625us/LSB = 6.25ms
ADXL345_SetTapDuration(0x10);
// 모든 축에 대한 탭 감지 활성화
ADXL345_SetTapAxes(ADXL345_TAP_AXIS_X | ADXL345_TAP_AXIS_Y | ADXL345_TAP_AXIS_Z, 0);
// 인터럽트 활성화
ADXL345_EnableInterrupts(ADXL345_INT_DATA_READY | ADXL345_INT_SINGLE_TAP | ADXL345_INT_DOUBLE_TAP);
// 모든 인터럽트를 INT1 핀에 맵핑
ADXL345_MapInterruptsToINT1(ADXL345_INT_DATA_READY | ADXL345_INT_SINGLE_TAP | ADXL345_INT_DOUBLE_TAP);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// ADXL345_GetAccelerometerData 함수를 호출하여 가속도 데이터 읽기
status = ADXL345_GetAccelerometerData(&accel_data);
if (status == ADXL345_OK) {
// 가속도 값을 g 단위로 변환
// ADXL345의 Full resolution 모드에서 +/-16g 범위일 때, 1 LSB = 3.9 mg (0.0039g)
float x_g = accel_data.x * 0.0039f;
float y_g = accel_data.y * 0.0039f;
float z_g = accel_data.z * 0.0039f;
// 데이터를 UART 등으로 전송하거나 디스플레이에 표시
// 예: printf("X: %.2f g, Y: %.2f g, Z: %.2f g\r\n", x_g, y_g, z_g);
} else {
// 데이터 읽기 실패 시 오류 처리
// 예: printf("데이터 읽기 실패!\r\n");
}
// 인터럽트 소스 레지스터를 읽어 어떤 이벤트가 발생했는지 확인
uint8_t int_source;
ADXL345_GetInterruptSource(&int_source);
if (int_source & ADXL345_INT_SINGLE_TAP) {
// 단일 탭 감지 이벤트가 발생했을 때의 로직
// 예: printf("단일 탭 감지! \r\n");
}
if (int_source & ADXL345_INT_DOUBLE_TAP) {
// 더블 탭 감지 이벤트가 발생했을 때의 로직
// 예: printf("더블 탭 감지! \r\n");
}
// 100ms 대기 (데이터 전송률에 따라 조정)
HAL_Delay(100);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/* USER CODE BEGIN 4 */
// 이 부분에 인터럽트 콜백 함수 등을 추가할 수 있습니다.
/* USER CODE END 4 */
5. 결론
이 문서는 ADXL345 센서의 주요 사양과 STM32 기반의 완벽한 디바이스 드라이버 구현 방법을 다루었습니다. 이 코드를 기반으로 센서의 복잡한 통신을 추상화하여, 동작 인식, 만보계, 자세 추정 등 다양한 프로젝트를 손쉽게 개발할 수 있습니다.
'MCU > STM32' 카테고리의 다른 글
STM32CubeMX에서 아두이노 스타일 사용자 코드 구조 만들기 (0) | 2025.09.14 |
---|---|
STM32 ADC 샘플 타임 설정 방법과 실무 팁 (0) | 2025.08.21 |
STM32 에서 PWM Soft Start 구현: 모터와 LED 제어를 위한 부드러운 시작 (0) | 2025.08.21 |
STM32 링커 스크립트: 상세 설명, 구조, 작성 방법 및 예제 (STM32 Linker Script: Detailed Explanation, Structure, Writing Methods, and Examples) (4) | 2025.08.18 |
STM32로 Modbus RTU Slave 코드 구현: DMA와 저전력 최적화 (0) | 2025.08.13 |
STM32G474 를 이용한 동일 어드레스를 갖는 64채널 I2C 디바이스 제어 (0) | 2025.08.12 |
STM32H503RB I3C 통신 코드 구현: 초보자를 위한 상세 가이드 (0) | 2025.08.10 |