ADXL345三轴加速度传感器
详细的代码和cubemx的配置附后,请需要的同学们直接拉到后面。
特性:
- 可选分辨率:10位固定分辨率,13位全分辨率。
- 数字输出位16位二进制补码格式。
特殊检测功能
- 活动和非活动检测功能通过比较任意轴上的加速度与用户设置的阈值来检测有无运动发生。
- 敲击检测功能可以检测任意方向的单振和双振动作。
- 自由落体检测功能可以检测器件是否正在掉落。
这些功能可以独立映射到两个中断输出引脚中的一个
引脚配置和功能描述:
引脚功能描述:
引脚编号 | 引脚名称 | 描述 |
---|---|---|
1 | VDD | 数字接口电源电压 |
2 | GND | 接地 |
3 | 保留 | |
4 | GND | 接地 |
5 | GND | 接地 |
6 | vs | 电源电压 |
7 | CS | 片选 |
8 | INT1 | 中断1输出 |
9 | INT2 | 中断2输出 |
10 | NC | 内部不练接 |
11 | 保留 | |
12 | SDO/ALT ADDRESS | 串行数据输出(SPI 4线)/备用I2C地址选择(I2C |
13 | SDA/SDI/SDIO | 串行数据(I2C)/串行数据输入(SPI 4线)/串行数据输入和输出(SPI 3线)。 |
14 | SCL/SCLk | 串行通信时钟。 SCL为I2C时钟, SCLK为SPI时钟 |
工作原理
既能测量运动或冲击导致的动态加速度,也能测量静止加速度,例如重力加速度,使得器件可作为倾斜传感器使用
施加VS,器件进入待机模式,此时功耗最小。
器件等待施加V DD I/O和接收进入测量模式的命令。(此命令可以通过设置POWER_CTL寄存器(地址0x2D)的测量位(位D3)启动。)此外,器件处于待机模式时,任何寄存器可以写入或读取,以配置器件。建议在待机模式配置器件,然后使能测量模式。清除测量位,器件返回到待机模式。
电源时序
条件 | VS | VDD | 描述 |
---|---|---|---|
关断 | 关 | 关 | 该器件完全关断,但可能存在通信总线冲突 |
总线禁用 | 开 | 关 | 该器件开启,进入待机模式,但通信不可用,并且与通信总线冲突 |
总线使能 | 关 | 开 | 无功能可用,但该器件不会与通信总线冲突 |
待机或测量模式 | 开 | 开 | 上电时,器件处于待机模式,等待进入测量模式的命令,所有传感器功能关闭。该器件得到指示后进入测量模式,所有的传感器功能都可用 |
低功耗模式:
要进入低功耗模式,在BW_RATE寄存器(地址0x2C)中设置LOW_POWER位(位4)。
自动休眠模式
如果ADXL345在静止期间自动切换到休眠模式,可以省电。要使能此功能,在THRESH_INACT寄存器(地址0x25)和TIME_INACT寄存器(地址0x26)设置一个值表示静止(适当值视应用而定),然后在POWER_CTL寄存器(地址0x2D)中设置AUTO_SLEEP位(位D4)和链接位(位D5)。
待机模式
更低功率操作,也可以使用待机模式。待机模式下,功耗降低到0.1 μA(典型值)。该模式中,无测量发生。在POWER_CTL寄存器(地址0x2D)中,清除测量位(位D3),
串行通信
可采用I2C和SPI数字通信。上述两种情况下, ADXL345作为从机运行。 CS引脚上拉至V DD I/O, I2C模式使能。 CS引脚应始终上拉至V DD I/O或由外部控制器驱动,因为CS引脚无连接时,默认模式不存在。因此,如果没有采取这些措施,可能会导致该器件无法通信。 SPI模式下, CS引脚由总线主机控制。 SPI和I2C两种操作模式下, ADXL345写入期间,应忽略从ADXL345传输到主器件的数据
这个器件可以使用IIC和SPI,因我我选择使用的IIC所以只有IIC的东西,关于SPI请大家自行了解。
IIC
1口和7口都接3.3V,
PB7<---->13 //数据线
PB6<---->14 //信号线
设备地址:0x53
因为是HAL库开发,所以只要配置好cubemx就只需在main.c中收发即可。
1、使用I2C1
2、打开串口(uarrt1)
波特率和你串口调试助手设置一样即可(通常连接电脑的串口一般都设置为115200)
3、时钟图
4、一些注意事项
<
5、生成代码
点击完之后会跳出来一个提示框,选择打开项目,他自己直接就跳到keil中了。
6、进入keil的第一件事情就是重定义printf
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,HAL_MAX_DELAY);//循环发送,直到发送完毕
return ch;
}
将这段代码加在main.c中,点击魔术棒,按照下图勾选**(很多情况下,串口不打印都是这个地方没勾选)**
并且添加头文件#include "stdio.h"
如果你嫌麻烦直接全选附后代码,我将整个main.c复制过来了。直接替换你的.c 文件即可
找到了一段可以不勾选的代码,但是报错,还没解决。(就先用这个吧)
7、附一张串口输出
8、main.c代码
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#define ADXL345_ADDR 0x53
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,HAL_MAX_DELAY);//循环发送,直到发送完毕
return ch;
}
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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_TIM3_Init();
MX_USART1_UART_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
printf("串口测试行hello 全西安最帅的嵌入式Linux工程师\n");
// 启用测量模式
uint8_t data[] = {0x2D, 0x08}; // 寄存器0x2D,值0x08表示启用测量
HAL_I2C_Master_Transmit(&hi2c1, ADXL345_ADDR << 1, data, 2, HAL_MAX_DELAY);
//uint8_t buf[100] = {0};
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// 读取加速度数据
uint8_t regAddr = 0x32; // 加速度数据起始寄存器地址
uint8_t dataRaw[6]; // 6个字节分别存储X、Y、Z轴的加速度数据
HAL_I2C_Master_Transmit(&hi2c1, ADXL345_ADDR << 1, ®Addr, 1, HAL_MAX_DELAY);
HAL_I2C_Master_Receive(&hi2c1, ADXL345_ADDR << 1, dataRaw, 6, HAL_MAX_DELAY);
int16_t accelerometer_data[3]; // 存储解析后的加速度数据
accelerometer_data[0] = (int16_t)((dataRaw[1] << 8) | dataRaw[0]); // X轴数据
accelerometer_data[1] = (int16_t)((dataRaw[3] << 8) | dataRaw[2]); // Y轴数据
accelerometer_data[2] = (int16_t)((dataRaw[5] << 8) | dataRaw[4]); // Z轴数据
printf("x = %d\n",accelerometer_data[0]);
printf("y = %d\n",accelerometer_data[1]);
printf("z = %d\n",accelerometer_data[2]);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */