微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 单片机实习报告——点阵的动态显示

单片机实习报告——点阵的动态显示

时间:11-24 来源:互联网 点击:
一、功能介绍

程序实现字幕不同方向,不同速度滚动显示的效果,字幕滚动方向和速度可以通过键盘操作改变。
当出现静态笑脸图案时,可以操作键盘,键盘按下时,会听到蜂鸣提示音。此时按下第一个或第二个键,分别显示向左和向上的“小”“石”“山”“庄”和一个笑脸的滚动字幕的显示,当再次出现静态的现笑脸时,按下第三个或第四个键,分别降低和提高字幕滚动的速度。然后,可以再次按下第一个或第二个键,来检测改变速度后字幕滚动的效果。

二、硬件原理即实现
有关部分的电路图如下:



有关部分电路说明:
点阵显示部分:CPU的P0.0~P0.7口接8*8LED点阵的COM1~COM8端,控制点阵行的显示;P2.0~P2.7口通过74HC573接8*8LED点阵的RED1~RED8,存放点阵每行显示的数据。从程序中获取数据后控制点阵的显示。COM端为0,表示该行可能亮起;RED端为1,表示某行该列亮。
按键实现部分:CPU的P3.2~P3.5口分别接KEY1~KEY4,用于接收从键盘输入的控制信息。KEY等于0,表示该按键按下;否则,没有按下。
蜂鸣器部分:CPU的P3.7接蜂鸣器的BEE口,用于控制蜂鸣器。低电平蜂鸣器蜂鸣,高电平安静。

一、软件原理及实现

1.整体思路
主程序用while循环执行显示和几个分支语句,实现用键盘对滚动方向和滚动速度的控制。
滚动效果原理类似动画片的原理,逐屏显示错位一行或一列的字幕,从而达到横向或纵向滚动的效果。横向滚动的实现只需将RED端的数据向右和向左移位,并将每次移位后的数据存储于中间变量中,用于显示输出。纵向滚动的实现需要循环控制输出数据的起始位置,每次循环输出的起始位置向后移一个元素,从而实现逐行向上滚动的效果。
用一个全局变量来控制滚动速度,该全局变量可以通过键盘的操作增加或减小,从而实现键盘控制速度。
程序特点:主程序分别调用子程序,子程序再调用子程序,最多达到了调用三层子程序。这样的子程序嵌套调用可以提高程序代码的重用率,同时使主程序看起来简练、清晰。例如,程序中实现向左滚动的部分调用了函数disp_moveleft函数,该函数又分别调用了adjust_moveright和adjust_moveleft函数,用于分别实现逐列显示出完整的字符和字符显示完全后,逐列左移直到全部移出。

具体的程序部分功能参见程序源代码中的注释。

2.程序大体流程图如下:



3.程序原代码如下:
#include
#include
uchar code sz[][8]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //null
0x08,0x08,0x08,0x 2a,0x49,0xa8,0x18,0x08, //小
0xff,0x10,0x10,0x3e,0x52,0x92,0x12,0x1e, //石
0x08,0x08,0x08,0x08,0x49,0x49,0x49,0x7f, //山
0x08,0x3f,0x20,0x24,0x2e,0x24,0x44,0x9f, //庄
0x00,0x42,0xA5,0x00,0x00,0xff,0x42,0x3C, //smile
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 //null
};
uchar code smile[][8]={
0x00,0x00,0xa5,0x42,0x00,0x00,0x24,0x18,
0x00,0x00,0xe7,0x00,0x00,0x3c,0x42,0x3c,
0x00,0x42,0xA5,0x00,0x00,0xff,0x42,0x3C
};
uchar temp[8]={0}; //用于临时存放某一时刻屏幕上显示的字符或字符某部分的图案
uchar time=5; //用于控制速度
void delayms(uchar x) //延时一段时间(具体由参数而定)
{
uchar i;
uint16 j;
for(i=x;i>0;i--)
for(j=5000;j>0;j--);
}
void delay()
{
uchar i;
for(i=150;i>0;i--);
}
void disp_dat(uchar x) //显示一屏
{
uchar i,j,k,l;
for(j=x;j>0;j--)
{
for(k=3;k>0;k--)
{
l=0xfe;
for(i=0;i<8;i++)
{
P2=0;
P0=l;
P2=temp[i];
delay();
l<=1;
l++;
}
}
}
}
void adjust_moveleft(uchar x,uchar *dat) //第i个字符逐列左移
{
uchar j,k;
for(j=0;j<8;j++)
{
k=*dat;
k<=x;
temp[j]=k;
dat++;
}
}
void adjust_moveright(uchar x,uchar *dat) //第i个字符显示出x列后存储在temp数组中
{
uchar j,k;
for(j=0;j<8;j++)
{
k=*dat;
k>>=x;
temp[j]=k;
dat++;
}
}
void disp_moveleft(uchar *dat)
{
uchar i,t;
for(i=8;i>0;i--) //逐列显示出字符
{
adjust_moveright(i,dat);
t=time;
disp_dat(t);
}
for(i=0;i<=8;i++) //字符显示完全后,逐列左移直到全部移出
{
adjust_moveleft(i,dat);
t=time;
disp_dat(t);
}
}
void adjust_jingtai(uchar *dat)
{
uchar i;
for(i=0;i<8;i++)
{
temp[i]=*dat;
dat++;
}
}
void disp_moveup(uchar *dat)
{
uchar i,j,t;
for(i=0;i<6;i++)
{
for(j=0;j<8;j++)
{
dat++;
adjust_jingtai(dat);
t=time;
disp_dat(t);
}
disp_dat(30);
}
}
void main()
{
while(1)
{
uchar j;
for(j=0;j<8;j++)
temp[j]=smile[2][j];
disp_dat(30);
if(key1==0)
{
bee=0;
delayms(1);
bee=1;
delayms(1);
if(key1==0) //向左滚动
{
uchar i;
for(i=1;i<6;i++)
{
disp_moveleft(&sz[i][0]);
}
}
while(key1==0);
}
if(key2==0)
{
bee=0;
delayms(1);
bee=1;
delayms(1);
if(key2==0) //向上滚动
{
disp_moveup(&sz[0][0]);
}
while(key2==0);
}
if(key3==0)
{
delayms(1);
if(key3==0) //减速
{
time=time+1;
}
while(key3==0);
bee=0;
delayms(1);
bee=1;
}
if(key4==0)
{
delayms(1);
if(key4==0) //加速
{
if(time!=1)
time=time-1;
}
while(key4==0);
bee=0;
delayms(1);
bee=1;
}
}
}

四、误差分析及改进

该实例是控制点阵显示的程序,不涉及时间,也就没有时间的误差。但是主程序中用的是扫描法检测是否有键盘控制输入,而且扫描过程中还插入了显示动态笑脸界面的程序段,扫描程序显得稍有冗长,所以短暂的按键可能没有被程序扫描到。

为了解决这个问题,可以让扫描程序变得简短清晰些,所以,将动态笑脸改为了静态的笑脸。对键盘的操作时间(即按键的时间)要适当长些,以便被程序捕捉。为了便于控制时间的长短,在程序中利用了蜂鸣器的功能,一旦按键操作被程序扫描到,蜂鸣器蜂鸣,以提示操作者键盘操作有效。

程序不足之处是:
1.键盘的操作不够灵敏。
2.只能在一次滚动结束后,即再次出现一个静态笑脸时才能够操作键盘。

如果改为中断法响应键盘,或许会更灵敏些。这需要四个中断服务程序处理按键事件。并且把实现不同方向滚动的程序段放在终端服务程序之外,可以解决第二个不足之处,即可以在滚动过程中,响应不同的按键。


Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top