您当前的位置: 首页 >  单片机

咸鱼弟

暂无认证

  • 1浏览

    0关注

    165博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

基于单片机倾角检测仪设计分享

咸鱼弟 发布时间:2022-07-15 22:49:38 ,浏览量:1

目录

【功能介绍】

【原理图】

【PCB】 

【实物图】

【元器件清单】

【源代码】

【参考资料】

【参考文献】

【功能介绍】

本设计利用51单片机为主控系统,采用三轴加速度传感器ADXL345进行倾角测量,可以实现两大功能:

  • 实时显示当前测量的角度值;
  • 可以设置角度报警值,到达设定角度进行报警功能。
【原理图】

        原理图中包含单片机最小系统,按键电路,显示模块,电源模块,蜂鸣器模块,倾角检测模块等;如需详细资料可私信作者或加微信biyezhan007

【PCB】 

【实物图】

【元器件清单】 10uf电解电容130pf瓷片电容23mm 红色led灯1小电源接口1自锁开关1自锁按键74针排针1LCD1602液晶显示屏+16P插座18550 三极管15V 有源蜂鸣器1103排阻13K电阻11K电阻210K电阻3ADXL345模块+2*5P插座1STC89C52 单片机+DIP40插座112M晶振1 【源代码】
#include  				 //头文件调用
#include "ADXL345.h"			 //调用倾角传感器的控制程序函数
#include "LCD1602.h"			 //调用LCD1602 的显示控制函数
#include "eeprom52.h"			 //调用LCD1602 的显示控制函数


#define   uchar unsigned char  //简化宏定义
#define   uint unsigned int	   //简化宏定义

sbit Key_1=P1^0;		//校零按键定义IO口
sbit Key_2=P1^1;		//绝对校零按键定义IO口

sbit Key_3=P1^2;		//暂停显示控制按键

sbit Key_4=P1^3;
sbit Key_5=P1^4;
sbit Key_6=P1^5;


sbit Beep=P2^3;		 //蜂鸣器标志位

bit  angle_flag=0;	 //判断处于绝对角度还是相对角度	,angle_flag=0绝对角度显示 Absolute angle、    =1相对显示	  relative angle


int xDat,yDat,zDat;		//倾角度传感器的暂存数据变量
int x,y,z;				//角度数据滤波计算暂存变量
int xNum,yNum,zNum;		//角度数据滤波计算暂存变量
int ShowDatx,ShowDaty,ShowDatz;	 //滤波后的角度数据变量
bit SysError,key1,key2,key3,key4,key5,key6,SysMode;  //系统错误标志位,按键控制3个标志位,系统显示状态标志位
uint ButtonTime=0;			//按键等待延时变量

int AngleDat,Dat1AngleDat;  //实时角度值暂存变量
int AngleDat_value=0;

float AngleDatx,CalibrationDat;	  //实际角度值、校准角度值

uchar state,ms;		 //数据显示变量,定时变量
bit s1,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个数
// 例如数据257           257/256=1        257%256=1    ,这就存进去两个1,读取的时候,将高位数据乘以256加低位数据,还原数据

*/




//按键处理函数,平常按键处理是,判断按键按下,延时消抖,再次判断,然后按键死循环等待释放,但是这样会有
//一些问题,就是如果我按键一直按下,不松开,就会一直等待按键释放,程序就会死在那,所以就不用这种按键处理
//换了一种变量判断形势的,比如说我将一个变量在按键不按下的时候等于0,按键按下的时候进行累加,当数值累加到
//一定程度,再次判断按键是否按下,如果按键真的按下,就执行,这种思路
void ButtonCode()		//系统按键控制函数
{
	if(!Key_2)				 //恢复绝对零度的校准值
	{
		CalibrationDat=0;	 //清除校0标志位
		angle_flag=0;
	}
	if(!Key_1)				 //校准零度  记录在绝对零度下的 角度值   (重要)
	{
		if(ButtonTime4)			//变量加到四之后,就进行再次判断按键是否按下
		{
			if(!key1)						//是按键按下,只要这个变量等于1,就执行一次按键操作,并且变量清零,确保执行一次
			{
				key1=1;
				CalibrationDat=AngleDatx;  //校零时记录当前系统的角度值
				angle_flag=1;
			}
		}else key1=0;
		
	}else if(!Key_3)
	{
		if(ButtonTime4)
		{
			if(!key3)
			{
				key3=1;
				SysMode=!SysMode;	  //显示角度锁定状态标志位置位
			}
		}else key3=0;
	}else if(!Key_4)				 //校准零度  记录在绝对零度下的 角度值   (重要)
	{
		if(ButtonTime4)
		{
			if(!key4)
			{
				key4=1;
				state=(state+1)%2;
			}
		}else key4=0;
		
	}else if(!Key_5)
	{
		if(ButtonTime4)
		{
			if(ButtonTime>80)
			{
				ButtonTime=75;
				key5=0;
			}
			if(!key5)
			{
				key5=1;
				if(state==1)
				{
					if(Dat1AngleDat80)
			{
				ButtonTime=75;
				key6=0;
			}
			if(!key6)
			{
				key6=1;
				if(state==1)
				{
					if(Dat1AngleDat>0)
					{
						Dat1AngleDat--;
						SectorErase(0x2000);
						byte_write(0x2000,Dat1AngleDat);
					}
				}
			}
		}else key6=0;
	}else ButtonTime=0;
}


/*
    1602液晶,是常用的显示器件,一共是16个管脚,其中有八个管脚是数据传输管脚,有三个管脚是数据命令使能端管脚,还有两组电源管脚,
其中一组电源管脚是给整个液晶进行供电的,还有一组电源是单纯的背景光电源,还剩下的最后一个管脚是对比度调节管脚,一般接上一个3K电
阻再接地即可。
一般我们用的函数,无非就是  LCD1602_write 和 LCD1602_writebyte
LCD1602_write(x,y);   这个函数括号里面可以填写两个数据,第一个数据只能是 0  1 ,是0就说明第二个数据对液晶来说就是命令,填1就说明
第二个数据对于液晶来说就是要显示的数据。
LCD1602_writebyte();  这个函数里面直接填上要显示的字符串即可,自动进行显示
 
 
*/


void ShowCode()	   //显示控制函数
{
	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); //角度值划分  超限制计算实际角度值	
	}else if(AngleDat            
关注
打赏
1663644285
查看更多评论
0.0377s