仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include <reg52.h>
- sbit hang1=P2^0;
- sbit hang2=P2^1;
- sbit lie1=P2^2;
- sbit lie2=P2^3;
- sbit buzzer=P2^7; //蜂鸣器
- //与ADC相关的位声明
- sbit ADC_START=P3^4; //转换启动信号,高脉冲启动转换
- sbit ADC_EOC=P3^2; //转换结束信号,高电平转换结束
- sbit ADC_A=P3^5;
- sbit ADC_B=P3^6;
- sbit ADC_C=P3^7;
- unsigned char code table[]={0x03,0x9f,0x25,0x0d,
- 0x99,0x49,0x41,0x1f,
- 0x01,0x09,0x11,0xc1,
- 0xe5,0x85,0x21,0x71,0xff};
- void sendstr(unsigned char); //串口发送数字显示
- void delay(unsigned char ); //延时函数
- void desplay(); //移动显示学号函数
- void keyscan(); //键盘扫描函数
- void desplay_key_number();
- void Get_ADC(void); //ADC转换函数
- unsigned char b=0,i,counter=4,Time=0,flag=0,INT;
- float ADC_V; //AD转换的电压值
- int main()
- {
- /*主程序初始化部分*/
- EA=1; //开总中断
- SCON=0x00; //串口初始化 ,工作方式0
- EX1=1; //开外部中断1
- IT1=1; //外部中断1电平触发
- ET0=1; //开启定时器0中断
- ET1=1; //开启定时器1中断
- TMOD=0X11; //定时器0工作方式1,定时器1工作方式1
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- TH1=(65536-500)/256;
- TL1=(65536-500)%256;
- hang1=hang2=0;
- ADC_A=ADC_B=ADC_C=0; //选择ADC转换通道0
-
- desplay(); //上电显示学号
- while(1)
- {
-
- if(INT) //INT=1表示进入外部中断1,则可以进行键盘扫描
- {
- keyscan(); //扫描得到键值
- TR0=0; //关闭定时器0,判断此时按键按下的时间
- INT=0;
- EX1=1; //开外部中断1
- }
- if(counter!=4)
- {
-
- if(flag) //到2.5秒执行
- {
- switch (counter)
- {
- case 0: //DA功能键,即梯形波
- TR1=1; //启动定时器1产生波形
- break;
- case 1: //学号显示键
-
- desplay(); //显示学号 delay(100);
- break;
- case 2:
-
-
- break;
- case 3: //AD功能键
- for(i=0;i<8;i++)
- {
- sendstr(16); //将所有数码管清灭
- }
- Get_ADC();
- SBUF=table[(int)(ADC_V)]&0xfe; //与小数点一同显示
- while(!TI);
- TI=0;
- sendstr((int)(ADC_V*10)%10);
- sendstr((int)(ADC_V*100)%100%10);
- break;
- default:
- break;
- }
- flag=0; //在此将flag清零,而不在中断中清零
- }
- else //未到2.5秒执行
- {
-
- desplay_key_number();
-
- }
- counter=4;
- }
- }
-
- }
- void INT_1() interrupt 2 //外部中断1函数
- {
- TR0=1; //启动定时器0
- TR1=0; //关闭定时器1,以免与定时器0冲突
- Time=0; //不能在此将flag清零,放下按键也会产生抖动,
- //此时进入中断将flag清零就错了,反应不了真实情况
- buzzer=0;
- delay(1);
- buzzer=1;
-
- IE1=0; //软件清零中断标志
- EX1=0; //关外部中断1,等待键盘扫描结束再重新打开
- INT=1; //进入中断标志位
- }
- void timer_0() interrupt 1 //定时器0中断服务函数,用于判断2.5秒钟时间是否已到
- {
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- Time++;
- if(Time==50)
- {
- flag=1; //标志位置1
- /*蜂鸣器叫两声提示时间到*/
- buzzer=0;
- delay(1);
- buzzer=1;
- delay(1);
- buzzer=0;
- delay(1);
- buzzer=1;
- }
- }
- void timer_1() interrupt 3 //矩形波发生中断函数
- {
- TH1=(65536-500)/256;
- TL1=(65536-500)%256;
- TR0=0; //关闭定时器0,以免冲突
- switch(b)
- {
- case 0:
- P0=0x00;
- for(i=0;i<51;i++)
- {
- P0+=5;
- ;;;;;;;;;;;;;;;;;;; //多个分号,用于延时
- }
- b++;
- break;
- case 1:
- b++;
- break;
- case 2:
- for(i=0;i<51;i++)
- {
- P0-=5;
- ;;;;;;;;;;;;;;;;;;; //多个分号,用于延时
- }
- b++;
- break;
- case 3:
- b=0;
- break;
- default:
- break;
- }
-
- }
- void sendstr(unsigned char i) //串口发送数字显示
- {
- SBUF=table[i];
- while(!TI);
- TI=0;
- }
- void keyscan() //键盘扫描函数
- {
- //扫描第一行
- hang1=0;
- hang2=1;
- if(lie1==0)
- { delay(1); //消抖动
- while(!lie1);
- counter=0;
- }
- if(lie2==0)
- { delay(1); //消抖动
- while(!lie2);
- counter=1;
- }
- //扫描第二行
- hang1=1;
- hang2=0;
- if(lie1==0)
- { delay(1); //消抖动
- while(!lie1);
- counter=2;
- }
- if(lie2==0)
- { delay(1); //消抖动
- while(!lie2);
- counter=3;
- }
- hang1=hang2=0; //出程序拉低按键行号
- }
- void desplay_key_number() //显示按键值号函数
- {
- unsigned char num;
- for(num=0;num<8;num++)
- {
- sendstr(counter);
- }
- }
- void Get_ADC() //ADC转换函数
- {
- unsigned char ADC;
- ADC_START=0; ADC_START=1; ADC_START=0; //高脉冲启动转换
- while(ADC_EOC==0); //等待转换结束
- ADC=P1;
- ADC_V=(float)(ADC)/255*5;
- }
- void delay(unsigned char h) //延时函数
- {
- unsigned char j;
- for(j=0;j<100;j++)
- {
- while(h--);
- }
- }
- void desplay() //移动显示学号函数
- {
- unsigned char i;
- for(i=0;i<8;i++)
- {
- sendstr(16);
- }
- i=250;
- sendstr(0);
- delay(i);
- sendstr(1);
- delay(i);
- sendstr(1);
- delay(i);
- sendstr(1);
- delay(i);
- sendstr(0);
- delay(i);
- sendstr(1);
- delay(i);
- sendstr(5);
- delay(i);
- sendstr(0);
- delay(i);
- }
复制代码
所有资料51hei提供下载:
51单片机数码管显示学号.rar
(47.04 KB, 下载次数: 34)
|