倾斜角测量仪程序
#include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义 #include
#include
#include
#include
#include
#include
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P0
#define MEAS 0x00 //测量模式
#define RWTR 0x08 //读写温度数据寄存器
#define STX 0x0E //x通道自检
#define STY 0x0F //Y通道自检
#define RDAX 0x10 //读X通道加速度值
#define RDAY 0x11 //读Y通道加速度值
sbit RS = P2^4; //定义端口
sbit RW = P2^5;
sbit EN = P2^6;
sbit SPK=P2^0;
sbit SCK=P1^7;
sbit MISO=P1^6;
sbit MOSI=P1^5;
sbit CSB=P1^4;
unsigned char frq;
sbit P0_0 = P0^0;
sbit P0_1 = P0^1;
sbit P0_2 = P0^2;
sbit P0_3 = P0^3;
sbit P0_4 = P0^4;
sbit P0_5 = P0^5;
sbit P0_6 = P0^6;
sbit P0_7 = P0^7;
sbit P1_0 = P1^0;
sbit P1_1 = P1^1;
sbit P1_2 = P1^2;
sbit P1_3 = P1^3;
sbit P1_4 = P1^4;
sbit P1_5 = P1^5;
sbit P1_6 = P1^6;
sbit P1_7 = P1^7;
sbit P2_0 = P2^0;
sbit P2_1 = P2^1;
sbit P2_2 = P2^2;
sbit P2_3 = P2^3;
sbit P2_4 = P2^4;
sbit P2_5 = P2^5;
sbit P2_6 = P2^6;
sbit P2_7 = P2^7;
sbit P3_0 = P3^0;
sbit P3_1 = P3^1;
sbit P3_2 = P3^2;
sbit P3_3 = P3^3;
sbit P3_4 = P3^4;
sbit P3_5 = P3^5;
sbit P3_6 = P3^6;
sbit P3_7 = P3^7;
unsigned int SPI_ReadBits(unsigned char n );
void SPI_WriteByte( unsigned char wdata );
void SPI_Start(void);
void SPI_Stop(void);
void SPI_Reset(void);
void SPI_Delay(unsigned char);
unsigned int SPI_GetX( void );
unsigned int SPI_GetY( void );
void SPI_Init( void );
void SPI_Stop( void )
{
SCK = 0;
CSB = 1;
SPI_Delay(10);
}
void SPI_Reset(void)
{
SPI_Stop();
}
void SPI_Delay(unsigned char n)
{
while(n--);
}
void SPI_Start(void)
{
SCK = 0;
CSB = 0;
SPI_Delay(10);
}
//主机写一个BYTE 到器件
//最终状态:CLK = LOW
void SPI_WriteByte( unsigned char wdata )
{
unsigned char i;
for( i = 0 ; i
{
SCK = 0;
SPI_Delay(10);
MOSI = wdata & 0x80;
wdata = wdata
SPI_Delay(10);
SCK = 1;
SPI_Delay(10);
}
SCK = 0;
}
//主机读入N 个比特
//n 限制为16及其以下
//结束状态 CLK = 0
unsigned int SPI_ReadBits( unsigned char n )
{
unsigned int rtemp,i;
MISO = 1;
for( i = 0 ; i
{
rtemp
SPI_Delay(10);
if( MISO == 1 ){
rtemp |= 0x0001;
}else{
rtemp &= 0xFFFE;
}
SCK = 1;
SPI_Delay(10);
SCK = 0;
SPI_Delay(10);
}
return rtemp;
}
//读X 方向角度
unsigned int SPI_GetX( void )
{
unsigned int result;
SPI_Start();
SPI_WriteByte( RDAX );
result = SPI_ReadBits(11);
SPI_Stop();
return result;
}
//读Y 方向角度
unsigned int SPI_GetY( void )
{
unsigned int result;
SPI_Start();
SPI_WriteByte( RDAY );
result = SPI_ReadBits(11);
SPI_Stop();
return result;
}
//SPI测量模式
void SPI_Init( void )
{
SPI_Start();
SPI_WriteByte( MEAS );
SPI_Stop();
}
unsigned char code C[]={'0','1','2','3','4','5','6','7','8','9'};
/*------------------------------------------------
uS 延时函数,含有输入参数 unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M ,精确延时请使用汇编, 大致延时
长度如下 T=tx2+5 uS
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
mS 延时函数,含有输入参数 unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M ,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{
while(t--)
{
//大致延时1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
判忙函数
------------------------------------------------*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
_nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
/*------------------------------------------------
写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com)
{
while(LCD_Check_Busy()); //忙则等待
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
_nop_();
EN_CLR;
}
/*------------------------------------------------
写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data)
{
while(LCD_Check_Busy()); //忙则等待
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();
EN_CLR;
}
/*------------------------------------------------
清屏函数
------------------------------------------------*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*------------------------------------------------
写入字符串函数
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x); //表示第一行
}
else
{
LCD_Write_Com(0xC0 + x); //表示第二行
}
while (*s)
{
LCD_Write_Data( *s);
s ++;
}
}
/*------------------------------------------------
写入字符函数
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
/*------------------------------------------------
角度转化函数
------------------------------------------------*/
float angle_transfer( double result)
{ double angle,f;
f=asin((result-1024)/1638);
angle=f*180/3.14;
return(angle);
}
/*------------------------------------------------
初始化函数
------------------------------------------------*/
void LCD_Init(void)
{
LCD_Write_Com(0x38); /*显示模式设置*/
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08); /*显示关闭*/
LCD_Write_Com(0x01); /*显示清屏*/
LCD_Write_Com(0x06); /*显示光标移动设置*/
DelayMs(5);
LCD_Write_Com(0x0C); /*显示开及光标设置*/
}
/*------------------------------------------------
LCD 显示函数
------------------------------------------------*/
void LCD_Display(unsigned int i,double angle)
{ int m,n,c,d,e,an;
an=(int)(angle*1000);
m=an%10;
LCD_Write_Char(8,i,C[m]);
DelayMs(245);
DelayMs(245);
an=an/10;
n=an%10;
LCD_Write_Char(7,i,C[n]);
DelayMs(245);
DelayMs(245);
an=an/10;
c=an%10;
LCD_Write_Char(6,i,C[c]);
DelayMs(245);
DelayMs(245);
an=an/10;
d=an%10;
LCD_Write_Char(4,i,C[d]);
DelayMs(245);
DelayMs(245);
e=an/10;
LCD_Write_Char(3,i,C[e]);
DelayMs(245);
DelayMs(245);
LCD_Write_Char(5,i,'.');
}
/*------------------------------------------------
定时器初始化子程序
------------------------------------------------*/
void Init_Timer0(void)
{
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
//TH0=0x00; //给定初值
//TL0=0x00;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关打开
}
/*------------------------------------------------
定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
TH0=0xfe; //重新赋值
TL0=frq; //低8位值在主程序中不断累加
SPK=!SPK; //端口电平取反
}
/*------------------------------------------------
报警函数
------------------------------------------------*/
bit Warning(double angle,unsigned char x,unsigned char y)
{
int g;
angle=fabs(angle);
if(angle>20)
{g=0;
LCD_Write_String(x,y,"DANGER!");
while(!P2_0)
{
Init_Timer0(); //初始化定时器
DelayMs(1); //延时1ms ,累加频率值
frq++;
}
}
else
{
LCD_Write_String(x,y," ");
EA=0;
g=1;
}
return(g);
}
/*------------------------------------------------
发送函数
------------------------------------------------*/
void Send(float a )
{
TMOD=0x20;
TL1=0xE6;
TH1=0xE6;
PCON=0x00;
TR1=1;
SCON=0x50; /*串口8位异步收发,波特率可变*/
if(RI=1)
{RI=0;
SBUF=a;
while(TI!=1);
TI=0;
}
}
/*------------------------------------------------
主函数
------------------------------------------------*/
void main(void)
{unsigned int result;
double angle,a,b;
LCD_Init();
LCD_Clear();//清屏
SPI_Reset();
SPI_Delay(1000);
SPI_Init();
SPI_Delay(1000);
while (1)
{
result = SPI_GetX();
angle=angle_transfer(result); a=angle;
Send(a);
P2_0=Warning(angle,9,0); P2_1=Warning(angle,9,0); if(a
{a=fabs(a);
LCD_Write_String(0,0,"X:-"); LCD_Display(0,a); }
else
{LCD_Write_String(0,0,"X:+"); LCD_Display(0,a); }
result = SPI_GetY();
angle=angle_transfer(result); b=angle;
Send(b);
P2_0=Warning(angle,9,1); P2_2=Warning(angle,9,1); if(b
{b=fabs(b);
LCD_Write_String(0,1,"Y:-"); LCD_Display(1,b); }
else
{LCD_Write_String(0,1,"Y:+"); LCD_Display(1,b); }
}
}