完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
/*发数据组格式 xx xx xx xx xx xx 两字节加速度 总组数 坏组数 组间计时数 */ #include #include #include #define uchar unsigned char #define uint unsigned int #define DuQuYanShi 20 // DuQuShiJian(毫秒)+1895us=20ms;100到5递减5,20部分 #define ShuChuSuLv 0x0D //3200Hz,0x0F; 5部分 //1600Hz,0x0E; //800Hz ,0x0D; //400Hz ,0x0C; //200Hz ,0x0B; //100Hz ,0x0A; //50Hz ,0x09; //25Hz ,0x08; #define INT_SOURCE 0X30 //0x30—INT_SOURCE /*从机地址定义*/ #define SlaveAddress 0x3A //定义器件在IIC总线中的从地址,根据ALT ADDRESS地址引脚不同修改 //ALT ADDRESS引脚接地时地址为0xA6:写入0xA7:读取, // 接电源时地址为0x3A:写入,0x3B:读取 /*STC89C52RD单片机管脚定义*/ #define DataPort P0 //LCD1602数据端口 ***it LCM_RS=P1^5; //LCD1602命令端口 ***it LCM_RW=P1^6; //LCD1602命令端口 ***it LCM_EN=P1^7; //LCD1602命令端口 ***it DUAN=P1^0; // 数码管段控制 ***it WEI=P1^1; // 数码管位控制 ***it LEDEN=P1^2; // LED灯控制端 ***it LINE=P1^3; // 点阵行控制端 ***it SDA=P3^2; //ADXL345_IIC数据引脚定义 ***it SCL=P3^3; //ADXL345_IIC时钟引脚定义 ***it RST_1302=P3^4; //DS1302复位端,低电平关闭 ***it INT10=P3^5; //ADXL345_INT1引脚定义 ***it INT20=P3^6; //ADXL345_INT2引脚定义 ***it CS=P3^7; //ADXL345_CS引脚定义 /*系统数据缓冲器及全局变量定义*/ uchar BUF[6]={0}; //接收6字节XYZ三轴加速度数据缓存区 int Dis_Data[3]={0}; //存放3个字的XYZ三轴的加速度数据缓存器及待转换数据 idata uchar Dis_Dataa[75][2]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,25, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,25, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,25, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,25, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,25, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,25, }; uchar Wan,Qian,Bai,Shi,Ge,Shi_Fen,Bai_Fen,Qian_Fen; //转换后数据存储位变量 //***************************************************** // 数据处理函数 //***************************************************** /*将角度转换为液晶显示的各个数据位*/ void CONVERSION_Angle(float temp_data_a) /*改动过*/ { long temp_data; temp_data=temp_data_a*100; Bai=temp_data/10000+0x30 ; //+0x30是为转换为ASCII码表中相关字符值 百 temp_data=temp_data%10000; //取余运算 Shi=temp_data/1000+0x30 ; // 十 temp_data=temp_data%1000; //取余运算 Ge=temp_data/100+0x30 ; // 个 temp_data=temp_data%100; //取余运算 Shi_Fen=temp_data/10+0x30; // 十分位 temp_data=temp_data%10; //取余运算 Bai_Fen=temp_data+0x30; // 百分位 } /*将加速度转换为液晶显示的各个数据位*/ void CONVERSION_JIASUDU(double temp) /*改动过*/ { long temp_data; temp_data=(long)(temp*10); Wan=temp_data/100000+0x30 ; //+0x30是为转换为ASCII码表中相关字符值 万 temp_data=temp_data%100000; //取余运算 Qian=temp_data/10000+0x30 ; // 千 temp_data=temp_data%10000; //取余运算 Bai=temp_data/1000+0x30 ; // 百 temp_data=temp_data%1000; //取余运算 Shi=temp_data/100+0x30; // 十 temp_data=temp_data%100; //取余运算 Ge=temp_data/10+0x30; // 个 temp_data=temp_data%10; //取余运算 Shi_Fen=temp_data+0x30; // 十分位 } //***************************************************** // 各种延时函数 //***************************************************** /*延时k*999us=k个ms*/ void delay(uint k) //上电延时 { uint i,j; for(i=0;i for(j=0;j<121;j++) {;}} } /************************************** 延时5微秒(STC90C52RC@12M) 不同的工作环境,需要调整此函数,注意时钟过快时需要修改 当改用1T的MCU时,请调整此延时函数 **************************************/ void Delay5us() { _nop_(); } /************************************** 延时5毫秒(STC90C52RC@12M) 不同的工作环境,需要调整此函数 当改用1T的MCU时,请调整此延时函数 **************************************/ void Delay5ms() { int n = 560;while (n--); } //***************************************************** // 关于ADXL345加速度传感器通讯函数 //***************************************************** /*ADXL345加速度传感器:开始信号*/ void ADXL345_Start() { SDA = 1; //拉高数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时,tBUF,一个结束条件和起始条件之间的总线空闲时间可以是1.3us SDA = 0; //产生下降沿,起始/重复起始条件保持时间,可以是0.6us Delay5us(); //延时,起始/重复起始条件保持时间,可以是0.6us SCL = 0; //拉低时钟线 } /*ADXL345加速度传感器:停止信号*/ void ADXL345_Stop() { SDA = 0; //拉低数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时,停止条件建立时间,可以是0.6us SDA = 1; //产生上升沿 Delay5us(); //延时 } /*ADXL345加速度传感器:发送应答信号;入口参数:ack (0:ACK 1:NAK)*/ void ADXL345_SendACK(bit ack) { SDA = ack; //写应答信号 SCL = 1; //拉高时钟线 Delay5us(); //延时 SCL = 0; //拉低时钟线 Delay5us(); //延时 } /*ADXL345加速度传感器:接收应答信号*/ bit ADXL345_RecvACK() { SCL = 1; //拉高时钟线 Delay5us(); //延时 CY = SDA; //读应答信号 SCL = 0; //拉低时钟线 Delay5us(); //延时 return CY; } /*ADXL345加速度传感器:向ADXL345的IIC总线发送一个字节数据*/ void ADXL345_SendByte(uchar dat) { uchar i; for (i=0; i<8; i++) //8位计数器 { dat <<= 1; //移出数据的最高位 SDA = CY; //送数据口 SCL = 1; //拉高时钟线 Delay5us(); //延时 SCL = 0; //拉低时钟线 Delay5us(); //延时 } ADXL345_RecvACK(); } /*ADXL345加速度传感器:从ADXL345的IIC总线接收一个字节数据*/ uchar ADXL345_RecvByte() { uchar i; uchar dat = 0; SDA = 1; //使能内部上拉,准备读取数据,?? for (i=0; i<8; i++) //8位计数器 { dat <<= 1; SCL = 1; //拉高时钟线 Delay5us(); //延时 dat |= SDA; //读数据 SCL = 0; //拉低时钟线 Delay5us(); //延时 } return dat; } /*ADXL345加速度传感器:单字节写入*/ void Single_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(); //发送停止信号 } /*ADXL345加速度传感器:单字节读取*/ uchar Single_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加速度传感器:连续读出ADXL345内部加速度数据,地址范围0x32~0x37*/ void Multiple_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[i] = ADXL345_RecvByte(); //BUF[0]存储0x32地址中的数据 if (i == 5) { ADXL345_SendACK(1); //最后一个数据需要回NOACK } else { ADXL345_SendACK(0); //回应ACK } } ADXL345_Stop(); //停止信号 delay(DuQuYanShi); } /*ADXL345加速度传感器:初始化ADXL345设置,根据需要请参考pdf进行修改*/ void Init_ADXL345() { Single_Write_ADXL345(0x31,0x0B); //0x0B=0 0 0 0 测量范围,正负16g,13位模式 // 禁止自测力;4线式SPI模式;中断高电平;一直为0; // 1 0 11 // 全分辨率模式;右对齐模式;正负16g Single_Write_ADXL345(0x2C,ShuChuSuLv); //0x0x=000 0 1000;速率设定为12.5 参考pdf13页 // 硬件清零;正常操作 ;输出数据速率为25Hz 带宽为12.5Hz Single_Write_ADXL345(0x2D,0x08); //0x08=00 0 0 ;选择电源模式 参考pdf24页 // 硬件清零;静止活动功能同时进行;禁用自动切换至休眠模式 // 1 0 00 // 置于测量模式;将器件置于普通工作模式;休眠模式下的唤醒8Hz Single_Write_ADXL345(0x2E,0x80); //0x80=1 000 0000;使能 DATA_READY 中断 // 使能相应功能,生成中断; Single_Write_ADXL345(0x1E,0x00); //X 偏移量 根据测试传感器的状态写入pdf29页 Single_Write_ADXL345(0x1F,0x00); //Y 偏移量 根据测试传感器的状态写入pdf29页 Single_Write_ADXL345(0x20,0x00); //Z 偏移量 根据测试传感器的状态写入pdf29页 } //***************************************************** // 关于LCD1602显示函数 //***************************************************** /*关闭除LCD1602以外的其他显示器*/ void CLOSE_SHUMA_LED_DIANZHEN_1302(void) { DataPort=0xFF; //关闭数码管 WEI=0; DataPort=0x00; DUAN=0; LEDEN=1; //关闭LED灯 DataPort=0xFF; LEDEN=0; DataPort=0X00; //关闭点阵 LINE=0; RST_1302=0; //关闭DS1302 } /*LCD1602:读取忙标志,直至不忙,过**/ void WaitForEnable(void) { DataPort=0xff; LCM_RS=0;LCM_RW=1;_nop_(); LCM_EN=1;_nop_();_nop_(); while(DataPort&0x80); //读取忙标志,直至不忙过 LCM_EN=0; } /*LCD1602:写命令**/ void WriteCommandLCM(uchar CMD,uchar Attribc) { if(Attribc)WaitForEnable(); //直至不忙时,写命令 LCM_RS=0;LCM_RW=0;_nop_(); //_nop_ 一个指令周期 DataPort=CMD;_nop_(); LCM_EN=1;_nop_();_nop_();LCM_EN=0; } /*LCD1602:写数据**/ void WriteDataLCM(uchar dataW) { WaitForEnable(); LCM_RS=1;LCM_RW=0;_nop_(); DataPort=dataW;_nop_(); LCM_EN=1;_nop_();_nop_();LCM_EN=0; } /*LCD1602:初始化设置,可更改,实现各种显示效果**/ void InitLcd() { WriteCommandLCM(0x38,1); //8位数据接口,两行显示,5*7点阵字符 WriteCommandLCM(0x08,1); //显示开关为关,光标关,闪烁关 WriteCommandLCM(0x01,1); //清屏 WriteCommandLCM(0x06,1); //数据读写操作后,AC自动增一;画面不动 WriteCommandLCM(0x0c,1); //显示开关为开,光标关,闪烁关 CLOSE_SHUMA_LED_DIANZHEN_1302(); } /*LCD1602:显示一个字符*/ void DisplayOneChar(uchar X,uchar Y,uchar DData) { Y&=1; //Y和0000 0001与,之后只保留0~1 X&=15; //X和0000 1111与,之后只能保留,0~15 if(Y)X|=0x40; //如果是第二行,则X和0100 0000或操作 X|=0x80; //X和1000 0000或操作,高位置1 WriteCommandLCM(X,0); //为何不判断忙不忙就写数据呢? WriteDataLCM(DData); } /*LCD1602:显示一个字符串*/ void DisplayOneString(uchar X,uchar Y,uchar *s) { Y&=1; //Y和0000 0001与,之后只保留0~1 X&=15; //X和0000 1111与,之后只能保留,0~15 if(Y)X|=0x40; //如果是第二行,则X和0100 0000或操作 X|=0x80; //X和1000 0000或操作,高位置1 WriteCommandLCM(X,0); //为何不判断忙不忙就写数据呢? while(*s) {WriteDataLCM(*s); s++; } } /*LCD1602:显示倾斜角度转换后数据*/ void Display_CONVERSION_DATA_Angle(uchar C) { switch(C) { case 0 : DisplayOneChar(6,0,'X');break;//X轴 case 1 : DisplayOneChar(6,0,'Y');break;//X轴 case 2 : DisplayOneChar(6,0,'Z');break;//X轴 default : break; } DisplayOneChar(7,0,':'); DisplayOneChar(9,0,Bai); if(Bai>=0x3A||Bai<=0x30) DisplayOneChar(9,0,' '); DisplayOneChar(10,0,Shi); DisplayOneChar(11,0,Ge); DisplayOneChar(12,0,'.'); DisplayOneChar(13,0,Shi_Fen); DisplayOneChar(14,0,Bai_Fen); DisplayOneChar(15,0,0xDF); } void Display_CONVERSION_DATA_JIASUDU(uchar C) { switch(C) { case 0 : DisplayOneChar(6,0,'X');break;//X轴 case 1 : DisplayOneChar(6,0,'Y');break;//X轴 case 2 : DisplayOneChar(6,0,'Z');break;//X轴 default : break; } DisplayOneChar(7,0,':'); DisplayOneChar(9,0,Wan); DisplayOneChar(10,0,Qian); DisplayOneChar(11,0,Bai); DisplayOneChar(12,0,Shi); DisplayOneChar(13,0,Ge); DisplayOneChar(14,0,'.'); DisplayOneChar(15,0,Shi_Fen); } /*LCD1602:显示x/y/z轴加速度*/ void Display_x_y_z(unsigned char C,uint yanshi) //C=0、1、2分别对应x、y、z { double temp; DisplayOneString(0,0,"JSUDU "); if(Dis_Data[C]<0) { Dis_Data[C]=-Dis_Data[C]; DisplayOneChar(8,0,'-'); //显示正负符号位 } else DisplayOneChar(8,0,' '); //显示+ temp=((float)Dis_Data[C])*3.9; //计算数据和显示,查考ADXL345快速入门第4页 CONVERSION_JIASUDU(temp); //转换出显示需要的数据 Display_CONVERSION_DATA_JIASUDU(C); DisplayOneString(0,1,"mg/s2"); delay(yanshi); } /*LCD1602:显示x/y/z三维倾度*/ void DisplayAngle(uchar C,uint yanshi ) //C=0、1、2分别为X轴、Y轴、Z轴倾角度数 { float a,b,Tem,Angle; DisplayOneString(0,0,"ANGLE ") ; switch(C) { case 0 : a=Dis_Data[1]*Dis_Data[1]+Dis_Data[2]*Dis_Data[2]; Tem=Dis_Data[0];break;//X轴 case 1 : a=Dis_Data[0]*Dis_Data[0]+Dis_Data[2]*Dis_Data[2]; Tem=Dis_Data[1];break;//y轴 case 2 : a=Dis_Data[0]*Dis_Data[0]+Dis_Data[1]*Dis_Data[1]; Tem=Dis_Data[2];break;//X轴 default : break; } b=sqrt(a); if(C!=2) Angle=atan2(Tem,b); //*57.29;// 180/3.1416=57.29 else Angle=atan2(b,Tem); if(Angle<0){Angle=-Angle;DisplayOneChar(8,0,'-');} //显示正负符号位 else DisplayOneChar(8,0,' '); //显示空格 Angle*=180/3.1415926; CONVERSION_Angle(Angle); Display_CONVERSION_DATA_Angle(C); DisplayOneString(0,1," "); delay(yanshi); } void InitUART (void) { SCON = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收 TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit 重装 TH1 = 0xFD; // TH1: 重装值 9600 波特率 晶振 11.0592MHz TR1 =TR0= 1; // TR1: timer 1 打开 EA = 0; //打开总中断 ES = 0; //打开串口中断 } /*MCU初始化函数*/ void MCU_Initialize() { uchar devid; delay(500); //上电延时 InitUART(); InitLcd(); //液晶初始化ADXL345 DisplayOneString(0,0,"ADXL345") ; Init_ADXL345(); //初始化ADXL345 devid=Single_Read_ADXL345(0X00); //读出的数据为0XE5,表示正确, while(devid!=0xe5)DisplayOneString(6,1,"WRONG"); if(devid==0xe5)DisplayOneString(6,1,"RIGHT"); } /*------------------------------------------------ 发送一个字节 ------------------------------------------------*/ void SendByte(unsigned char dat) { SBUF = dat; while(!TI); TI = 0; } /*------------------------------------------------ 发送一个字符串 ------------------------------------------------*/ void SendStr(unsigned char *s) { while(*s!=' |