龙空技术网

第五课 LED数码管,蜂鸣器《中学生C51单片机易学实战入门教程》

DayDayUp程序员 561

前言:

今天朋友们对“单片机一个for循环时间是多少分钟”大概比较关心,大家都需要知道一些“单片机一个for循环时间是多少分钟”的相关资讯。那么小编在网上搜集了一些有关“单片机一个for循环时间是多少分钟””的相关文章,希望朋友们能喜欢,同学们一起来学习一下吧!

实验准备

课程内容

 

第五课 LED数码管,蜂鸣器实验准备:

使用前一课已装配好的实验板

共阳极单位数码管1只

共阴极4位数码管2只

蜂鸣器模块一件

电阻:10k 8只 或排阻(用于P0上拉)

138译码器:74LS138 一只

(或直接使用完整的开发板)

课程内容:一、 共阳极LED数码管

对比下这两个原理图,应该很容易发现差不多相同的abcdefg和dp分别对应 8 LED 的D1—D8,那么控制数码管显示数字是不是与8 LED一样控制发光与不发光呢,例如显示0,只需要让g和dp不发光,其他发光,给这8位数的信号是 11000000。光说不行,必须做实验。实践是检验真理的唯一标准。

 这一课开始,我们用上P0端口,这P0端口与其他的P1、P2、P3有点不同,它每个管脚需要增加一只电阻接上电源5V,这称为上拉,让管脚先获得默认值1,如果没有这上拉电阻,管脚状态称为浮空,不能确定数据是0还是1。

把P0的线接上这只共阳级单位数码管,然后按刚才的想法,修改程序。

void main()

{

P0=0xC0; // 11000000

}

编译、下载、观看效果。果然0显示出来了。

其他的数字呢,同样,可以计算出来。

我们利用前一课LED点阵课程中数组的方式,把这一组数先存放好,其中还包括AbcdEFPHLy-这几个常用的字符的显示数据。

uchar code light[] ={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0x8C,0x89,0xC7,0x91,0xBF,0xFF};

放入function.h头文件中,方便以后随时使用。

void main()

{

P0= light[3]; // 显示数组中第4个数,注意C语言顺序是从0开始

}

继续,我们让数字也动起来,让数码管从0到8一个一个按顺序显示,这得要用上前面课程中的循环与延时功能了。

void main()

{

uint i; //循环变量,用于控制循环

for(i=0;i<9;i++)

{

P0= light[i]; // 显示数组中第i个数,注意C语言顺序是从0开始

mDelay(1000);

}

}

编译,下载到实验板,可以看到数字变化起来了。

再继续,来换成倒数方式,程序改动一点点。

void main()

{

uint i; //循环变量,用于控制循环

for(i=9;i>0;i--)

{

P0= light[i]; // 显示数组中第i个数,注意C语言顺序是从0开始

mDelay(1000);

}

}

编译,下载实验板检验,倒数出来了,但是少了0的显示。

看那判断循环条件,i>0时才做循环,所以0时没进入循环内,改为i>=0试下;

void main()

{

uint i; //循环变量,用于控制循环

for(i=9;i>=0;i--)

{

P0= light[i]; // 显示数组中第i个数,注意C语言顺序是从0开始

mDelay(1000);

}

}

编译,下载实验板,终于可以倒数到0了。

但感觉有不对劲的地方,没改>=0之前可以不断变数字,而现在数到0就停了!!

二、 BUG 的分析与排除

搞开发总是免不了BUG,但有错必改,关键是如何工出BUG点,然后修复。

分析开始:

代码中当 i=0,符合条件 i>=0,所以进入循环体内显示0,之后执行i--,这时,问题来了。

Main()内的第一行命令 uint i; 是定义一个循环变量,用于控制循环,这个i是uint 型,表示正整型数(即是数学上的正数、整数)。

而当 i=0之后再减1时,i就变成负数,与定义的正整型数不符合,程序中止。

修复:

修复BUG的方法有多种,这里提供一种,其他方法可以自己试下改代码实践下。

既然 i 必须是正整数,那么必须让i>0做循环条件,而不是i>=0,同时循环体内的数组显示改为P0= light[i-1];也就是显示前一位置的数,来达到显示0的效果。

void main()

{

uint i; //循环变量,用于控制循环

for(i=9;i>0;i--)

{

P0= light[i-1]; //显示数组中第i-1个数,注意C语言顺序是从0开始

mDelay(1000);

}

}

编译,下载实验板,这回效果终于正确了,这就是查BUG与修复,学习开发中必须要学会的。

三、蜂鸣器

看那倒数的程序,与火箭发射倒计时很像,每显示一数加个『嘀』就行了。

这需要用到蜂鸣器模块。

从蜂鸣器原理图看到,把它接在P1的第5脚 ,然后给这管脚一个信号0,就可以让它响了。

首先,在function.h 头文件中 增加 这管脚的定义sbit P15=P1^5;

然后,修改主程序main(),如下:

void main()

{

uint i; //循环变量,用于控制循环

for(i=9;i>0;i--)

{

P0= light[i-1]; //显示数组中第i-1个数,注意C语言顺序是从0开始

P15=0; // 给信号0,让蜂鸣器在显示数字同时响

mDelay(1000); //延时1秒,可以调节

P15=1; //响1秒,够了,静音

mDelay(1000);//延时,否则直接进入下一个循环立即又响,没停了

}

}

编译,下载实验板,效果有了。

不过,倒数到0后,又回去从头开始倒数,火箭都跑了,还数什么呢,而且『嘀』声不断也挺烦人,这不符合火箭发射倒数要求,必须在倒数到0后,就停在0处。

单片机是永不停息工作的,除非程序出BUG,想让它停,也真不容易。既然它喜欢工作,那就让它在某处绕圈子,做没用的工作,实现停在某处的效果。

怎样不停的让它做没用的工作,这就要用于之前学的 for 循环,让单片机做空命令循环,把这空循环代码放程序结束之前就行了。

void main()

{

uint i; //循环变量,用于控制循环

for(i=9;i>0;i--)

{

P0= light[i-1]; //显示数组中第i-1个数,注意C语言顺序是从0开始

P15=0; // 给信号0,让蜂鸣器在显示数字同时响

mDelay(1000); //延时1秒,可以调节

P15=1; //响1秒,够了,静音

mDelay(1000);//延时,否则直接进入下一个循环立即又响,没停了

}

for(;;); //让程序停在这 不断做空体循环

}

编译,下载实验板,要想的效果出来了,也就是程序正确了。

四、 共阴极数码管

 

从原理图可以看到 共阴极数码管是把LED 的负极接在一起,由COM来控制,给COM来个0,然后传 个8位的数据,就会有显示了。

共阴极LED数码管要显示数字,对应的位的信号刚好与共阳极的相反,例如,数字0,这里对应的数据变成00111111。按前面的方法,可以计算出共阴极数码管显示数据。

uchar code Elight[] ={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x73,0x76,0x38,0x6E,0x40,0x00};

同样,放进 function.h内,方便以后调用。

从原理图中看到2个4位数码管各COM控制线刚好组成8位,那么我们用P2 来连接这个控制线。

void main()

{

uint i; //循环变量,用于控制循环

for(i=9;i>0;i--)

{

P0= Elight[i-1]; //显示数组中第i-1个数,注意C语言顺序是从0开始

P15=0; // 给信号0,让蜂鸣器在显示数字同时响

mDelay(1000); //延时1秒,可以调节

P15=1; //响1秒,够了,静音

mDelay(1000);//延时,否则直接进入下一个循环立即又响,没停了

}

for(;;); //让程序停在这 不断做空体循环

}

也就是仅仅是把显示数组换成 Elight 。

编译,下载实验板检验,怎么没反应的?

分析下,原来控制口COM接上了P2,P2内部有上拉信号,也就是就各管脚默认值是1,而这是共阴极数码管,只有给0才显示,所以信号是1时就不显示了。

那么代码中加 P2 =0x00;代码:

void main()

{

uint i; //循环变量,用于控制循环

P2 =0x00; //控制数码管显示

for(i=9;i>0;i--)

{

P0= Elight[i-1]; //显示数组中第i-1个数,注意C语言顺序是从0开始

P15=0; // 给信号0,让蜂鸣器在显示数字同时响

mDelay(1000); //延时1秒,可以调节

P15=1; //响1秒,够了,静音

mDelay(1000);//延时,否则直接进入下一个循环立即又响,没停了

}

for(;;); //让程序停在这 不断做空体循环

}

编译,下载实验板检验,8个管同时倒数,挺壮观的。

把P2 =0x00; 换成 P2=0xAA ;即10101010,编译,下载实验板检验,可以看出你想哪个管显示,那么就给哪个管COM信号0。

五、138译码器

从上面的程序中可看到。选择数码管占用了整整一个P2端口,8个IO ,这51单片机总共才4组,这样使用,效率低。于是138译码器出场了,它让8个IO 口的占用减少到只用3个 IO,为什么3个IO就够了呢,3个IO可以从000数到111,刚好是十进制的 0到7,共8个数,可以代表8个数码管的选择位。

就取某一学习板的138电路原理图,那J15直接连上 8位数码管的COM控制端,同时也用P22、P23、P24这三个IO来控制选位。

OK,在function.h 上补上这三个IO的定义:

sbit P22=P2^2;

sbit P23=P2^3;

sbit P24=P2^4;

然后修改main()主程序:

void main()

{

uint i; //循环变量,用于控制循环

P24 =1; //

P23=0; // 100 就是十进制4,第5个数码管有显示

P22=0; //

for(i=9;i>0;i--)

{

P0= Elight[i-1]; //显示数组中第i-1个数,注意C语言顺序是从0开始

P15=0; // 给信号0,让蜂鸣器在显示数字同时响

mDelay(1000); //延时1秒,可以调节

P15=1; //响1秒,够了,静音

mDelay(1000);//延时,否则直接进入下一个循环立即又响,没停了

}

for(;;); //让程序停在这 不断做空体循环

}

同样方式,可以选择其他位的数码管。

六、 让8位数码管动起来

这里8位数码管,仅显示1位,不行,下面要让8位轮显示不同的数,动起来。

前面课程学过用移位的方法让LED轮流发光,这里也可以使用。如果不采用138译码器的方式,直接P2控制数码管COM端,直接移位试就可以,同学可以自己课后编程实验下。这里采用138译码器,要有点改动,因为P22,P23,P24在P2的中间位置,用01表示这三位,就是11100011(给0是选位),即0xE3。那么只要这三个位的数有变化就行了。

看代码中的注释。

void main()

{

uchar a =0x00; //用于从0到7的计算

uchar b =0x00;//用于让P22,P23,P24 对应的位置与a相同

uint i; //循环变量,用于控制循环

for(i=8;i>0;i--)

{

b=a<<2; //a左移两位,给b保存存

P2=0xE3+b; // P2原值加上P22,P23,P24 对应位置的数

a++; //从0到7 变化

P0= Elight[i-1]; //显示数组中第i-1个数,注意C语言顺序是从0开始

mDelay(1000);

}

}

分析代码:

1)b=a<<2;

例如,某一时刻 a值是 000000101,(即0x05,十进制 5),左移2位是

00010100刚好其中原 101这三位进入到P22,P23,P24的位置。

2)P2=0xE3+b;

0xE3就是11100011,加上b值后,就是11110111,即P22,P23,P24 这几位放上了对应的数了,而这三位控制数码管选位,于是对应位显示了。

3)P0= Elight[i-1];

每次循环显示不同的数,这样各位就显示不同的数。

编译,下载实验板检验,可以看到每隔1秒,效果出来了。

那里的延时

mDelay(1000);

可以按自己的想法随意改,可以试下填入 100,10,1,观看不同的效果。

到最后用 mDelay(1000);时,看到各个数码管同时亮起来,稳定显示不同的数。

这是由于数码管的LED有显示数后有余辉,才1毫秒的延时基本没消失就显示进入下一次的显示,这样显示就是连续的效果。

标签: #单片机一个for循环时间是多少分钟