51单片机应用:8只数码管同时显示多个不同字符
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
51单片机应用:8只数码管同时显示多个不同字符设计要求
单片机控制8只数码管,同时显示8个字符。
例如,从左至右显示“”,接着显示“”,在接着显示“”,……“”,“”,
分析及方案设计:
本题可以采用扩展I/O口或直接用单片机自身的I/O口的方法实现。
为节省硬件设施并使电路连线尽量简单,采用直接使用单片机自身I/O口的方式,8个数码管同时显示数字则需采用动态显示方法,初步设定以P0口给出数码管显示字段,P1口选中某一时刻动态点亮的数码管。
软件设计可以有以下几种方案:
a)将全部显示状态列出,放在主程序中不断循环
b)将显示状态放入8个数组中,每个状态循环一次后主程序重新开始循环
c)只设置两个数组,其中一个取值不变,为正序的从1到8的共阳极数码管段码,另一个数组中的数值不断被修改,即每次显示状态改变的时候都相应改变一次,如从的段码改为的段码。
从上述方案可以看出,若设置太多的数组或列出所有显示状态,程序虽然清晰易懂但占用程序存储空间明显较大,且用delay()函数延时的话会不断占用CPU;用两个数组和两个定时器虽然算法略复杂,但程序可以达到最简化。
详细的方案说明:
1)采用数码管动态显示方法。
2)8个数码管由P3控制位选,即决定某一时刻哪一个数码管亮,由P0发出的总线控制显示的段码。
3)定时器T0和T1同时工作,定时时间均为
0."5毫秒,采用方式1定时,每次溢出后由软件重装初值。
4)设置中间变量temp,用于不断左移并给P3赋值;数组display[]为code 即取之不变的数组,数组show[]中的取值变化。
5)每次T0计数溢出时,temp左移一次,相应的P3左移一次,数码管由第i 个点亮变为第i+1个点亮,与此同时赋给P0口的值由show[i]变为show[i+1],达到动态显示的效果。
6)定时器T1也是每
0."5毫秒计数溢出一次,但只有到1秒时才执行定时器1中断中修改数组show[]取值的程序,用变量t记录T1溢出的次数,达到200次时数组show[]中的内容开始进行修改并且t清零。
假设showp[0]到show[7]中的取值分别为共阳极数码管显示
1、"
2、
3、"
4、
5、"
6、
7、"8的段码,修改后分别变为显示
2、"
3、
4、"
5、
6、"
7、
8、"1的段码,这样显示状态自然发生了改变。
7)修改show[]中的取值为本程序中细节最多的部分,设置无符号长整型变量n(无符号长整型变量的取值为0到95,按1秒增加1的速度计算,在实验范围内不会溢出)为显示状态总共改变的次数,易知show[0]的值为display[p],p为n除以8的余数,从此处开始循环给show[]重新赋值。
硬件电路设计:
程序:
#include<reg
51."h>
#include<intrins.h>
int i,t,m,a;
unsigned long n;
unsigned char code
display[]={0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80};unsigned char
show[]={0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80}; //数组display的取值不变,数组show的取值每次显示状态改变时均改变一次,T0中断程序只管流水使得位选从0到7时依次显示show[]中从0到7的取值//
unsigned char temp;//定时器T1中断程序控制数组show[]取值的改变,使得现实状态相应改变//
unsigned char middle; //i用于T0的计时循环,取值从0到7,控制P1口位选的流水;t用于T1的循环,控制每个显示状态(或等)的时间,1s改变一次,即t的取值从0到200//
//n记录显示状态改变的次数,每次改变时m从0到7为数组show循环赋值,a为中间变量,保证第n次显示状态时show[]的第0个取值恰好为n除以8的余数被记录下来//
void main(){TMOD=0x11;//设置定时器T
0、"T1均为方式1工作
TH0=0xee;//写入定时器T0的高8位
TL0=0x00;//写入定时器T0的低8位
TH1=0xee;//写入定时器T1的高8位
TL1=0x00;//写入定时器T1的低8位
EA=1;//打开总中断
ET0=1;
ET1=1;//定时器中断允许位置1
TR0=1;
TR1=1;//定时器开始工作
i=0;
temp=0x01;
P3=temp;//给变量设定初值
P0=show[i];//第一个数码管开始显示数字1
while
(1)
{//空的循环作为主程序,中断返回后回到主程序;}}
void t0int(void) interrupt 1//定时器T0中断服务程序{TH0=0xee;//给T0重新装入16位初值,重新开始计数TL0=0x00;
i++;//预备动态点亮下一个数码管
if(i==8)
{//判断i的数值,若超过0到7的范围,清零i=0;}temp=_crol_(temp,1);//给即将动态点亮的数码管位选加高电平P3=temp;//位选从P3送出,数码管被选中
P0=show[i];//P0发送总线信息为改点亮的数码管的编码,第i个数码管显示show[i]}void t1int(void) interrupt 3//定时器T1的中断服务程序,内容为数组show[]的改写,从而改变显示状态{TH1=0xee;
TL1=0x00;//定时器T1重新装初值
if(t<200)
{//判断t的数值,若t<200,即没到1秒钟,显示状态不改变,t增一计数;若t到200,开始修改显示状态
t++;}else{t=0;//定时器T1计数溢出200次,到达时间1秒钟,t清零重新开始1秒钟计时
n++;//n为总的显示状态改变次数,每次改变显示状态,n加1
a=n%8;//a为n除以8的余数,记录不断变化数组show[]应取的第一个值在不变的数组display[]中的位置
for(m=0;m<8;m++){if(a<8)//若a小于8,display[a]赋值给show[0],display[a+1]赋值给show[1]...{middle=display[a];//middle做中间变量,在数组display[]和show[]之间传递数值
show[m]=middle; //每次赋值之后a加1
a++;}else//a的值需要不断进行判断,若a到达8则将a清零,否则数组出错{a=a-8;
middle=display[a];
show[m]=middle;
a++;}}}}。