数字倾角测量仪设计-_第1页
数字倾角测量仪设计-_第2页
数字倾角测量仪设计-_第3页
数字倾角测量仪设计-_第4页
数字倾角测量仪设计-_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

数字式倾角测量仪设计摘要现如今,技术的不断深化,数字式倾角测量仪在生活当中应用范围越来越广,它的主要功能是检测旋转的角度和角速度。在传统的数字式倾角测量仪设计当中,由于成本过高以及体积的问题,导致其在消费电子当中的应用不是特别广泛。本文设计的数字式倾角测量仪目的是为了让人们使用和控制变得更加便捷。利用STC89C52作为核心,数字信号则使用液晶显示模块,加速传感器ADXL345用来检测倾角,然后利用电路使电脑显示数据,这样就可以得出物体倾斜的角度。经过多次测试,设计最终能够实时显示绝对角度与相对角度测量数据、超限报警和预警值修改,而且该设计测量范围为-180度至180度,与传统设计相比测量更智能,范围更大,而且使用简单,携带方便,能耗低,适用范围也更加广泛。关键词:STC89C52,ADXL345,倾角测量,智能目录21574摘要 附录A原理图附录B源程序#include<reg52.H> //头文件调用#include"ADXL345.h" //调用倾角传感器的控制程序函数#include"LCD1602.h" //调用LCD1602的显示控制函数#include"eeprom52.h" //调用LCD1602的显示控制函数#defineucharunsignedchar//简化宏定义#defineuintunsignedint //简化宏定义sbitKey_1=P1^0; //校零按键定义IO口sbitKey_2=P1^1; //绝对校零按键定义IO口sbitKey_3=P1^2; //暂停显示控制按键sbitKey_4=P1^3;sbitKey_5=P1^4;sbitKey_6=P1^5;sbitBeep=P2^3; //蜂鸣器标志位bitangle_flag=0; //判断处于绝对角度还是相对角度 ,angle_flag=0绝对角度显示Absoluteangle、=1相对显示 relativeangleintxDat,yDat,zDat; //倾角度传感器的暂存数据变量intx,y,z; //角度数据滤波计算暂存变量intxNum,yNum,zNum; //角度数据滤波计算暂存变量intShowDatx,ShowDaty,ShowDatz; //滤波后的角度数据变量bitSysError,key1,key2,key3,key4,key5,key6,SysMode;//系统错误标志位,按键控制3个标志位,系统显示状态标志位uintButtonTime=0; //按键等待延时变量intAngleDat,Dat1AngleDat;//实时角度值暂存变量intAngleDat_value=0;floatAngleDatx,CalibrationDat; //实际角度值、校准角度值ucharstate,ms; //数据显示变量,定时变量bits1,Beep1; //数据闪烁标志位,蜂鸣器报警标志位/*无论是什么单片机,只要是用内部存储区域EEPROM基本使用都是这样关于内部存储区,EEPROM,不同的单片机使用流程基本一致,单片机内部有很多存储单元,或者说扇区,每一个扇区下面有很多地址,数据就是存储在这些地址下面的。存储函数的程序都是官方提供好的,这些程序,咱们只需要用三个,一个是扇区擦除函数,一个是数据写函数,还有一个就是数据读取函数。扇区擦除函数使用哪个扇区,先对那个扇区进行擦,函数里填写要擦除扇区的首地址例如SectorErase(0x2000);就是说擦除首地址为0x2000的扇区数据数据存储扇区擦除之后,就可以使用这个扇区下的地址进行存储数据例如byte_write(0x2000,123);就是说将123存储在0x2000地址下数据读取直接调用即可,例如Dat=byte_read(0x2000);就是说将0x2000地址下的数据读取出来给Dat另外//51单片机存储区域是8位的,也就是说能够存下的最大数据是255,而我们存的数据一旦大于256就会出现一些问题//所以,如果您的设计需要存储的数据大于256,那就把数据拆开存/256得到高位%256得到低位,之所以是256,是因为0-255,256个数//例如数据257257/256=1257%256=1,这就存进去两个1,读取的时候,将高位数据乘以256加低位数据,还原数据*///按键处理函数,平常按键处理是,判断按键按下,延时消抖,再次判断,然后按键死循环等待释放,但是这样会有//一些问题,就是如果我按键一直按下,不松开,就会一直等待按键释放,程序就会死在那,所以就不用这种按键处理//换了一种变量判断形势的,比如说我将一个变量在按键不按下的时候等于0,按键按下的时候进行累加,当数值累加到//一定程度,再次判断按键是否按下,如果按键真的按下,就执行,这种思路voidButtonCode() //系统按键控制函数{ if(!Key_2) //恢复绝对零度的校准值 { CalibrationDat=0; //清除校0标志位 angle_flag=0; } if(!Key_1) //校准零度记录在绝对零度下的角度值(重要) { if(ButtonTime<1000)ButtonTime++; //变量累加 if(!Key_1&&ButtonTime>4) //变量加到四之后,就进行再次判断按键是否按下 { if(!key1) //是按键按下,只要这个变量等于1,就执行一次按键操作,并且变量清零,确保执行一次 { key1=1; CalibrationDat=AngleDatx;//校零时记录当前系统的角度值 angle_flag=1; } }elsekey1=0; }elseif(!Key_3) { if(ButtonTime<1000)ButtonTime++; if(!Key_3&&ButtonTime>4) { if(!key3) { key3=1; SysMode=!SysMode; //显示角度锁定状态标志位置位 } }elsekey3=0; }elseif(!Key_4) //校准零度记录在绝对零度下的角度值(重要) { if(ButtonTime<1000)ButtonTime++; if(!Key_4&&ButtonTime>4) { if(!key4) { key4=1; state=(state+1)%2; } }elsekey4=0; }elseif(!Key_5) { if(ButtonTime<1000)ButtonTime++; if(!Key_5&&ButtonTime>4) { if(ButtonTime>80) { ButtonTime=75; key5=0; } if(!key5) { key5=1; if(state==1) { if(Dat1AngleDat<180) { Dat1AngleDat++; SectorErase(0x2000); byte_write(0x2000,Dat1AngleDat); } } } }elsekey5=0; }elseif(!Key_6) { if(ButtonTime<1000)ButtonTime++; if(!Key_6&&ButtonTime>4) { if(ButtonTime>80) { ButtonTime=75; key6=0; } if(!key6) { key6=1; if(state==1) { if(Dat1AngleDat>0) { Dat1AngleDat--; SectorErase(0x2000); byte_write(0x2000,Dat1AngleDat); } } } }elsekey6=0; }elseButtonTime=0;}/*1602液晶,是常用的显示器件,一共是16个管脚,其中有八个管脚是数据传输管脚,有三个管脚是数据命令使能端管脚,还有两组电源管脚,其中一组电源管脚是给整个液晶进行供电的,还有一组电源是单纯的背景光电源,还剩下的最后一个管脚是对比度调节管脚,一般接上一个3K电阻再接地即可。一般我们用的函数,无非就是LCD1602_write和LCD1602_writebyteLCD1602_write(x,y);这个函数括号里面可以填写两个数据,第一个数据只能是01,是0就说明第二个数据对液晶来说就是命令,填1就说明第二个数据对于液晶来说就是要显示的数据。LCD1602_writebyte();这个函数里面直接填上要显示的字符串即可,自动进行显示*/voidShowCode() //显示控制函数{ if(ShowDaty>=0) //判断当前系统设备当前角度处于正半轴还是负半轴 //计算绝对零度时的角度数据 { if(ShowDatz>=0) //判断当前角度是否为0°-90°/还是90°-180°的饭 { AngleDatx=(float)ShowDaty*90/257; //计算当前角度值0-90(当前角度=Y周角度数据*90°/Y轴最大90°时对应的角度数据) }else { AngleDatx=((float)2570-ShowDaty)*90/257+900;//计算当前角度值90-180(当前角度=Y周角度数据*90°/Y轴最大90°时对应的角度数据+90°)- } }else { if(ShowDatz>=0) //判断当前角度是否为-0°→-90°/还是-90°→-180°的饭 { AngleDatx=(float)ShowDaty*90/257; //计算当前角度值0--90(当前角度=Y周角度数据*90°/Y轴最大90°时对应的角度数据) }else { AngleDatx=(float)((ShowDaty*-1)-2570)*90/257-900; //计算当前角度值90-180(当前角度=Y周角度数据*90°/Y轴最大90°时对应的角度数据-90°)- } } ButtonCode(); //调用按键控制程序 AngleDatx=AngleDatx-CalibrationDat;//零点校准部分程序 if(AngleDatx>1800) //角度值划分超限制计算实际角度值 { AngleDatx=-1800+(AngleDatx-1800);//角度值划分超限制计算实际角度值 }elseif(AngleDat<-1800) { AngleDatx=1800+(AngleDatx+1800);//角度值划分超限制计算实际角度值 } AngleDat=(int)AngleDatx;//赋值当前角度值并显示 if(state==0) { LCD1602_write(0,0x80); //819590-90 if(angle_flag==0) LCD1602_writebyte("Absoluteangle"); else LCD1602_writebyte("Relativeangle"); LCD1602_write(0,0xC0); //显示到第二行 LCD1602_writebyte("DAT:"); //显示当前角度值 if(SysMode==0) { AngleDat_value=AngleDat; if(AngleDat<0) //如果角度为负数 { LCD1602_writebyte("-"); //显示对应的数据 LCD1602_write(1,0x30+AngleDat*-1/1000%10); LCD1602_write(1,0x30+AngleDat*-1/100%10); LCD1602_write(1,0x30+AngleDat*-1/10%10); LCD1602_writebyte("."); LCD1602_write(1,0x30+AngleDat*-1%10); }else { //如果角度为正数 LCD1602_writebyte(""); LCD1602_write(1,0x30+AngleDat/1000%10); //显示对应的数据 LCD1602_write(1,0x30+AngleDat/100%10); LCD1602_write(1,0x30+AngleDat/10%10); LCD1602_writebyte("."); LCD1602_write(1,0x30+AngleDat%10); } LCD1602_write(1,0xdf); //单位显示符号 if((Dat1AngleDat*10<AngleDat||Dat1AngleDat*-10>AngleDat)&&Dat1AngleDat!=0)Beep1=1; elseBeep1=0; } else { if(AngleDat_value<0) //如果角度为负数 { LCD1602_writebyte("-"); //显示对应的数据 LCD1602_write(1,0x30+AngleDat_value*-1/1000%10); LCD1602_write(1,0x30+AngleDat_value*-1/100%10); LCD1602_write(1,0x30+AngleDat_value*-1/10%10); LCD1602_writebyte("."); LCD1602_write(1,0x30+AngleDat_value*-1%10); }else { //如果角度为正数 LCD1602_writebyte(""); LCD1602_write(1,0x30+AngleDat_value/1000%10); //显示对应的数据 LCD1602_write(1,0x30+AngleDat_value/100%10); LCD1602_write(1,0x30+AngleDat_value/10%10); LCD1602_writebyte("."); LCD1602_write(1,0x30+AngleDat_value%10); } } LCD1602_write(0,0xC0+11); if(SysMode==0) //显示系统状态 { LCD1602_writebyte("ON"); }else { LCD1602_writebyte("OFF"); } }else { LCD1602_write(0,0x80); LCD1602_writebyte("AlarmValue:"); if(state==1&&s1==1) { LCD1602_writebyte(""); }else { LCD1602_write(1,0x30+Dat1AngleDat/100%10); //显示对应的数据 LCD1602_write(1,0x30+Dat1AngleDat/10%10); LCD1602_write(1,0x30+Dat1AngleDat%10); } LCD1602_write(1,0xdf); //单位显示符号 LCD1602_write(0,0xC0); LCD1602_writebyte(""); }}voidinterrupt_Init(void){ TMOD=0x01; //定义两个定时器 TL0=0x00; //设置定时初值 TH0=0x4C; //设置定时初值 EA=1;//开总中断 ET0=1; TR0=1; }voidmain() //系统主程序{ ucharIDDat,cs; interrupt_Init(); LCD1602_cls(); //系统初始化,液晶显示初始化 Dat1AngleDat=byte_read(0x2000); if(Dat1AngleDat>180||Dat1AngleDat<0) { Dat1AngleDat=45; SectorErase(0x2000); byte_write(0x2000,Dat1AngleDat); } Init_ADXL345(); //初始化ADXL345 IDDat=Single_Read_ADXL345(0X00); //读出的数据为0XE5,表示正确 if(IDDat!=0XE5) SysError=1; //判断传感器是否正常 elseSysError=0; while(1) //循环 { if(SysError==0)

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论