欢迎大家来到IT世界,在知识的湖畔探索吧!
-
实验准备
-
课程内容
第五课 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毫秒的延时基本没消失就显示进入下一次的显示,这样显示就是连续的效果。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/18189.html