#include <reg51.h>
//变量类型别名
typedef unsigned char u8;
typedef unsigned short u16;
//函数声明
void delay_ms(u16 nms); //ms级延时函数
void dig_display(u8 digx,u8 number,bit dot);//单数码管显示函数
void dig_display_all(u16 number);//四数码管显示函数
void exit0_init(void); //外部中断0配置函数
void exit1_init(void); //外部中断1配置函数
//共阴数码管数字显示代码数组,a-g分别接P1.0~P1.6
//0~9显示代码
const u8 Seg_Code[10] = {
0x3f,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F
};
//开关数码管代码
const u8 seg_switch[8] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07
};
//宏定义数码管的号码,便于分辨
#define DIG0 0
#define DIG1 1
#define DIG2 2
#define DIG3 3
/**************************************************
* @function 程序入口函数
* @parameter None
* @return None
* @description
* - 此程序主要执行以下功能
* - ①.配置外部中断0和外部中断1
* - ②.数码管动态扫描显示
***************************************************/
u16 number = 0;//数码管显示全局变量
void main(void)
{
//初始化设备
exit0_init();//初始化外部中断0,设置为低优先级
exit1_init();//初始化外部中断1,设置为高优先级
//后台循环扫描显示数码管,前台接收外部信号,使显示的数字发生变化
while(1)
{
dig_display_all(number);
}
}
/**************************************************
* @function 外部中断0配置函数
* @parameter None
* @return None
* @description
* - 89C51系列-外部中断触发方式只有两种: 下降沿触发和低电平触发
* - 89C51系列-中断优先级只有两个: 高优先级和低优先级
* - 中断同时到来的时候,优先处理高优先级的中断请求
***************************************************/
void exit0_init(void)
{
IE0 = 0;
EA = 1; //打开所有总中断开关,EA位已经在<reg51.h>头文件中定义
IT0 = 1;//配置外部中断0触发方式,设置为下降沿触发,IT0已经在<reg51.h>头文件中定义
EX0 = 1;//打开外部中断0开关,IT0已经在<reg51.h>头文件中定义
IP = (IP&0x3E)|0x00;//设置外部中断0为低优先级
}
/**************************************************
* @function 外部中断0配置函数
* @parameter None
* @return None
* @description
* - 89C51系列-外部中断触发方式只有两种: 下降沿触发和低电平触发
* - 中断同时到来的时候,优先处理高优先级的中断请求
***************************************************/
void exit1_init(void)
{
IE1 = 0;
EA = 1; //打开所有总中断开关,EA位已经在<reg51.h>头文件中定义
IT1 = 1;//配置外部中断1触发方式,设置为下降沿触发,IT1已经在<reg51.h>头文件中定义
EX1 = 1;//打开外部中断1开关,IT1已经在<reg51.h>头文件中定义
IP = (IP&0x3B)|0x01;//设置外部中断1为高优先级
}
/**************************************************
* @function 外部中断0服务函数
* @parameter None
* @return None
* @description
* - 89C51系列-外部中断0所连接的管脚为P3.2
* - 外部中断0 对应的 中断服务函数标号为0
* - 中断服务函数没有参数,没有返回值,使用不需要声明
***************************************************/
void Exit0_IRQHandler() interrupt 0
{
number++;
IE0 = 0;//清除外部中断0标志位
}
/**************************************************
* @function 外部中断1服务函数
* @parameter None
* @return None
* @description
* - 89C51系列-外部中断1所连接的管脚为P3.3
* - 外部中断1 对应的 中断服务函数标号为2
* - 中断服务函数没有参数,没有返回值,使用不需要声明
***************************************************/
void Exit1_IRQHandler() interrupt 2
{
number--;
IE1 = 0;//清除外部中断1标志位
}
/***************************************************
* @function 数码管显示函数(单个)
* @parameter
* - digx 指定哪个数码管显示(0~3)
* - number 指定数码管显示的数字(0~9)
* - dot 指定数字后是否有小数点(0或1)
* @return None
***************************************************/
void dig_display(u8 digx,u8 number,bit dot)
{
if(digx>3)
{
digx = 3;
}
P2 = (P2&0xCF)|(seg_switch[digx]<<4);
if(number>=10)
{
P1 = 0x00;
}
if(dot)
{
P1 = (Seg_Code[number]|0x80);
}else{
P1 = (Seg_Code[number]&0x7F);
}
}
/***************************************************
* @function 数码管显示函数(四个)
* @parameter
* - number 数码管需要显示的数字(0000~9999)
* @return None
{***************************************************/
void dig_display_all(u16 number)
{
u8 dig0_num,dig1_num,dig2_num,dig3_num;
//1234
dig0_num = number%10;
dig1_num = (number%100-dig0_num)/10;
dig2_num = (number%1000 - dig1_num*10-dig0_num)/100;
dig3_num = number%10000/1000;
dig_display(DIG3,dig0_num,0);
delay_ms(1);
dig_display(DIG2,dig1_num,0);
delay_ms(1);
dig_display(DIG1,dig2_num,0);
delay_ms(1);
dig_display(DIG0,dig3_num,0);
delay_ms(1);
}
/***************************************************
* @function ms级延时函数(软件延时)
* @parameter
* - nms 设置延时的时间(0~65535)
* @return None
***************************************************/
void delay_ms(u16 nms)
{
unsigned char i, j;
while(nms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}