设计操作流程及要求:
1、当第一次给单片机上电时,功能数码管显示1,时间设置数码管按照由I2C中读取的值进行显示。此时用户可对电磁阀的得电时间、卸载时间和能耗制动时间进行设置。
2、数码管在显示数据的过程中,I2C不但要对按键不断变化的数据进行实时的存储,而且要能够被及时的读出并显示在数码管上。
3、用户在进行按键操作时,按键与按键之间的操作不应过快,以便给CPU一定的处理时间。
4、显示时间设置的数码管当显示0时对应的设置时间是1s,当显示1时对应的设置时间是2,当显示3时……当显示9时,对应的时间设置是10s。
5、在脚踏开关的中断处理的过程中,先是电磁阀的得电,延时一定时间,其次开始卸载,卸载完毕后,电动机能耗制动,再延时一定的时间(由设置决定),关闭能耗制动和电磁阀的得电。此时完成一次卸载操作。
6、各种时间设置完毕后,当脚踏开关有动作时,产生的中断能够及时的得到处理。
7、过电保护的中断过程中,当产生中断时,各种按键动作均无效,且数码管不再显示任何数据。
程序如下:
首先是新建一个.h的文件,文件名为24LC00.h,编写#include"24LC00.h"的头文件,程序如下:
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit sda=P1^6;
sbit scl=P1^7;
uchar a;
void start() //开始信号
{
sda=1;
_nop_();
scl=1;
_nop_();
sda=0;
_nop_();
}
void stop() //停止
{
sda=0;
_nop_();
scl=1;
_nop_();
sda=1;
_nop_();
}
void respons() //应答
{
uchar i;
scl=1;
_nop_();
while((sda==1)&&(i<250))i++;
scl=0;
_nop_();
}
void write_byte(uchar date)
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
scl=0;
_nop_();
sda=CY;
_nop_();
scl=1;
_nop_();
}
scl=0;
_nop_();
sda=1;
_nop_();
}
uchar read_byte()
{
uchar i,k;
scl=0;
_nop_();
sda=1;
_nop_();
for(i=0;i<8;i++)
{
scl=1;
_nop_();
k=(k<<1)|sda;
scl=0;
_nop_();
}
return k;
}
void delay(uchar y)
{
uchar x,z;
for(x=0;x<y;x++)
for(z=0;z<109;z++);
}
void write_add(uchar address,uchar date)
{
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
write_byte(date);
respons();
stop();
}
uchar read_add(uchar address)
{
uchar date;
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
start();
write_byte(0xa1);
respons();
date=read_byte();
stop();
return date;
}
头文件编写完毕后,开始写主函数部分,程序如下:
#include<reg52.h>
#include"24LC00.h"
sbit func=P1^0;
sbit plus=P1^1;
sbit dec=P1^2;
sbit engine=P1^3;
sbit drag=P1^4;
sbit valve=P1^5;
uchar a,b,c,d,num0=1;
uchar i,j,k,flag;
char num1,num2,num3;
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
/*****************程序的初始化**********************/
void init()
{
TMOD=0X01; //设置定时器0为定时模式,且工作于方式1
TH0=(65536-50000)/256;
TL0=(65536-50000)%256; //定时50ms的计数初值
engine=0;
drag=0;
valve=0;
P0=~0xf9; //功能数码管上初始化为电磁阀设置
P2=~read_add(1); //数码管2上显示电磁阀的设定时间
IT0=1;
IT1=1; //外部中断0和1均设置为跳沿触发
IP=0x07;
EX0=1; //开外部中断0
ET0=1; //开定时器中断0
EX1=1; //开外部中断1
EA=1; //开中断
}
/*****************************延时函数********************************/
void delay1(uint y)
{
uint x,z;
for(x=0;x<y;x++)
for(z=0;z<109;z++);
}
/**********************************读键扫描程序************************************/
void key_scan()
{
if(func==0) //功能键是否按下?
{
delay(5); //软件消抖
if(func==0) //检测按键是否真的被按下
{
num0++;
if(num0==4)
num0=1; //功能键只显示三种时间的设置
}
while(!func); //功能键是不是还在被按下
P0=~table[num0]; //功能数值在数码管1上显示
P2=~read_add(num0); //功能键相对应的时间设置显示在数码管2上
delay(1);
}
if(num0!=0)
{
switch(num0)
{
case 1: //功能键显示1时,设置电磁阀得电时间
{
if(plus==0) //是加法键按下么? 是
{
delay(5); //延时消抖
if(plus==0) //确认加键被按下
{
num1++; //键值加1
if(num1==10)
num1=0; //键值为10时,清零
while(!plus); //按键松手检测
P2=~table[num1]; //显示键值
write_add(1,table[(unsigned char) num1]); //存储键值
}
}
if(dec==0) //是减法键按下么?是
{
delay(5); //延时消抖
if(dec==0) //确认减法键被按下
{
num1--; //键值减1
if(num1==-1)
num1=9; //当键值为-1时,清9
while(!dec); //按键松手检测
P2=~table[num1]; //显示键值
write_add(1,table[(unsigned char) num1]); //存储键值
}
}
}
break;
case 2: //功能键显示2时,设置卸载时间
{
if(plus==0) //是加法键按下么? 是
{
delay(5); //延时消抖
if(plus==0) //确认加键被按下
{
num2++; //键值加1
if(num2==10)
num2=0; //键值为10时,清零
while(!plus); //按键松手检测
P2=~table[num2]; //显示键值
write_add(2,table[(unsigned char) num2]); //存储键值
}
}
if(dec==0) //是减法键按下么?是
{
delay(5); //延时消抖
if(dec==0) //确认减法键被按下
{
num2--; //键值减1
if(num2==-1)
num2=9; //当键值为-1时,清9
while(!dec); //按键松手检测
P2=~table[num2]; //显示键值
write_add(2,table[(unsigned char) num2]); //存储键值
}
}
}
break;
case 3: //功能键显示3时,设置能耗制动时间
{
if(plus==0) //是加法键按下么? 是
{
delay(5); //延时消抖
if(plus==0) //确认加键被按下
{
num3++; //键值加1
if(num3==10)
num3=0; //键值为10时,清零
while(!plus); //按键松手检测
P2=~table[num3]; //显示键值
write_add(3,table[(unsigned char) num3]); //存储键值
}
}
if(dec==0) //是减法键按下么?是
{
delay(5); //延时消抖
if(dec==0) //确认减法键被按下
{
num3--; //键值减1
if(num3==-1)
num3=9; //当键值为-1时,清9
while(!dec); //按键松手检测
P2=~table[num3]; //显示键值
write_add(3,table[(unsigned char) num3]); //存储键值
}
}
}
break;
}
}
}
/****************************主程序*********************************/
void main()
{
init();
while(1)
{
key_scan(); //上电后开始读键
if(flag==1)
{
flag=0;
valve=1; //电磁阀开始得电
b=read_add(0x01); //读电磁阀延时时间的基数
TR0=1; //开启1s的定时中断
for(i=0;i<=b;i++)
{
while(a<=20); //定时1s未到,在此等待
a=0;
}
TR0=0;
engine=1; //开始卸载
c=read_add(0x02); //读卸载延时的基数
TR0=1;
for(j=0;j<=c;j++) //根据卸载时间的设置,延时相应的时间
{
while(a<=20);
a=0;
}
TR0=0; //延时结束后,关闭定时器
engine=0; //停止卸载
drag=1; //开始能耗制动
d=read_add(0x03); //读能耗制动时间的基数
TR0=1;
for(k=0;k<=d;k++) //根据能耗制动时间的设置,延时相应的时间
{
while(a<=20);
a=0;
}
TR0=0; //能耗制动的时间
drag=0; //关闭能耗制动
valve=0; //电磁阀失电
EX1=1; // 开外部中断1
}
}
}
/****************************外部中断0的服务程序**********************************/
void wai0() interrupt 0
{
IE=0; //关闭所有中断
engine=0;
drag=0;
valve=0; //电磁阀,电动机和能耗制能均不再工作
P0=0;
P2=0; //关闭两个数码管的显示
scl=0;
sda=0; //I2C中的数据不再发生任何变化
}
/***************************定时器0的中断服务程序********************************/
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
a++; //当a=20时定时1秒
}
/****************************外部中断1的服务程序**********************************/
void wai1() interrupt 2
{
EX1=0; //进入外部中断1后,关外部中断1
flag=1;
}