#include<reg52.h>
#define WREN 0x06 //x25045设置写允许位
#define WRDI 0x04 //复位写允许位
#define RDSR 0x05 //读状态寄存器
#define WRSR 0x01 //写状态寄存器
#define READ0 0x03 //读操作内部EEPROM页地址0
#define READ1 0x0b //读操作内部EEPROM页地址1
#define WRITE0 0x02 //写操作内部EEPROM页地址0
#define WRITE1 0x0a //写操作内部EEPROM页地址1
#define uchar unsigned char
#define uint unsigned int
#define H 10
#define E 11
#define L 12
#define O 13
#define P 14
#define A 15
#define S1 16
#define S2 17
#define d 19
#define C 20
#define E1 21
sbit CS=P1^0; //x25045片选
sbit SO=P1^1; //x25045输出
sbit SCK=P1^2; //x25045时钟
sbit SI=P1^3; //x25045输入
sbit CLK1=P2^4; //锁存器时钟控制位
sbit CLK2=P2^5;
sbit CLK3=P2^6;
sbit CLK4=P2^7;
sbit key=P1^5; //键盘输入位
sbit busy=P3^2; //AD转换器busy输入信号与INT0相连接
sbit A0=P1^6; //双四选一模拟开关CD4052,通道选择
sbit A1=P1^7;
char code tabled[]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09,
0x91,0x61,0xe3,0x03,0x31,0x11,0x49,0x49,0xfd,0x85,0x63,0x61};//段选数据
char code tablew[8]={0x00,0x02,0x04,0x03,
0x05,0x06,0x07,0x01};//位选数组
char hcun[8]={H,E,L,O,P,A,S1,S2};
//数据缓存数组,存放数码管将要显示的数据,初始为0
char code table2[11]={0xff,0xfe,0xfc,0xf8,0xf0,
0xe0,0xc0,0x80,0x00,0x0e,0x0c};//光柱段选
char code table1[]={0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0,
0xff,0xff,0xff,0xff,0xf7,0xf8};//低四位光柱位选,高四位为CLK都写1,后六个数据位开机程序数据
uint dianya;//AD采集的电压数
uint lc;//仪表量程存储变量
uint gzs,gzg;//光柱显示十位个位参数
int jianzhi=0;//键值全局变量保存键值
int wei=0;//函数dukey()与键扫描disled()的传递变量
uint f;//小数点标志位等于1,2,3有小数点并代表小数点的位置,等于0无小数点
uint f1;//量程范围指示位1为0-9,2为10-99,3为100-999,0为1000-9999
uint t;//通道选择全局变量分别为1,2,3,4
uint z=0;//光柱选择标志等于0不选择,等于1选择
uint zj1=1;//自检标志位等于1选择,等于0不选择
uint a;//a为输入信号类型0-5V,1-5V
uint shangxian,xiaxian;//报警上下限存储变量
uint bj=0;//报警标志位等于0无报警,等于1有报警用于屏蔽光柱
uint hc;//报警回差存储变量
uint bs;//回差标志位用于指示回差
void dukey(); //函数声明
void baojing();
void delay(int x)//延时X毫秒
{
int i,j;
while(x--)
{
for(i=23;i>0;i--)
for(j=1;j>0;j--);
}
}
void delayc(int x)//延时X0.1毫秒
{
int i,j;
while(x--)
{
for(i=2;i>0;i--)
for(j=1;j>0;j--);
}
}
void disled() //数码管显示函数和键盘检测函数
{
int j;
for(j=0;j<8;j++)
{
P2=tablew[j];
if(f==1&&j==4||f==2&&j==5||f==3&&j==6)//小数点标志位用于指示第几位有小数点
{
CLK1=0;
P0=tabled[hcun[j]]-1;
CLK1=1;
}
else
{
CLK1=0;
P0=tabled[hcun[j]];
CLK1=1;
}
switch(j)
{
case 0:wei=0;wei=1;dukey();TR1=1;break;//键盘检测
case 1:wei=0;wei=3;dukey();TR1=1;break;
case 3:wei=0;wei=4;dukey();TR1=1;break;
case 7:wei=0;wei=2;dukey();TR1=1;break;
default:delay(1);break;
}
CLK1=0;
P0=0xff; //数码管消除残影
CLK1=1;
if(bj==0)
{
CLK3=0;
P0=0x0f; //关闭报警输出
CLK3=1;
}
}
}
void gzxiaoyin() //光柱消隐
{
CLK4=0;
P0=0xff;
CLK4=1;
CLK3=0;
P0=0x0f;
CLK3=1;
P2=0xff;
}
void disgz(shiwei,gewei)//光柱显示程序,显示所测模拟量的百分数
{
int i;
for(i=0;i<=shiwei;i++)//显示十位
{
P2=table1[i];
CLK4=0;
P0=table2[8];
CLK4=1;
CLK3=0;
P0=table2[10];
CLK3=1;
delayc(4);
gzxiaoyin();
}
if(gewei<=8) //显示个位
{
P2=table1[shiwei+1];
CLK4=0;
P0=table2[gewei];
CLK4=1;
CLK3=0;
P0=0x0f;
CLK3=1;
delayc(4);
gzxiaoyin();
}
else
{
P2=table1[shiwei+1];
CLK4=0;
P0=table2[8];
CLK4=1;
CLK3=0;
P0=table2[gewei];
CLK3=1;
delayc(4);
gzxiaoyin();
}
}
uchar ReadByte() //从x25045读一个字节
{
bit bData;
uchar ucLoop;
uchar ucData;
for(ucLoop=0;ucLoop<8;ucLoop++)
{
SCK=1;
SCK=0;
bData=SO;
ucData<<=1;
if(bData)
{ ucData|=0x01; }
}
return ucData;
}
void WriteByte(uchar ucData)//向x25045写一个字节
{
uchar ucLoop;
for(ucLoop=0;ucLoop<8;ucLoop++)
{
if((ucData&0x80)==0) //首先写入高位
{SI=0;}
else
{SI=1;}
SCK=0;
SCK=1;
ucData<<=1;
}
}
uchar ReadReg() //读寄存器
{
uchar ucData;
CS=0;
WriteByte(RDSR);
ucData=ReadByte();
CS=1;
return ucData;
}
uchar WriteReg(uchar ucData) //写寄存器
{
uchar ucTemp;
ucTemp=ReadReg();
if((ucTemp&0x01)==1) //最低位为一,说明x25045正在写入中,为忙
return 0;
CS=0;
WriteByte(WREN);//当写入写使能时,cs必须有一个高电平
CS=1;
CS=0;
WriteByte(WRSR);
WriteByte(ucData);
CS=1;
return 1;
}
void WriteEpm(uchar cData,uchar cAddress,bit bRegion)
/* 写入一个字节,cData为写入的数,cAddress为写入地址,bRegion为页 */
{
while((ReadReg()&0x01)==1); //x25045正在写入,为忙
CS=0;
WriteByte(WREN); //当写入写使能时,cs必须有一个高电平
CS=1;
CS=0;
if(bRegion==0)
{ WriteByte(WRITE0);} //写页地址
else
{WriteByte(WRITE1);}
WriteByte(cAddress);
WriteByte(cData);
SCK=0; //
CS=1;
}
uchar ReadEpm(uchar cAddress,bit bRegion)
/* 读入一个字节,cAddress为读入地址,bRegion为页 */
{
uchar cData;
while((ReadReg()&0x01)==1);//x25045正在写入,为忙
CS=0;
WriteByte(WREN); //当写入写使能时,cs必须有一个高电平
CS=1;
CS=0;
if(bRegion==0)
{WriteByte(READ0); }
else
{WriteByte(READ1);}
WriteByte(cAddress);
cData=ReadByte();
SCK=0;
CS=1;
return cData;
}
void dukey() //读键盘将键值保存在全局变量jianzhi中
{
if(key==1) //判断键是否按下
delay(1);
if(key==1)
jianzhi=wei;
TR1=0;
while(key); //判断键是否松开
delay(1);
while(key);
}
void jcl() //键处理程序
{ uint wei1=0,wei2=0,wei3=0,wei4=0,z1;
jianzhi=0;
z=0;//禁止调用光柱
f=0;//清小数点标志位
while(1)//进入HH等待
{
if(jianzhi==1)break;//跳出HH等待回到显示
hcun[0]=18;hcun[1]=0;hcun[2]=0;hcun[3]=18;
hcun[4]=18;hcun[5]=H;hcun[6]=H;hcun[7]=18;//显示等待标记HH
if(jianzhi==3)//按下左键进行查询各参数设置
{
while(1)//查询状态循环
{
if(jianzhi==1)break;//按下ESC退出查询状态进入HH等待状态
if(jianzhi==3)//按左键逐次查询配置信息
{
hcun[4]=18;hcun[5]=C;hcun[6]=C;hcun[7]=18;//显示查询标记CC
hcun[2]=wei4++;//查询标志,记下查询状态
if(wei4>6)
wei4=0;//查询一圈结束清零
if(hcun[2]==4||hcun[2]==5||hcun[2]==6)
f=f1;//当查询4,5,6时,需要有小数点,小数点位置有f1提供
else
f=0;
if(hcun[2]==1)//查询通道号
{
hcun[5]=18;
hcun[6]=18;
hcun[7]=t;
}
if(hcun[2]==2)//查询输入信号类型
{
hcun[5]=a;
hcun[6]=18;
hcun[7]=5;
}
if(hcun[2]==3)//查询量程
{
hcun[4]=lc/1000;
hcun[5]=lc%1000/100;
hcun[6]=lc%100/10;
hcun[7]=lc%10;
}
if(hcun[2]==4)//查询报警上限
{
hcun[4]=shangxian/1000;
hcun[5]=shangxian%1000/100;
hcun[6]=shangxian%100/10;
hcun[7]=shangxian%10;
}
if(hcun[2]==5)//查询报警下限
{
hcun[4]=xiaxian/1000;
hcun[5]=xiaxian%1000/100;
hcun[6]=xiaxian%100/10;
hcun[7]=xiaxian%10;
}
if(hcun[2]==6)//查询报警回差
{
hcun[4]=hc/1000;
hcun[5]=hc%1000/100;
hcun[6]=hc%100/10;
hcun[7]=hc%10;