#include <AT89X51.H> //器件配置文件
#define uchar unsigned char//变量类型的宏定义
#define uint unsigned int
uchar code SEG7[10]={0x03,0x9f,0x25,0x0d,0x99, //0~9的数码管段码
0x49,0x41,0x1f,0x01,0x09};
uchar data cnt[8];//在data区定义8位长度的数组,用来存放计数值
uchar data pre_cnt[8];//在data区定义8位长度的数组,用来存放预置值
sbit drv=P3^4;//定义输出驱动端
bit set_flag;//定义工作标志
bit out_flag;//定义输出标志
bit keydown_flag;//键按下标志
/****************************************************************/
void scan_key(void)//扫描S1~S8键子程序开始
{uchar i,m=0x01;//定义两个字符型局部变量,并赋值0x01给m
P3_6=0;P3_7=1;//禁止发送给显示器,消隐有效
for(i=0;i<8;i++)//循环8次
{
SBUF=255-m;while(!TI);TI=0;//依次发送数据使IC2的输出从右至左的列线为0
if(!P3_5)pre_cnt[i]++;//若检测到P3.5为0,说明某列线送出0时与连接
//该列线的按键被按下,数组中对应的存放单元加1
m<<=1;//m的取值使从右向左的下一条列线为0
}//扫描S1~S8键子程序结束
//----------------------------------------------------------------------------------------
for(i=0;i<8;i++)//循环8次
{if(pre_cnt[i]>9)pre_cnt[i]=0;}//对数组中的8个单元进行调整,其范围为0~9
}
/*************************************************************/
void dis_cnter(void)//显示计数器值子程序开始
{uchar i;//定义字符型局部变量i
P3_7=1;P3_6=1;//消隐有效,允许显示
for(i=0;i<8;i++)//循环8次
{SBUF=SEG7[cnt[i]];while(!TI);TI=0;}//根据8个单元的计数值查表发送显示
P3_7=0;//关闭消隐,正常显示
}//显示计数器值子程序结束
/****************************************************************/
void cnter(void)//计数转换子程序开始
{uchar i;//定义字符型局部变量i
for(i=0;i<7;i++)//循环8次
{if(cnt[i]>9){cnt[i]=0;cnt[i+1]++;}}//若计数器某位值大于9,则该位回0,
//而高位被进位加1
//------------------------------------
if(cnt[7]>9){for(i=0;i<8;i++)cnt[i]=0;}// 若计数器最高位值大于9,则计数器全清0
}//计数转换子程序结束
/******************************************************************/
void pt_cnt(void) //输出控制子程序开始
{
if((cnt[0]==pre_cnt[0])&&(cnt[1]==pre_cnt[1])&&\
(cnt[2]==pre_cnt[2])&&(cnt[3]==pre_cnt[3])&&\
(cnt[4]==pre_cnt[4])&&(cnt[5]==pre_cnt[5])&&\
(cnt[6]==pre_cnt[6])&&(cnt[7]==pre_cnt[7]))//若计数值等于预置值
out_flag=1;//输出标志置1
else out_flag=0;//否则输出标志置0
//=================================================
if(out_flag)drv=0;//若输出标志为1,输出端(P3.4)置0,驱动光耦U2
else drv=1;//否则输出端(P3.4)置1
}//输出控制子程序结束
/**********************************************************/
void main(void)//主程序开始
{IE=0x84;//开放CPU中断,开放外中断1的中断
IT1=1;//置外中断1为边沿触发
while(1)//无限循环
{P3_6=0;P3_7=1;//禁止发送给显示器,消隐有效
SBUF=0x00;while(!TI);TI=0;//向IC2发送0x00,使IC2输出为全0
if((P3&0x24)!=0x24)keydown_flag=1;//检测P3.2、P3.5是否为高电平。
//若不为高电平,说明有键按下,键被按下标志置1
else keydown_flag=0;//否则,键被按下标志置0
//-------------------------------------------------------------------------------
SBUF=0xfe;while(!TI);TI=0;//向IC2发送0xfe
if(!P3_2)set_flag=!set_flag;//若P3.2为0,说明S9键按下,标志set_flag取反
//==================================================
if(!set_flag){cnter();dis_cnter();pt_cnt();delay(100);}
//若标志set_flag为0,调用计数、显示计数、输出控制的子程序
else {scan_key();dis_pre_cnter();delay(10);}
否则标志set_flag为1,调用扫描S1~S8键、显示预置值的子程序
//=====================================================
if(keydown_flag)delay(300);//因有键按下,调用延时300mS子程序,
//以免调整键值的速度过快
}
}//主程序结束
/***************************************************************/
void extern_int1(void) interrupt 2 using 1//外中断1服务子程序
{
cnt[0]++;//计数器的最低位加1
}