#include "motion.h"
#include "delay.h"
// 运动检测全局变量
static u16 shake_count = 0;
static u16 step_count = 0;
static u16 squat_count = 0;
// 加速度传感器原始数据
static int16_t acc_x = 0, acc_y = 0, acc_z = 0;
static int16_t last_acc_x = 0, last_acc_y = 0, last_acc_z = 0;
// 运动检测初始化
void MOTION_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
// 使能I2C1和GPIO时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// 配置I2C1引脚: SCL-PB6, SDA-PB7
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 配置I2C1
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 400000;
I2C_Init(I2C1, &I2C_InitStructure);
// 使能I2C1
I2C_Cmd(I2C1, ENABLE);
// 初始化MPU6050
MPU6050_Init();
// 初始化计数器
MOTION_ResetCounters();
}
// 初始化MPU6050
void MPU6050_Init(void)
{
// 唤醒MPU6050
I2C_WriteByte(MPU6050_ADDR, MPU6050_PWR_MGMT_1, 0x00);
Delay_ms(100);
// 设置陀螺仪量程为±2000°/s
I2C_WriteByte(MPU6050_ADDR, MPU6050_GYRO_CONFIG, 0x08);
// 设置加速度计量程为±4g
I2C_WriteByte(MPU6050_ADDR, MPU6050_ACCEL_CONFIG, 0x08);
// 设置采样率分频
I2C_WriteByte(MPU6050_ADDR, MPU6050_SMPLRT_DIV, 0x07);
// 设置数字低通滤波器
I2C_WriteByte(MPU6050_ADDR, MPU6050_CONFIG, 0x06);
}
// I2C写一个字节
void I2C_WriteByte(u8 addr, u8 reg, u8 data)
{
// 发送起始信号
I2C_GenerateSTART(I2C1, ENABLE);
// 等待起始信号发送完成
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
// 发送设备地址(写)
I2C_Send7bitAddress(I2C1, addr << 1, I2C_Direction_Transmitter);
// 等待地址发送完成
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
// 发送寄存器地址
I2C_SendData(I2C1, reg);
// 等待寄存器地址发送完成
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// 发送数据
I2C_SendData(I2C1, data);
// 等待数据发送完成
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// 发送停止信号
I2C_GenerateSTOP(I2C1, ENABLE);
}
// I2C读取多个字节
void I2C_ReadBytes(u8 addr, u8 reg, u8 length, u8 *data)
{
// 发送起始信号
I2C_GenerateSTART(I2C1, ENABLE);
// 等待起始信号发送完成
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
// 发送设备地址(写)
I2C_Send7bitAddress(I2C1, addr << 1, I2C_Direction_Transmitter);
// 等待地址发送完成
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
// 发送寄存器地址
I2C_SendData(I2C1, reg);
// 等待寄存器地址发送完成
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// 发送起始信号(重新开始)
I2C_GenerateSTART(I2C1, ENABLE);
// 等待起始信号发送完成
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
// 发送设备地址(读)
I2C_Send7bitAddress(I2C1, addr << 1, I2C_Direction_Receiver);
// 等待地址发送完成
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
// 接收数据
for(u8 i = 0; i < length; i++)
{
if(i == length - 1)
{
// 最后一个字节,不发送ACK
I2C_AcknowledgeConfig(I2C1, DISABLE);
}
// 等待数据接收完成
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
// 读取数据
data[i] = I2C_ReceiveData(I2C1);
}
// 发送停止信号
I2C_GenerateSTOP(I2C1, ENABLE);
// 重新使能ACK
I2C_AcknowledgeConfig(I2C1, ENABLE);
}
// 读取加速度数据
void MPU6050_ReadAccel(int16_t *x, int16_t *y, int16_t *z)
{
u8 buffer[6];
I2C_ReadBytes(MPU6050_ADDR, MPU6050_ACCEL_XOUT_H, 6, buffer);
*x = (buffer[0] << 8) | buffer[1];
*y = (buffer[2] << 8) | buffer[3];
*z = (buffer[4] << 8) | buffer[5];
}
// 检测运动
void MOTION_Detect(void)
{
// 保存上一次的加速度值
last_acc_x = acc_x;
last_acc_y = acc_y;
last_acc_z = acc_z;
// 读取当前加速度值
MPU6050_ReadAccel(&acc_x, &acc_y, &acc_z);
// 计算加速度变化量
int16_t delta_x = acc_x - last_acc_x;
int16_t delta_y = acc_y - last_acc_y;
int16_t delta_z = acc_z - last_acc_z;
// 计算总变化量
uint16_t total_delta = abs(delta_x) + abs(delta_y) + abs(delta_z);
// 检测摇晃
if(total_delta > SHAKE_THRESHOLD)
{
static uint32_t last_shake_time = 0;
uint32_t current_time = GetCurrentTime();
// 防抖处理,避免重复计数
if(current_time - last_shake_time > SHAKE_DEBOUNCE_TIME)
{
shake_count++;
last_shake_time = current_time;
}
}
// 检测步数
static int16_t last_z = 0;
static uint8_t step_state = 0;
if(step_state == 0 && acc_z > STEP_THRESHOLD_HIGH && last_z <= STEP_THRESHOLD_HIGH)
{
step_state = 1;
}
else if(step_state == 1 && acc_z < STEP_THRESHOLD_LOW && last_z >= STEP_THRESHOLD_LOW)
{
step_count++;
step_state = 0;
}
last_z = acc_z;
// 检测深蹲
static int16_t last_y_value = 0;
static uint8_t squat_state = 0;
if(squat_state == 0 && acc_y > SQUAT_THRESHOLD_DOWN && last_y_value <= SQUAT_THRESHOLD_DOWN)
{
squat_state = 1;
}
else if(squat_state == 1 && acc_y < SQUAT_THRESHOLD_UP && last_y_value >= SQUAT_THRESHOLD_UP)
{
squat_count++;
squat_state = 0;
}
last_y_value = acc_y;
}
// 获取当前摇晃次数
u16 MOTION_GetShakeCount(void)
{
return shake_count;
}
// 获取当前步数
u16 MOTION_GetStepCount(void)
{
return step_count;
}
// 获取当前深蹲次数
u16 MOTION_GetSquatCount(void)
{
return squat_count;
}
// 重置计数器
void MOTION_ResetCounters(void)
{
shake_count = 0;
step_count = 0;
squat_count = 0;
}
// 获取当前时间(模拟函数,实际项目中应使用定时器实现)
uint32_t GetCurrentTime(void)
{
// 这里使用一个简单的静态变量来模拟时间
static uint32_t time = 0;
time++;
return time;
}这是我的motion.c代码,出现了以下报错Hardwore\motion.c(53): warning: #223-D: function "I2C_WriteByte" declared implicitly
I2C_WriteByte(MPU6050_ADDR, MPU6050_PWR_MGMT_1, 0x00);
Hardwore\motion.c(70): error: #159: declaration is incompatible with previous "I2C_WriteByte" (declared at line 53)
void I2C_WriteByte(u8 addr, u8 reg, u8 data)
Hardwore\motion.c(184): warning: #223-D: function "abs" declared implicitly
uint16_t total_delta = abs(delta_x) + abs(delta_y) + abs(delta_z);
Hardwore\motion.c(190): warning: #223-D: function "GetCurrentTime" declared implicitly
uint32_t current_time = GetCurrentTime();
Hardwore\motion.c(260): error: #159: declaration is incompatible with previous "GetCurrentTime" (declared at line 190)
uint32_t GetCurrentTime(void)
Hardwore\motion.c: 3 warnings, 2 errors
最新发布