51单片机实验04 您所在的位置:网站首页 ms205du调5位显示 51单片机实验04

51单片机实验04

2024-06-01 04:12| 来源: 网络整理| 查看: 265

目录

一、实验目的

二、实验内容

三、实验原理

四、实验方法

五,实验效果及代码

1,效果

2,代码

六,课后习题

1,使用定时器T0的中断函数1 从999999~0计时

 1)效果

2)代码

2,使用定时器T1的中断函数3 从999999~0计时

1)效果 

2)代码

一、实验目的

1、熟悉掌握数码管动态显示的基本方法。 2、根据已知电路和设计要求在实验板上实现数码管动态显示。 3、掌握利用定时器T0中断的使用方法。

二、实验内容

在KST-51开发板上,选择任意左右相连的4位数码管,利用定时器T0中断实现动态显示0123→1234→2345→3456→4567→5678→6789→7890→8901→9012→0123→不断反复,每隔2s切换显示内容。

三、实验原理

实验要求“4位数码管上实现动态显示

0123→1234→2345→3456→4567→5678→6789→7890→8901→9012→0123→不断反复,每隔2s切换显示内容”。动态扫描可以实现该要求。

简单地说,动态扫描就是选通一位,送一位数据。原理图中的LEDS0-LEDS5是相应数码管的位选信号,即选择哪个数码管显示数字;P0.0-P0.7是段码,即要显示的数字。可以通过依次选通某一位7段数码管并通过P0端口送出显示数据。由于人眼的视觉残留原理,如果这种依次唯一选通每一位7段数码管的动作在10ms内完成,就会造成多位数码管同时点亮显示各自数字的假象。 本实验使用定时器T0中断,实现每2s更新一次数字。

定时器有关代码请看前面文章:

51单片机实验03-单片机定时/计数器实验-CSDN博客

四、实验方法

1、根据电路图,分析和掌握数码管动态显示的原理,选择4位数码管。使用定时器T0中断实现每2秒更新一次数字的设计思路。 本次实验使用Timer0中断,由于其定时时间最大为65536us,不能实现2s的长延时,那么可以使用多次中断来实现,并且在中断到来时,不断地死循环显示数字,即根据动态显示原理“选通一位,来一位数据”。设x表示千位的数字,由于最大的数字为9,则(x%10)、(x+1)%10、(x+2)%10、(x+3)%10分别是千位、百位、十位、个位上的数字。在编写代码时,设置Timer0定时时间为2ms,可以用一个参数cnt计算中断的次数;当中断的次数达到1000次时,说明已经达到了2s,此时更新数字,即将数字x自增1。 2、针对要求,画出程序流程图,根据流程图进行代码编写。 3、编译调试生成HEX文件,进行代码烧写,完成数码管动态显示功能。

五,实验效果及代码

我选择的是中间四个数码管,如果想要选择其它数码管的,可以修改这几行代码:

addr2,addr1,addr0分别控制了138译码器的输出y0~y6,因为y6已经用来控制发光二极管 ,因此,y0~y5就是用来控制数码管的。例如,y0控制最右边的数码管leds0,对应的138译码器输入:

addr2=0;addr1=0;addr0=0;

如果想要控制最左边的数码管,就需要y5输出低电平。即addr2=1;addr1=0;addr0=1;

1,效果

0123-1234等数字的循环显示

2,代码 #include sbit enled=P1^4; // 138译码器使能 sbit addr3=P1^3; sbit addr2=P1^2; sbit addr1=P1^1; sbit addr0=P1^0; // 使能端 unsigned char code ledChar[]={ // 晶体管0~9真值表 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90 //,0x88,0x83,0xC6,0xA1,0x86,0x8E }; unsigned char ledBuff[]={ // 晶体管全灭 0xFF,0xFF,0xFF,0xFF }; unsigned int outflow=0; // 记录定时器溢出次数 unsigned char ind=0; // 动态扫描的索引 unsigned char flags=0; // 2s定时标志 void main(){ unsigned long sectransistor=0; // 记录数码管显示的秒数 enled=0; addr3=1; TMOD=0x01; // 定时器T0选择模式1(16位定时器) TH0=0xFC; // 定时器的初始值 TL0=0x67; EA=1; //总中断打开 ET0=1; // 定时器0使能中断打开 TR0=1; // 定时器T0运行 while(1){ // 写好定时器中断服务后再使用while循环 if(flags==2){ // flags是2s定时 flags=0; // 重新计时,直到flags再次等于1(时间再次为2s) ledBuff[0]=ledChar[(sectransistor+3)%10]; ledBuff[1]=ledChar[(sectransistor+2)%10]; ledBuff[2]=ledChar[(sectransistor+1)%10]; // 0+1对10取余为1 ,10对10取余为0 ledBuff[3]=ledChar[sectransistor%10]; // 最左边的晶体管数值最小0 sectransistor++; // 秒数自增 } } } void InterruptTimer0() interrupt 1{ // 定时器T0中断服务函数1 TH0=0xFC; // 定时器初始值 TL0=0x67; outflow++; // 溢出自增 if(outflow==2000){ //每隔2s切换显示内容 outflow=0; flags=2; // 2s到了之后,flags立起来 } P0=0xFF; // 关闭段 switch(ind){ // 控制指定晶体管亮起 case 0:addr2=0;addr1=0;addr0=1;ind++;P0=ledBuff[0];break; case 1:addr2=0;addr1=1;addr0=0;ind++;P0=ledBuff[1];break; case 2:addr2=0;addr1=1;addr0=1;ind++;P0=ledBuff[2];break; case 3:addr2=1;addr1=0;addr0=0;ind=0;P0=ledBuff[3];break; default: break; } } 六,课后习题

 需要知道的是,使用不同的定时器,所对应的中断函数也是不一样的,如下表中所示👇

 可以看到,定时器T0的中断函数编号是1 ,而定时器T1的中断函数3,因此在写程序的时候需要正确更改interrupt后面的编号。

1,使用定时器T0的中断函数1 从999999~0计时  1)效果

效果同T1定时器👇:

定时器T1使用中断函数从999999~0计时

2)代码 #include sbit enled=P1^4; // 138译码器使能 sbit addr3=P1^3; sbit addr2=P1^2; sbit addr1=P1^1; sbit addr0=P1^0; // 使能端 // unsigned char code ledChar[]={ // 晶体管真值表 //0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, //0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E //}; //倒计时 0x8E,0x86,0xA1,0xC6,0x83,0x88, unsigned char code ledChar[]={ // 从数值9开始 0x90,0x80,0xF8,0x82,0x92,0x99,0xB0,0xA4,0xF9,0xC0 }; unsigned char ledBuff[]={ // 晶体管全灭 0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF }; unsigned int outflow=0; // 记录定时器溢出次数 unsigned char ind=0; // 动态扫描的索引 unsigned char flags=0; // 1s定时标志 void main(){ unsigned long sectransistor=0; // 记录数码管显示的秒数 // 0~999999 enled=0; addr3=1; TMOD=0x01; // 定时器T0选择模式1 TH0=0xFC; // 定时器的初始值 TL0=0x67; EA=1; //总中断打开 ET0=1; // 定时器0使能中断打开 TR0=1; // 定时器T0运行 while(1){ // 写好定时器中断服务后再使用while循环 if(flags==1){ // flags是1s定时 flags=0; // 重新及时,直到flags再次等于1 ledBuff[0]=ledChar[sectransistor%10]; // 开启指定晶体管 ledBuff[1]=ledChar[sectransistor/10%10]; ledBuff[2]=ledChar[sectransistor/100%10]; ledBuff[3]=ledChar[sectransistor/1000%10]; ledBuff[4]=ledChar[sectransistor/10000%10]; ledBuff[5]=ledChar[sectransistor/100000%10]; sectransistor++; // 数码管在之前的基础上+1s } } } void InterruptTimer0() interrupt 1{ // 定时器T0中断服务函数1 TH0=0xFC; // 定时器初始值 TL0=0x67; outflow++; // 溢出自增 if(outflow==1000){ //1s outflow=0; flags=1; // 1s到了之后,flags立起来 } P0=0xFF; // 关闭段 switch(ind){ // 控制指定晶体管亮起 case 0:addr2=0;addr1=0;addr0=0;ind++;P0=ledBuff[0];break; case 1:addr2=0;addr1=0;addr0=1;ind++;P0=ledBuff[1];break; case 2:addr2=0;addr1=1;addr0=0;ind++;P0=ledBuff[2];break; case 3:addr2=0;addr1=1;addr0=1;ind++;P0=ledBuff[3];break; case 4:addr2=1;addr1=0;addr0=0;ind++;P0=ledBuff[4];break; case 5:addr2=1;addr1=0;addr0=1;ind=0;P0=ledBuff[5];break; default: break; } } 2,使用定时器T1的中断函数3 从999999~0计时 1)效果 

定时器T1使用中断函数从999999~0计时

2)代码 #include sbit enled=P1^4; // 138译码器使能 sbit addr3=P1^3; sbit addr2=P1^2; sbit addr1=P1^1; sbit addr0=P1^0; // 使能端 // unsigned char code ledChar[]={ // 晶体管真值表 //0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, //0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E //}; //倒计时 0x8E,0x86,0xA1,0xC6,0x83,0x88, unsigned char code ledChar[]={ 0x90,0x80,0xF8,0x82,0x92,0x99,0xB0,0xA4,0xF9,0xC0 }; unsigned char ledBuff[]={ // 晶体管全灭 0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF }; unsigned int outflow=0; // 记录定时器溢出次数 unsigned char ind=0; // 动态扫描的索引 unsigned char flags=0; // 1s定时标志 void main(){ unsigned long sectransistor=0; // 记录数码管显示的秒数 // 0~999999 enled=0; addr3=1; TMOD=0x10; // 定时器T1选择模式1 TH1=0xFC; // 定时器初始值 TL1=0x67; EA=1; //总中断打开 ET1=1; // 定时器1使能中断打开 TR1=1; // 定时器运行 while(1){ // 写好定时器中断服务后再使用while循环 if(flags==1){ // flags是1s定时 flags=0; // 重新及时,直到flags再次等于1 ledBuff[0]=ledChar[sectransistor%10]; // 开启指定晶体管 ledBuff[1]=ledChar[sectransistor/10%10]; ledBuff[2]=ledChar[sectransistor/100%10]; ledBuff[3]=ledChar[sectransistor/1000%10]; ledBuff[4]=ledChar[sectransistor/10000%10]; ledBuff[5]=ledChar[sectransistor/100000%10]; sectransistor++; // 数码管在之前的基础上+1s } } } void InterruptTimer1() interrupt 3{ // 定时器0中断服务函数 TH1=0xFC; // 定时器初始值 TL1=0x67; outflow++; // 溢出自增 if(outflow==1000){ //1s outflow=0; flags=1; // 1s到了之后,flags立起来 } P0=0xFF; // 关闭段 switch(ind){ // 控制指定晶体管亮起 case 0:addr2=0;addr1=0;addr0=0;ind++;P0=ledBuff[0];break; case 1:addr2=0;addr1=0;addr0=1;ind++;P0=ledBuff[1];break; case 2:addr2=0;addr1=1;addr0=0;ind++;P0=ledBuff[2];break; case 3:addr2=0;addr1=1;addr0=1;ind++;P0=ledBuff[3];break; case 4:addr2=1;addr1=0;addr0=0;ind++;P0=ledBuff[4];break; case 5:addr2=1;addr1=0;addr0=1;ind=0;P0=ledBuff[5];break; default: break; } }

有问题请在评论区留言,一天8h在线。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有