标题:
51单片机数码管显示学号程序+Proteus仿真电路图
[打印本页]
作者:
trc
时间:
2019-4-8 15:41
标题:
51单片机数码管显示学号程序+Proteus仿真电路图
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
0.png
(26.6 KB, 下载次数: 53)
下载附件
2019-4-8 15:42 上传
0.png
(10.03 KB, 下载次数: 44)
下载附件
2019-4-8 15:42 上传
单片机源程序如下:
#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)
2019-4-8 15:40 上传
点击文件名下载附件
51单片机
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1