需知道:
LED的特性是什么?共阳极与共阴极的区别?什么是段码?段码是怎么计算的(自己可以推断共阴极或共阳极的段码)?段码与位选的区别?7段LED显示的字符分别有哪些?自己能够写得出吗?能够区分静态显示与动态显示吗?
实验要求:
编程控制单片机驱动一个八位一体LED数码管和一个开关,实现:开关拨上实现八个LED数码管同时循环显示“0,1,2……E,F”等十六个字符。开关拨下时,实时切换八个LED数码管显示状态为同时显示八个不同的数字,例如“12345678”。当开关再次拨上时,将继续切换前的字符往下同时循环显示“0,1,2……E,F”等十六个字符。
实验工具:
仿真软件:proteus8.0
软件:keil4
提示:高版本的可以打开低版本的,但是低版本打不开高版本的。
实验步骤
实验电路
元件简要介绍:
元件名称 | 图片 | 备注 |
---|---|---|
7SEG-MPX8-CC—BLUE | MPX表示多位一体,8表示8位 | |
RESPACK—8 | 8个可以连接的引脚,1号引脚连接电源,2-9号引脚连接单片机的P0接口,可做上拉电阻用 | |
SW-SPDT | ||
AT89C51 |
软件源代码:
版本1
此代码参考了 参考链接
#include<reg51.h>
#define uchar unsigned char
sbit DI1=P0^0; //定义8位数码管位选信号
sbit DI2=P0^1;
sbit DI3=P0^2;
sbit DI4=P0^3;
sbit DI5=P0^4;
sbit DI6=P0^5;
sbit DI7=P0^6;
sbit DI8=P0^7;
//定义输入端的信号端口
sbit sw=P1^7;
void delay(uchar x) //定义延时函数
{
uchar j;
while(x--)
{
for(j=0;j<125;j++);
}
} /*定义数码管显示字符跟数字的对应数组关系*/
unsigned char code dis[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F ,0x77,0x7c,0x39,0x5e,0x79,0x71};
void main()
{
char i,k=0;
while(1)
{
if(sw==1)
{
for(i=0;i<=15;i++)
{
P0=0x00;
P3=dis[k%16];
if(sw!=1)
break;
delay(500);
k++;
}
}
else
{
P3=0x00; //P0口初始化
DI1=0; //第一位数码管位选
P3=dis[1]; //第一位数码管显示0
delay(5);
DI1=1; //关闭第一位数码管位选
DI2=0; //第二位数码管位选
P3=dis[2]; //第二位数码管显示1
delay(5);
DI2=1; //关闭第二位数码管位选
DI3=0; //第三位数码管位选
P3=dis[3]; //第三位数码管显示2
delay(5);
DI3=1; //关闭第三位数码管位选
DI4=0; //第四位数码管位选
P3=dis[4]; //第四位数码管显示3
delay(5);
DI4=1; //关闭第四位数码管位选
DI5=0;
P3=dis[5];
delay(5);
DI5=1;
DI6=0; //6位
P3=dis[6];
delay(5);
DI6=1;
//7位
DI7=0;
P3=dis[7];
delay(5);
DI7=1;
DI8=0; //8位
P3=dis[8];
delay(5);
DI8=1;
}
}
}
看到版本2的代码,会觉得这个代码行数过多。而且在else里的代码有很多循环的,可以利用通式将其替换。
版本2:
#include <REGX51.H>
#include <intrins.h>
sbit sw=P1^7;
//段码 ,code存储在RAM中,访问速度快
unsigned char code dis[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F ,0x77,0x7c,0x39,0x5e,0x79,0x71};
//延时函数
void delay(unsigned int time)
{ unsigned int i;
for(;time>0;time--)
for(i=125;i>0;i--);
}
//主函数
void main()
{ unsigned char bit_scan[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//每次亮一个灯
unsigned char i,j,k=0;
while(1)
{
if(sw==1) //开关拨上
{
for(j=0;j<16;j++)
{
P0=0x00;//位码。LED全部亮
P3=dis[k%8];
if(sw!=1)//开关拨下,退出循环
break;
delay(500); //无它不显示其他的数字
k++; //标记
}
}
else
{
for(i=0;i<8;i++)
{
P0=bit_scan[i];
P3=dis[i+1];
delay(5);
}
}
}
}
遇到的问题
问题1
WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
不影响运行,只是说你定义的函数没有调用而已
解决办法:不用管
问题2
多次修改代码,然后就提示
--- Error: failed to execute 'D:\program files\单片机开发工具\Keil4\C51\BIN\C51.EXE'
然后按照提示的路径,查看文件,发现自己没有BIN文件(之前没有注意看,同学有这个文件,所以就默认自己有吧)
解决办法参考1.1:https://blog.csdn.net/qq_24835087/article/details/87929636
解决办法参考1.2:http://www.myexceptions.net/ai/1918822.html
解决办法参考1.3:https://www.cnblogs.com/shareidea/p/5273158.html
1.1未解决,复制了同学的BIN文件到安装路径,结果还是不行。
1.2未解决,在RealView Folder里选择keil安装目录下的C:\Keil\ARM\ARMCC\bin,点OK后就可以正常使用了
里根本浏览不了路径
1.3,解决了。路径\Keil4\
问题3
如果将版本2的代码,稍微改一下,即开关拨上拨下各自弄个函数。那么实验要求里的当开关再次拨上时,将继续切换前的字符往下同时循环显示“0,1,2……E,F”等十
就实现不了。为什么会出现这样的效果,我没有弄清楚
#include <REGX51.H>
#include <intrins.h>
sbit sw=P1^7;
//段码 ,code存储在RAM中,访问速度快
unsigned char code dis[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F ,0x77,0x7c,0x39,0x5e,0x79,0x71};
//延时函数
void delay(unsigned int time)
{ unsigned int i;
for(;time>0;time--)
for(i=125;i>0;i--);
}
//开关拨上函数
void hight()
{ unsigned char j,k=0;
//P0=0x00;//在这个位置LED不亮
for(j=0;j<16;j++)
{ P0=0x00;//位码。LED全部亮
P3=dis[k%16];
if(sw!=1)//开关拨下,退出循环
break;
delay(500); //无它不显示其他的数字
k++; //标记
}
}
//开关拨下函数
void low()
{ unsigned char bit_scan[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//每次亮一个灯
unsigned char i;
for(i=0;i<8;i++)
{
P0=bit_scan[i];
P3=dis[i+1];
delay(5);
if(sw!=0)
break;
}
}
//主函数
void main()
{
while(1)
{
if(sw==1) //开关拨上
{ hight();}
else
{low();}
}
}
最后
欢迎各位评论,指教!