/*********用4位数码管对流水线上的产品计数,当数字达到设定的数值时输出高电平控制继电器动作并清零,以便重新开始计数************************/
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
uchar Table[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //数码管段码
uchar Data[4]={0,0,0,0}; //显示初始值
uint CNT; //定义计数器变量
uint MBZhi;
uint MB1,MB2;
//定义目标值变量
uchar key_jia; //定义个位加按键
uchar key_jian; //定义个位减按键
uchar key_jiaB; //定义百位加按键
uchar key_jianB; //定义百位减按键
uchar key_shuru; //定义计数输入按键
uchar key_queren; //定义确认目标值按键
sbit P3_6=P3^6;
sbit scl=P3^1;
sbit sda=P3^3;
void delay()
{
;;;
}
void delay1()
{
uchar i,j;
uchar k=10;
for(i=k;i>0;i--);
for(j=110;j>0;j--);
}
void chushihua() //初始化
{
sda=1;
scl=1;
}
void start()
{ //启动信号
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
}
void stop()
{ //停止信号
sda=0;
delay();
scl=1;
delay();
sda=1;
delay();
}
void ack() //应答信号
{
uchar i;
scl=1;
if((sda==1)&&(i<250))
i++;
scl=0;
delay();
}
void noack() //无应答
{
sda=1;
delay();
scl=0;
delay();
scl=1;
delay();
scl=0;
delay();
}
void write_byte(uchar date) //写字节
{
uint i;
scl=0;
for(i=0;i<8;i++)
{
if(date&0x80)
{
sda=1;
}
else
{
sda=0;
}
date=date<<1;
scl=1;
delay();
scl=0;
delay();
}
sda=1;
delay();
}
uchar read_byte() //读字节
{
uchar i;
uchar date=0x00;
scl=0;
delay();
sda=1;
delay();
sda=1;
delay();
for(i=0;i<8;i++)
{
scl=1;
delay();
date=date<<1;
if(sda)
{
date++;
}
scl=0;
delay();
}
return date;
}
void xie(uchar add,uchar date) //写数据
{
start();
write_byte(0xa0);
ack();
write_byte(add);
ack();
write_byte(date);
ack();
stop();
}
uchar du(uchar t) //读数据
{
uchar k;
start();
write_byte(0xa0);
ack();
write_byte(t);
ack();
start();
write_byte(0xa1);
ack();
k=read_byte();
noack();
stop();
return k;
}
/**************延时函数*****************************/
void Delay(uint i)
{
uint j;
for(;i!=0;i--)
{
for(j=500;j!=0;j--){;}
}
}
/*****************数码管显示函数*********************/
void Display(uchar *p) //动态显示函数,指针变量p为待显示的数组名
{
uchar i,sel=0xf7; //i是循环次数0~3变化,sel用来选中数码管那个亮的
for(i=0;i<4;i++)
{
P2=sel; //开sel对于的数码管,使之点亮
P0=Table[p[i]]; //取数组中各个数对应的显示段码送给P0口
Delay(1); //延时1ms左右的时间,时间过长会出现逐个点亮的效果
sel=(sel>>1)|0xf0; //右移1位,高位置1,准备点亮下一个数码管
}
}
/********************数据处理函数********************/
void Process(uint i,uchar *p)
{
p[0]=i/1000; //取i的千位,保存到数组p0中
i=i%1000;
p[1]=i/100;
i=i%100; //取i的百位,保存到p1中
p[2]=i/10;
i=i%10; //取i的十位,保存到p2中
p[3]=i; //取i的个位,保存到p3中
}
/**********************按键读取函数********************/
void Get_key(void)
{
while((P1&0x01)==0) //如果P1.0口有按键按下表示个位加按键有输入
{
key_jia=1;
Display(Data);
}
while((P1&0x02)==0) // 检测个位减按键的输入
{
key_jian=1;
Display(Data);
}
while((P1&0x04)==0) //检测百位加按键的输入
{
key_jiaB=1;
Display(Data);
}
while((P1&0x08)==0) //检测百位减按键的输入
{
key_jianB=1;
Display(Data);
}
while((P1&0x10)==0) //检测确认按键的输入
{
key_queren=1;
Display(Data);
}
while((P1&0x80)==0) //检测计数输入按键的输入
{
key_shuru=1;
Display(Data);
}
}
/**************************按键处理函数**********************/
void keyproc(void)
{
Get_key();
if(key_jia==1) //个位加按键按下后的操作处理
{
if(CNT!=9999)
{
CNT=CNT+1;
key_jia=0;
}
else
CNT=0;
key_jia=0;
}
if(key_jian==1) //个位减按键按下后的操作处理
{
if(CNT!=0)
{
CNT=CNT-1;
key_jian=0;
}
else
CNT=9999;
key_jian=0;
}
if(key_jiaB==1) //百位加按键按下后的操作处理
{
if(CNT<9900)
{
CNT=CNT+100;
key_jiaB=0;
}
else
CNT=CNT-9900;
key_jiaB=0;
}
if(key_jianB==1) //百位减按键按下后的操作处理
{
if(CNT<100)
{
CNT=CNT+9900;
key_jianB=0;
}
else
CNT=CNT-100;
key_jianB=0;
}
if(key_queren==1) //确认按键按下后的操作处理
{
MBZhi=CNT;
CNT=0;
MB1=MBZhi/256;
MB2=MBZhi%256;
xie(10,MB1);
delay1();
xie(20,MB2);
key_queren=0;
}
if(key_shuru==1) //计数输入 按键按下后的操作处理
{
if(CNT==MBZhi) //如果实际计数的值达到目标设定值,则计数器从1开始重新计数,P3口输出反电位
{
CNT=1;
P3_6=~P3_6;
key_shuru=0;
}
else if(CNT<MBZhi)
{
CNT=CNT+1;
key_shuru=0;
}
}
}
/***********************************主函数*****************************/
void main(void)
{
chushihua();
MB1=du(10);
delay1();
MB2=du(20);
MBZhi=MB1*256+MB2;
while(1)
{
keyproc();
Process(CNT,Data);
Display(Data);
}
}
评论0