IIC协议链接
/* -----------------------------------------头文件-----------------------------------------*/
#include "ADXL346.h"
#include "math.h"
/* -----------------------------------------宏定义-----------------------------------------*/
#if BrakeMode_EN
/* -----------------------------------------结构体定义-------------------------------------*/
ADXL346_XYZ xdata XYZ_DATA = {0, 0, 0};
ADXL346_XYZ xdata XYZ_DATA1 = {0, 0, 0};
/******************
笔记:
1、DelayTick = 2
2、ADDR:SD0==0==0xA6 ; SD0==1==0x3A 【写命令0xA6 读命令0xA6|1】
*******************/
code IIC_TYPE ADXL346 = {2, 0xA6};
/* -----------------------------------------全局变量定义-----------------------------------*/
xdata uint8_t GET_DATA[6] = {0, 0, 0, 0, 0, 0}; //用于记录IIC返回的XYZ
xdata uint8_t Brake_Motion = 0; //当空间值大于阈值,即代表运动过
xdata uint8_t Motion_TIME = 0; //用于清除运动标记,计数2S左右,如果没有发生刹车则清零
xdata uint16_t Spatial_value_Cumulative = 0;
/* -----------------------------------------应用程序---------------------------------------*/
/*********************************************
函数名:ADXL346_Configuration
功 能:ADXL346器件初始化配置
形 参:INTI:1--初始化方向 0--不初始化方向
返回值:
备 注:
作 者:薛建强
时 间:2019/06/11
**********************************************/
void ADXL346_Configuration(const uint8_t INIT)
{
IIC_Init(); // I2C初始化
clr_EA;//关闭中断
clr_EX0;
P30_Input_Mode;
ADXL346_Read_DATA(ACT_TAP_STATUS);//中断清零前,应读取ACT_TAP_STATUS寄存器
ADXL346_Read_DATA(INT_SOURCE);//读取ADX346中断标志寄存器,读一次清空一次中断标记
ADXL346_Write_DATA(POWER_CTL, 0x03); //设置时需进入休眠模式 1HZ
ADXL346_Write_DATA(DATA_FORMAT, 0x0A); //+8g,寄存器0x31—DATA_FORMAT(读/写)--中断设为高电平有效--全分辨率模式--右对齐模式
ADXL346_Write_DATA(BW_RATE, 0x0D); //相当于800 Hz的输出数据速率。即1.25ms采集一次
if (INIT)
{
/*竖立*/
ADXL346_Write_DATA(OFSX, Factory_X); //写入X偏移量 -250校正为0
ADXL346_Write_DATA(OFSY, Factory_Y); //写入Y偏移量 无偏移
ADXL346_Write_DATA(OFSZ, Factory_Z); //写入Z偏移量 校正为0
}
ADXL346_Write_DATA(FIFO_CTL, 0xA8); //FIFO流模式 将触发模式下的触发事件链接至INT1
/*中断配置*/
ADXL346_Read_DATA(ACT_TAP_STATUS); //中断清零前,应读取ACT_TAP_STATUS寄存器
ADXL346_Read_DATA(INT_SOURCE); //读取ADX346中断标志寄存器,读一次清空一次中断标记
ADXL346_Write_DATA(INT_ENABLE, 0x00); //禁用 中断
ADXL346_Write_DATA(THRESH_ACT, Activity_threshold); // 活动阈值 变化幅度>6
ADXL346_Write_DATA(DUR, Activity_time); // 活动阈值时间 单位:16ms
ADXL346_Write_DATA(THRESH_INACT, Static_threshold); // 静止阈值 变化幅度<6
ADXL346_Write_DATA(TIME_INACT, Static_time); // 静止时间 单位:5s
ADXL346_Write_DATA(ACT_INACT_CTL, Active_static_any_axis_selection); // 活动静止任意轴选择 Z轴使能
ADXL346_Write_DATA(INT_ENABLE, 0x00); //禁用 中断
if (SystemReg.BrakeMode == 1)
{
ADXL346_Off();
ADXL346_Write_DATA(INT_ENABLE, 0x18); //开启动态、静止等中断模式,19页
ADXL346_Write_DATA(INT_MAP, 0x00); //使能 中断 ININ1
ADXL346_Write_DATA(POWER_CTL, 0x08); //测量模式
}
clr_EA;
}
/*********************************************
函数名:ADXL346_Write_DATA
功 能:写 地址 数据
形 参:addr 地址 dat 数据
返回值:
备 注:
作 者:薛建强
时 间:2019/06/11
**********************************************/
void ADXL346_Write_DATA(const uint8_t addr, const uint8_t DATA)
{
IIC_Start(); // 启动
IIC_WriteByte(ADXL346.ADDR); // 设备地址
IIC_Wait_ACK(); // 等待数据响应
IIC_WriteByte(addr); // 发送寄存器地址
IIC_Wait_ACK(); // 等待数据响应
IIC_WriteByte(DATA); // 发送数据
IIC_Wait_ACK(); // 等待数据响应
IIC_Stop(); // 停止
}
/*********************************************
函数名:ADXL346_Read_DATA
功 能:读地址数据
形 参:addr--寄存器地址
返回值:
备 注:
作 者:薛建强
时 间:2019/06/11
**********************************************/
uint8_t ADXL346_Read_DATA(const uint8_t addr)
{
uint8_t GET_DATA = 0;
IIC_Start(); // 启动
IIC_WriteByte(ADXL346.ADDR); // 发送地址
IIC_Wait_ACK(); // 等待数据响应
IIC_WriteByte(addr); // 发送地址
IIC_Wait_ACK(); // 等待数据响应
IIC_Start(); // 启动
IIC_WriteByte(ADXL346.ADDR | 1); // 发送地址
IIC_Wait_ACK(); // 等待数据响应
GET_DATA = IIC_ReadByte(); // 获取数据
IIC_Wait_ACK(); // 等待数据响应
IIC_Stop(); // 停止
return GET_DATA;
}
/*********************************************
函数名:ADXL346_get_data
功 能:读取一次加速度值
形 参:
返回值:
备 注:
作 者:薛建强
时 间:2019/06/11
**********************************************/
void ADXL346_get_data(void)
{
uint8_t i = 0;
IIC_Start(); // 启动
IIC_WriteByte(ADXL346.ADDR); // 发送地址
IIC_Wait_ACK(); // 等待数据响应
IIC_WriteByte(0x32); // 发送地址
IIC_Wait_ACK(); // 等待数据响应
IIC_Start(); // 启动
IIC_WriteByte(ADXL346.ADDR | 1); // 发送地址
IIC_Wait_ACK(); // 等待数据响应
for (i = 0; i < 6; i++)
{
if (i == 5)
{
GET_DATA[i] = IIC_ReceiveData(0);
}
else
{
GET_DATA[i] = IIC_ReceiveData(1);
}
}
IIC_Stop(); // 停止
if (Brake_Reg.Current_direction == 1 || Brake_Reg.Current_direction == 0)
{
XYZ_DATA1.X = (int)((GET_DATA[5] << 8) | (GET_DATA[4])); //X轴
XYZ_DATA1.Y = (int)((GET_DATA[3] << 8) | (GET_DATA[2])); //Y轴
}
else
{
XYZ_DATA1.X = (int)((GET_DATA[3] << 8) | (GET_DATA[2])); //Y轴
XYZ_DATA1.Y = (int)((GET_DATA[5] << 8) | (GET_DATA[4])); //X轴
}
XYZ_DATA1.Z = (int)((GET_DATA[1] << 8) | (GET_DATA[0])); //Z轴
}
/*********************************************
函数名:ADXL346_Off
功 能:进入暂停模式
形 参:
返回值:
备 注:
作 者:薛建强
时 间:2019/06/11
**********************************************/
void ADXL346_Off(void)
{
IIC_Start(); // 启动
IIC_WriteByte(ADXL346.ADDR); // 设备地址
IIC_Wait_ACK(); // 等待数据响应
IIC_WriteByte(0x2D); // 发送寄存器地址
IIC_Wait_ACK(); // 等待数据响应
IIC_WriteByte(0x04); // 发送数据
IIC_Wait_ACK(); // 等待数据响应
IIC_Stop(); // 停止
}
uint16_t StopState_Time_S = 0;
/*********************************************
函数名:ADXL346_FIFORead
功 能:从缓冲器中读取一次32个值,并求平均值
形 参:pData:存储平均值后的XYZ值
返回值:
备 注:
作 者:薛建强
时 间:2019/08/30
使 用:
**********************************************/
#define ReadNum 7
void ADXL346_FIFORead(ADXL346_XYZ *pData)
{
uint8_t i = 0, Loop = 0;
int X = 0, Y = 0, Z = 0;
uint16_t Spatial_value = 0;
for (Loop = 0; Loop < ReadNum; Loop++)
{
IIC_Start(); // 启动
IIC_WriteByte(ADXL346.ADDR); // 发送地址
IIC_Wait_ACK(); // 等待数据响应
IIC_WriteByte(0x32); // 发送地址
IIC_Wait_ACK(); // 等待数据响应
IIC_Start(); // 启动
IIC_WriteByte(ADXL346.ADDR | 1); // 发送地址
IIC_Wait_ACK(); // 等待数据响应
for (i = 0; i < 6; i++)
{
if (i == 5)
{
GET_DATA[i] = IIC_ReceiveData(0);
}
else
{
GET_DATA[i] = IIC_ReceiveData(1);
}
}
IIC_Stop(); // 停止
if (Brake_Reg.Current_direction == 1 || Brake_Reg.Current_direction == 0)
{
X += (int)((GET_DATA[1] << 8) | (GET_DATA[0])); //X轴
Y += (int)((GET_DATA[3] << 8) | (GET_DATA[2])); //Y轴
}
else
{
X += (int)((GET_DATA[3] << 8) | (GET_DATA[2])); //Y轴
Y += (int)((GET_DATA[1] << 8) | (GET_DATA[0])); //X轴
}
Z += (int)(~((GET_DATA[5] << 8) | (GET_DATA[4])) + 1); //Z轴 已经做反向处理
os_wait(K_IVL, 5, 0);//1ms
}
pData->X = X / ReadNum / 4;
pData->Y = Y / ReadNum / 4;
pData->Z = Z / ReadNum / 4;
if (((abs(pData->X) * 0.9 < pData->Z) || (abs(pData->X) < pData->Z)) && ((abs(pData->Y) * 0.9 < pData->Z) || abs(pData->Y) < 30)) //判断是否为有效值 && abs(XYZ_DATA.Y) < XYZ_DATA.Z
{
Spatial_value = sqrt(pData->X * pData->X + pData->Y * pData->Y + pData->Z * pData->Z);//归一处理
if (Spatial_value >= 5)//针对轻刹
{
if (Brake_Reg.Brake_OK < 250 && pData->Z > 0)
{
Brake_Motion = 1;
Motion_TIME = 0;
if (Brake_Reg.Brake_OK < 8 && ++Brake_Reg.Brake_OK >= 7)
{
Brake_Reg.Brake_OK = 7;
}
Spatial_value_Cumulative += Spatial_value; //累计加速度值
if (Brake_Reg.Brake_OK > 3 && Brake_Reg.Motion_State > 0) //至少有三个连续动作
{
//**刹车
Brake_Reg.Brake_OK = 0;
Brake_Motion = 0;
Spatial_value_Cumulative = 0;
//Send_Data_To_UART0('&');
Brake_Time_Add();//延迟刹车灯光
}
else if (Brake_Reg.Brake_OK > 2 && ((Spatial_value_Cumulative / Brake_Reg.Brake_OK) >= 9) && Brake_Reg.Motion_State > 0) //至少有两个连续动作
{
//**刹车
Brake_Reg.Brake_OK = 0;
Brake_Motion = 0;
Spatial_value_Cumulative = 0;
//Send_Data_To_UART0('&');
Brake_Time_Add();//延迟刹车灯光
}
}
}
else
{
Brake_Reg.Brake_OK = 0;
Spatial_value_Cumulative = 0;
os_wait(K_IVL, 1, 0);//1ms
}
}
else
{
Brake_Reg.Brake_OK = 0;
os_wait(K_IVL, 1, 0);//1ms
}
//printf("%d,%d,0\n", (uint16_t) sqrt(pData->X * pData->X + pData->Y * pData->Y + pData->Z * pData->Z), (uint16_t)Brake_Reg.Motion_State);
if (abs(pData->X - XYZ_DATA1.X) < 5 && abs(pData->Y - XYZ_DATA1.Y) < 5 && abs(pData->Z - XYZ_DATA1.Z) < 5) //是否相对静止
{
if (StopState_Time_S < 650 && ++StopState_Time_S > 600)//1min
{
StopState_Time_S = 0;
if (Brake_Reg.StopState_Time < 250)
{
Brake_Reg.StopState_Time++;
}
}
if (Brake_Reg.StopState_Num < 40)
{
Brake_Reg.StopState_Num++;
}
else
{
Brake_Reg.StopState_Num = 0;
if (Brake_Reg.StopState_FLAG == 1)
{
if (abs(pData->X) > 50 || abs(pData->Y) > 50)
{
}
else
{
ADXL346_jiaozhun();
//Send_Data_To_UART0('&');
Brake_Reg.StopState_FLAG = 0;
Brake_Time_On = 40;
}
}
}
}
else
{
/*关灯后,唤醒,重新激活*/
if (Brake_Reg.StopState_Time >= 5)
{
PWM_Change = 0;
CoefficientVaue = 100;
SystemReg.RunningState = 0;
Brake_Reg.LEDOff = 1;
}
Brake_Reg.StopState_Num = 0;
StopState_Time_S = 0;
}
if (abs(pData->X) > 4 || abs(pData->Y) > 4 || abs(pData->Z) > 4)
{
if (Brake_Reg.Motion_State < 250 && ++Brake_Reg.Motion_State > 5)
{
Brake_Reg.StopState_FLAG = 1; //运动过,可以用校准
}
}
XYZ_DATA1 = *pData;
//printf("%d,%d,%d-%d\n", pData->X, pData->Y, pData->Z, (uint16_t)Brake_Reg.StopState_Num);
//printf("%d,%d,%d\n", (uint16_t)Brake_Reg.Motion_State, (uint16_t)Brake_Reg.Static_Keep, pData->Z);
}
/*********************************************
函数名:ADXL346_jiaozhun
功 能:对各个方向进行一次校准
形 参:
返回值:
备 注:
作 者:薛建强
时 间:2019/09/16
使 用:
**********************************************/
void ADXL346_jiaozhun(void)
{
static uint8_t i = 0;
one:
if (jiaozhun_LED) LED_RGB(4);//黄灯
os_wait(K_IVL, 10, 0);//10ms
/*清零*/
ADXL346_Write_DATA(OFSX, 0);
os_wait(K_IVL, 10, 0);//10ms
ADXL346_Write_DATA(OFSY, 0);
os_wait(K_IVL, 10, 0);//10ms
ADXL346_Write_DATA(OFSZ, 0);
os_wait(K_IVL, 250, 0);//250ms
ADXL346_get_data();
os_wait(K_IVL, 100, 0);//100ms
//printf("(%d,%d,%d)\n", XYZ_DATA1.X, XYZ_DATA1.Y, XYZ_DATA1.Z);
ADXL346_Write_DATA(OFSX, -(XYZ_DATA1.Z / 4));
os_wait(K_IVL, 10, 0);//10ms
ADXL346_Write_DATA(OFSY, -(XYZ_DATA1.Y / 4));
os_wait(K_IVL, 10, 0);//10ms
ADXL346_Write_DATA(OFSZ, -(XYZ_DATA1.X / 4));
os_wait(K_IVL, 250, 0);//250ms
/*获取一次当前值*/
ADXL346_get_data();
if (abs((XYZ_DATA1.Z / 4)) > 3 || abs((XYZ_DATA1.Y / 4)) > 3 || abs((XYZ_DATA1.X / 4)) > 3)
{
//printf("[%d,%d,%d]\n", XYZ_DATA1.X / 4, XYZ_DATA1.Y / 4, XYZ_DATA1.Z / 4);
if (i < 250 && ++i > 5)
{
if (jiaozhun_LED) LED_OFF();
Brake_Reg.StopState_FLAG = 0; //不可校准,防止不停校准
ADXL346_Configuration(1);//初始化默认值
return;
}
if (i >= 250) i = 0;
os_wait(K_IVL, 5, 0);//5ms
goto one;
}
//printf("(%d,%d,%d)\n", XYZ_DATA1.X / 4, XYZ_DATA1.Y / 4, XYZ_DATA1.Z / 4);
Brake_Reg.Motion_State = 0;
Brake_Reg.BrakeTriggerFlag = 0; //检测到没有刹车
Brake_Reg.Collect_Tmr = 0;
Brake_Reg.StopState_FLAG = 0; //不可校准,防止不停校准
if (jiaozhun_LED) LED_OFF();
i = 0;
}
/*********************************************
函数名:ADXL346_INT_EN
功 能:ADXL346中断功能切换
形 参:
返回值:
备 注:
作 者:薛建强
时 间:2019/06/28
使 用:
**********************************************/
void ADXL346_INT_EN(const uint8_t En)
{
if (En == 1)
{
ADXL346_Write_DATA(INT_MAP, 0x00); //使能 中断 ININ1
ADXL346_Write_DATA(DATA_FORMAT, 0x2B); //高电平中断、全分辨率
ADXL346_Write_DATA(INT_ENABLE, 0x10); //使能 中断
Brake_Reg.Interrupt = 0x10;
/*外部引脚控制*/
clr_EA;//关闭中断
P30_Input_Mode;
set_IT0;
set_EX0;
set_EA; // global enable bit
}
else
{
ADXL346_Write_DATA(INT_ENABLE, 0x00); //禁用 中断
/*外部引脚控制*/
clr_EX0;
clr_EA;
}
}
/*********************************************
函数名:ADXL346_Motion_Quiet_Interrupt
功 能:切换加速度传感器的中断方式
形 参:ch--0x18 动静态中断 ch--0x10 动态中断
返回值:
备 注:
作 者:薛建强
时 间:2019/11/21
使 用:
**********************************************/
void ADXL346_Motion_Quiet_Interrupt(uint8_t ch)
{
ADXL346_Read_IQn();
os_wait(K_IVL, 10, 0);//10ms
ADXL346_Off();
os_wait(K_IVL, 10, 0);//10ms
ADXL346_Write_DATA(INT_ENABLE, ch);//开启动态检测
Brake_Reg.Interrupt = 0x10;
os_wait(K_IVL, 5, 0);//5ms
ADXL346_Write_DATA(INT_MAP, 0x00); //使能 中断 ININ1
os_wait(K_IVL, 5, 0);//5ms
ADXL346_Write_DATA(POWER_CTL, 0x08);//测量模式
os_wait(K_IVL, 5, 0);//5ms
LowPower_Tmr = 180;
Brake_Reg.Motion_State = 0;
os_wait(K_IVL, 10, 0);//10ms
}
void ADXL346_Read_IQn(void)
{
ADXL346_Read_DATA(0x2B);//中断清零前,应读取ACT_TAP_STATUS寄存器
ADXL346_Read_DATA(0x30);//读取ADX346中断标志寄存器,读一次清空一次中断标记
}
#endif
#ifndef __ADXL346_H
#define __ADXL346_H
/* -----------------------------------------头文件-----------------------------------------*/
#include "main.h"
/* -----------------------------------------宏定义-----------------------------------------*/
#define DEVICE_ID 0X00 // 器件ID 0xE5
#define THRESH_TAP 0X1D // 敲击阈值
#define OFSX 0X1E // X轴偏移
#define OFSY 0X1F // Y轴偏移
#define OFSZ 0X20 // Z轴偏移
#define DUR 0X21
#define Latent 0X22
#define Window 0X23
#define THRESH_ACT 0X24
#define THRESH_INACT 0X25
#define TIME_INACT 0X26
#define ACT_INACT_CTL 0X27
#define THRESH_FF 0X28
#define TIME_FF 0X29
#define TAP_AXES 0X2A
#define ACT_TAP_STATUS 0X2B
#define BW_RATE 0X2C
#define POWER_CTL 0X2D
#define INT_ENABLE 0X2E
#define INT_MAP 0X2F
#define INT_SOURCE 0X30
#define DATA_FORMAT 0X31
#define DATA_X0 0X32
#define DATA_X1 0X33
#define DATA_Y0 0X34
#define DATA_Y1 0X35
#define DATA_Z0 0X36
#define DATA_Z1 0X37
#define FIFO_CTL 0X38
#define FIFO_STATUS 0X39
#define ADXL_READ 0X3B
#define ADXL_WRITE 0X3A
//设置出厂值
#define Factory_X (-71)
#define Factory_Y (0)
#define Factory_Z (4)
#define Activity_threshold 6 //活动阀值
#define Activity_time 16 //活动阈值时间 单位:ms
#define Static_threshold 6 //静止阀值
#define Static_time 5 //静止阈值时间 单位:s
#define Active_static_any_axis_selection 0x9F //活动静止任意轴选择 Z轴使能
#define jiaozhun_LED 0 //是否打开校准灯
/* -----------------------------------------结构体定义-------------------------------------*/
typedef struct
{
int X; //x轴数据
int Y; //y轴数据
int Z; //z轴数据
}ADXL346_XYZ;
extern ADXL346_XYZ xdata XYZ_DATA;
extern ADXL346_XYZ xdata XYZ_DATA1;
/* -----------------------------------------全局变量定义-----------------------------------*/
extern xdata uint8_t Brake_Motion;
extern uint16_t StopState_Time_S;
/* -----------------------------------------应用程序---------------------------------------*/
void ADXL346_Configuration(const uint8_t INIT);
void ADXL346_Write_DATA (const uint8_t addr,const uint8_t DATA);
uint8_t ADXL346_Read_DATA (const uint8_t addr);
void ADXL346_get_data (void); // 获得数据
void ADXL346_Off (void);
void ADXL346_INT_EN (const uint8_t En);
void ADXL346_FIFORead (ADXL346_XYZ *pData);
void ADXL346_jiaozhun (void);
void ADXL346_Motion_Quiet_Interrupt(uint8_t ch);
void ADXL346_Read_IQn (void);
#endif