OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6618|回复: 2

求助:ADXL345摔倒报警系统的摔倒检测疑问

[复制链接]

1

主题

1

帖子

0

精华

新手入门

积分
4
金钱
4
注册时间
2017-5-23
在线时间
1 小时
发表于 2017-5-23 19:57:48 | 显示全部楼层 |阅读模式
1金钱
最近在淘宝上买了一个基于ADXL345的摔倒报警器,可是搞不懂它的程序。求大神指点一下。
if(ReadAdxl345==TRUE)   //定时读取adxl345数据
        {
           ReadAdxl345=FALSE;
           ReadData_x();                      //三轴检测函数
//         sprintf(displaytemp,"yTemp: %8.3f ",temp_Y);//打印温度值
//         SendStr(displaytemp,16);//显示第二行
//         sprintf(displaytemp,"xTemp: %8.3f ",temp_X);//打印温度值
//         SendStr(displaytemp,16);//显示第二行
           CheckNum++;
           if((temp_X<550)||(abs(temp_Y)>750))       //方位值判断 查看正常次数     请问这里的550和750是什么意思 三轴加速度跟温度有关系吗 为什么要打印温度值?
           {
              ErrorNum++;
           }
           if(CheckNum>=5)       //进行5次处理
           {
              if(KeyLater>=3)       //非按键下
              {
                  if(ErrorNum>=3)      //角度出现错误 5次出息3次情况
                  {
                     BUZZER=0;     //打开蜂鸣器
以下附上主程序和ADXL345的调用程序

Main.c
#include<reg52.h>//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include<stdio.h>
#include"1602.h"
#include"delay.h"
#include"math.h"
#include"adxl345.h"
sbitBUZZER=P1^4;
sbitLED=P1^1;
sbitkey=P2^2;
unsignedchar ReadAdxl345;     //定时读取adxl345数据
chardisplaytemp[16];        //  显示暂存 方便调试
unsignedlong time_20ms=0;  //  系统定时计数
unsignedlong KeyLater=3;    //按键延时计数
unsignedlong ReportLater=0; //上报延时
charCrtl_Z[1]={0x1a};      //发送短信最后字节
voidInit_Timer0(void);
voidSendStr(unsigned char *s,unsigned char length);
voidUART_Init(void);
voidSendByte(unsigned char dat);
voidmain (void)
{     
    static unsigned char ErrorNum=0;
    static unsigned char CheckNum=0;
    Init_Timer0();        //定时器0初始化
    UART_Init();
    DelayMs(20);          //延时有助于稳定
    Init_ADXL345();     //清屏
    if(Single_Read_ADXL345(0X00)==0xe5)    //读出的数据为0XE5,表示正确
    {
       DelayMs(5);
       SendStr("ready ok",8);//显示第二行
    }
    else
    {
       DelayMs(3);
    }
    BUZZER=1;
    LED=1;
    while (1)         //主循环
    {
       if(ReadAdxl345==TRUE)   //定时读取adxl345数据
        {
           ReadAdxl345=FALSE;
           ReadData_x();                      //三轴检测函数
//         sprintf(displaytemp,"yTemp: %8.3f",temp_Y);//打印温度值
//         SendStr(displaytemp,16);//显示第二行
//         sprintf(displaytemp,"xTemp: %8.3f",temp_X);//打印温度值
//         SendStr(displaytemp,16);//显示第二行
           CheckNum++;
           if((temp_X<550)||(abs(temp_Y)>750))       //方位值判断 查看正常次数
           {
              ErrorNum++;
           }
           if(CheckNum>=5)       //进行5次处理
           {
              if(KeyLater>=3)       //非按键下
              {
                  if(ErrorNum>=3)      //角度出现错误5次出息3次情况
                  {
                     BUZZER=0;     //打开蜂鸣器
                  }
                  else
                  {                 
                     BUZZER=1;     //关闭蜂鸣器
                     ReportLater=0;       //上报延时计数
                  }                 
              }
           
              ErrorNum=0;         //清空滤波计数
              CheckNum=0;   
           }
        }
       if(ReportLater>=20)  //2min
       {
           LED=0;
           SendStr("AT+CMGF=1\r\n",11);
           DelayMs(700);//延时2秒
          SendStr("AT+CSCS=\"GSM\"\r\n",15);
           DelayMs(700);//延时2秒
//         SendStr("AT+CMGS=\"+8618105140357\"\r\n",26);//可以修改电话号码
           SendStr("AT+CMGS=\"+8615395181107\"\r\n",26);//可以修改电话号码
           DelayMs(700);//延时2秒
           SendStr("Help me!!",9);  //可以修改短信内容,9代表短信内容长度,不可以发汉字,如果发汉字的话,需要转化为特定的码                     
           DelayMs(10);//延时
           SendStr( (uchar *)Crtl_Z, 1);       //发送
           DelayMs(2000);//延时5秒
           LED=1;
           BUZZER=1;
           ReportLater=0;
           KeyLater=0;
       }
       if(key==0)     //按键处理
       {
           DelayMs(10);      //按键消抖动
           if(key==0)
           {
              ReportLater=0;      //按键延时上报
              BUZZER=1;      //关闭蜂鸣器
              KeyLater=0;       //按键延时处理
           }
       }
    }
}
void Init_Timer0(void)
{
    TMOD |= 0x01;   //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响         
    TH0=(65536-20000)/256;        //重新赋值20ms
    TL0=(65536-20000)%256;
    EA=1;            //总中断打开
    ET0=1;           //定时器中断打开
    TR0=1;           //定时器开关打开
}
voidTimer0_isr(void) interrupt 1
{
    TH0=(65536-20000)/256;        //重新赋值20ms
    TL0=(65536-20000)%256;
//  LED=!LED;
    time_20ms++;
    if(time_20ms%10==0)
    {
       ReadAdxl345=TRUE;
    }
    if(time_20ms%47==0)
    {
       ReportLater++;
       KeyLater++;
    }
}
voidUART_Init(void)
{
    SCON = 0x50;            // SCON: 模式 1, 8-bit UART, 使能接收  
    TMOD |= 0x20;               // TMOD: timer 1, mode 2, 8-bit 重装
    TH1  = 0xFD;               // TH1:  重装值 9600 波特率 晶振 11.0592MHz
    TL1 = TH1;
    TR1  = 1;                  // TR1:  timer 1 打开                        
    EA   = 1;                  //打开总中断
    ES   = 1;                  //打开串口中断
}
voidSendByte(unsigned char dat)
{
    unsigned char time_out;
    time_out=0x00;
    SBUF = dat;
    while((!TI)&&(time_out<10))
    {time_out++;DelayMs(1);}
    TI = 0;
}
voidSendStr(unsigned char *s,unsigned char length)
{
    unsigned char NUM;
    NUM=0x00;
    while(NUM<length)
    {
       SendByte(*s);
       s++;
       NUM++;
     }
}
voidUART_SER (void) interrupt 4   //串行中断服务程序
{
    if(RI)                        //判断是接收中断产生
    {
       RI=0;                      //标志位清零
    }
    if(TI) //如果是发送标志位,清零
    TI=0;
}
adxl345.h
#include"adxl345.h"
#include  <INTRINS.H>
#defineLcd1602
sbitSCL=P1^2;
sbitSDA=P1^3;
#defineSCL_OUT   ;//(P4DIR|=BIT2) //置位scl
#defineSET_SCL SCL=1;//(P4OUT|=BIT2) //置位scl
#defineCLE_SCL SCL=0;//(P4OUT&=~BIT2)//清楚scl
                    
#defineSDA_OUT ;//(P4DIR|=BIT3)
#defineSDA_INT ;//(P4DIR&=~BIT3)
#defineSET_SDA SDA=1;//(P4OUT|=BIT3)//置位sda
#defineCLE_SDA SDA=0;//(P4OUT&=~BIT3)//清楚sda
#defineSDA_VAL SDA//(P4IN&BIT3)
#define    SlaveAddress   0xA6    //定义器件在IIC总线中的从地址,根据ALT  ADDRESS地址引脚不同修改                  //ALT  ADDRESS引脚接地时地址为0xA6,接电源时地址为0x3A
unsignedchar BUF[8];                         //接收数据缓存区        
ucharge,shi,bai,qian,wan;           //显示变量
unsignedchar err;
floattemp_X,temp_Y,temp_Z;
voidDelay5us()
{
    _nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();
}
voidDelay5ms()
{
    unsigned int n = 560;
    while (n--);
}
/**************************************
起始信号
**************************************/
voidADXL345_Start()
{
    SDA = 1;                    //拉高数据线
    SCL = 1;                    //拉高时钟线
    Delay5us();                 //延时
    SDA = 0;                    //产生下降沿
    Delay5us();                 //延时
    SCL = 0;                    //拉低时钟线
}
/**************************************
停止信号
**************************************/
voidADXL345_Stop()
{
    SDA = 0;                    //拉低数据线
    SCL = 1;                    //拉高时钟线
    Delay5us();                 //延时
    SDA = 1;                    //产生上升沿
    Delay5us();                 //延时
}
/**************************************
发送应答信号
入口参数:ack(0:ACK 1:NAK)
**************************************/
voidADXL345_SendACK(uchar ack)
{   
    SDA = ack;                  //写应答信号
    SCL = 1;                    //拉高时钟线
    Delay5us();                 //延时
    SCL = 0;                    //拉低时钟线
    Delay5us();                 //延时
}
/**************************************
接收应答信号
**************************************/
ucharADXL345_RecvACK()
{
    bit CY00;
    SCL = 1;                    //拉高时钟线
    Delay5us();                 //延时
    CY00 = SDA;                   //读应答信号
    SCL = 0;                    //拉低时钟线
    Delay5us();                 //延时
    return CY00;
}
/**************************************
向IIC总线发送一个字节数据
**************************************/
voidADXL345_SendByte(unsigned char dat)
{
    unsigned char i;
    for (i=0; i<8; i++)         //8位计数器
    {
         if(dat&0x80)    //dat <<= 1;              //移出数据的最高位
        {
           SDA = 1;               //送数据口   //    SDA = CY;               //送数据口
       }
       else
           SDA=0;
       dat <<= 1;
        SCL = 1;                //拉高时钟线
        Delay5us();             //延时
        SCL = 0;                //拉低时钟线
        Delay5us();             //延时
    }
    ADXL345_RecvACK();
}
/**************************************
从IIC总线接收一个字节数据
**************************************/
unsignedchar ADXL345_RecvByte()
{
    unsigned char i;
    unsigned char dat = 0;
    SDA = 1;                    //使能内部上拉,准备读取数据,
    for (i=0; i<8; i++)         //8位计数器
    {
        dat <<= 1;
        SCL = 1;                //拉高时钟线
        Delay5us();             //延时
        dat |= SDA;             //读数据               
        SCL = 0;                //拉低时钟线
        Delay5us();             //延时
    }
    return dat;
}
//******单字节写入*******************************************
voidSingle_Write_ADXL345(uchar REG_Address,uchar REG_data)
{
    ADXL345_Start();                  //起始信号
   ADXL345_SendByte(SlaveAddress);  //发送设备地址+写信号
    ADXL345_SendByte(REG_Address);    //内部寄存器地址,请参考中文pdf22页
    ADXL345_SendByte(REG_data);       //内部寄存器数据,请参考中文pdf22页
    ADXL345_Stop();                   //发送停止信号
}
//********单字节读取*****************************************
ucharSingle_Read_ADXL345(uchar REG_Address)
{  uchar REG_data;
    ADXL345_Start();                          //起始信号
    ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
    ADXL345_SendByte(REG_Address);            //发送存储单元地址,从0开始
    ADXL345_Start();                          //起始信号
    ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
    REG_data=ADXL345_RecvByte();              //读出寄存器数据
    ADXL345_SendACK(1);   
    ADXL345_Stop();                           //停止信号
    return REG_data;
}
//*********************************************************
//
//连续读出ADXL345内部加速度数据,地址范围0x32~0x37
//
//*********************************************************
voidMultiple_Read_ADXL345(void)
{   uchar i;
    ADXL345_Start();                          //起始信号
    ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
    ADXL345_SendByte(0x32);                   //发送存储单元地址,从0x32开始
    ADXL345_Start();                          //起始信号
    ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
     for(i=0; i<6; i++)                     //连续读取6个地址数据,存储中BUF
    {
        BUF = ADXL345_RecvByte();          //BUF[0]存储0x32地址中的数据
        if (i == 5)
        {
           ADXL345_SendACK(1);                //最后一个数据需要回NOACK
        }
        else
        {
          ADXL345_SendACK(0);                //回应ACK
       }
   }
    ADXL345_Stop();                          //停止信号
    Delay5ms();
}
//*****************************************************************
//初始化ADXL345,根据需要请参考pdf进行修改************************
voidInit_ADXL345()
{
   Single_Write_ADXL345(0x31,0x0B);   //测量范围,正负16g,13位模式
   Single_Write_ADXL345(0x2C,0x08);   //速率设定为12.5 参考pdf13页
   Single_Write_ADXL345(0x2D,0x08);   //选择电源模式  参考pdf24页
   Single_Write_ADXL345(0x2E,0x80);   //使能 DATA_READY 中断
   Single_Write_ADXL345(0x1E,0x00);   //X 偏移量 根据测试传感器的状态写入pdf29页
   Single_Write_ADXL345(0x1F,0x00);   //Y 偏移量 根据测试传感器的状态写入pdf29页
   Single_Write_ADXL345(0x20,0x05);   //Z 偏移量 根据测试传感器的状态写入pdf29页
}
//***********************************************************************
//显示x轴
voidReadData_x()
{   
  int dis_data;                       //变量
  Multiple_Read_ADXL345();         //连续读出数据,存储在BUF中
  dis_data=(BUF[1]<<8)+BUF[0];  //合成数据  
//  if(dis_data<0)
//  {
//    dis_data=-dis_data;
//  }
  temp_X=(float)dis_data*3.9;  //计算数据和显示,查考ADXL345快速入门第4页
  dis_data=(BUF[3]<<8)+BUF[2];  //合成数据  
//  if(dis_data<0)
//  {
//    dis_data=-dis_data;
//  }
  temp_Y=(float)dis_data*3.9;  //计算数据和显示,查考ADXL345快速入门第4页
  dis_data=(BUF[5]<<8)+BUF[4];    //合成数据  
//  if(dis_data<0)
//  {
//    dis_data=-dis_data;
//  }
  temp_Z=(float)dis_data*3.9;  //计算数据和显示,查考ADXL345快速入门第4页

}



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
129
金钱
129
注册时间
2016-3-18
在线时间
28 小时
发表于 2017-10-10 15:43:55 | 显示全部楼层
应该是注释有错。temp_X和temp_Y并不是温度,而是加速度值,函数void ReadData_x()。550是指550mg,即0.55g,相当于重力加速度*0.55;750类似,任意轴的加速度值变化大于0.75g,说明有可能发生跌倒
回复

使用道具 举报

6

主题

359

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1604
金钱
1604
注册时间
2017-12-18
在线时间
173 小时
发表于 2017-12-18 17:28:25 | 显示全部楼层
是的,这个temp_X是加速度值,不是温度的英文缩写。但是只测X和Y轴的加速度能准确吗?是测静止物体?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 16:26

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表