资源描述
单片机控制LED显示屏系统
选修课电子设计报告
XXXXXX班 XXX 10021189
系统简介
单片机是一种集成在电路芯片,采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计时器等多种功能集成到一块硅片上构成的一个小而完善的计算机系统,该系统小巧,功能多样且易于开发使用。而51单片机是对目前所有兼容Intel 8031指令系统的单片机的统称,且该系列单片机已经成为目前应用最广泛的8位单片机之一,其代表型号是ATMEL公司的AT89系列,它广泛应用于工业测控系统之中。
而LED显示屏,也是一个被广泛应用在在人们的日常生活中的设备。在商场、车站、以及银行等各类办事窗口等越来越多的场所,我们可以看见LED点阵显示文本信息。其由于耗电量低、使用寿命长、成本低、亮度高、规格品种多等诸多优点,可以满足各种不同应用场景的需求,可以说具有非常广阔的发展前景。然而目前市场上的LED显示屏大多都需要固定在特定位置,并且显示内容的更改需要连接PC机或插入移动存储器来实现。这使得大部分LED显示屏不能随意改变摆放位置。虽然少部分LED显示屏可以实现便携功能,但其只能通过外接移动存储器来输出显示内容,这导致LED显示屏的诸多优势不能完全体现。
正是由于单片机提供了操作简单的IR红外接收模块,我们可以考虑采用单片机和LED显示屏结合起来,用红外遥控的方式来控制单片机,继而再利用单片机控制LED显示屏的输出,最终实现遥控LED显示屏的效果。
以下所阐述的系统,是我们小组采用SST单片机作为控制核心,外接红外接收探头及LED扩展板为硬件基础构建了LED显示屏,从硬件上为便携、遥控等预期功能提供了基础。在代码编写方面,我们集成了现有比较完善的单片机的红外解码技术、蜂鸣器及LED点阵显示,并自主编写了屏幕显示的滚动效果的相关代码。
系统原理
为了更清楚的展示系统原理,先将该系统划分为3个子系统:红外接收系统,数据储存系统,以及信息展示系统。
首先,当用户按下遥控器上的某个按钮时,遥控器会发出一组脉冲。而红外接收系统的任务就是将接收到的物理脉冲进行解码,获得用户按钮信息,也就是让单片机捕捉到用户按下了哪个按钮。接着,数据储存系统会将用户按钮信息转换为该按钮对应的功能,比如字母键、清空键、滚动键等等,若用户输入的是文本,便将该文本存储在一个数组中。最后,信息展示系统会自动提取数据中存储的信息,控制其在LED展示屏上滚动显示。三个子系统通过中断触发,协同运,组成了整个LED显示系统(如下图所示)。
1 红外接收系统
人眼能看到的可见光按波长从长到短排列,依次为红、橙、黄、绿、青、蓝、紫。其中红光的波长范围为0.62~0.76μm;紫光的波长范围为0.38~0.46μm。比紫光的波长还短的光叫紫外线,比红光的波长还长的光叫红外线。红外线遥控就是利用波长为0.76~1.5μm之间的近红外线来传送控制信号的。对于红外线遥控器发出红外波的原理,再此不予讨论,我们仅研究将接收到的红外信号转化为我们可以利用的数据。
当用户一个键按下超过22ms,遥控器上的振荡器使芯片激活,将发射一组108ms的编码脉冲。由位置1的波形得知,这108ms发射代码由一个起始码(9ms),一个结果码(4.5ms),低8位地址码(用户编码)(9ms~18ms),高8位地址码(用户编码)(9ms~18ms),8位数据码(键值数据码)(9ms~18ms)和这8位数据的反码(键值数据码反码)(9ms~18ms)组成。如果按下超过108ms仍未松开,接下来发射的代码(连发代码由位置3所示)将仅由起始码(9ms)和结束码(2.5ms)组成。通过红外线接收头可接收这些信号,并且启用单片机外部中断来暂停LED运行来处理信号,之后经过特定程序的解码,我们便可以得到遥控器上各个按键的对应取值,也就是得到了用户所按的按键。
这里解码的关键是如何识别“0”和“1”。从位的定义我们可以发现“0”、“1”均以0.56ms的低电平开始,不同的是高电平的宽度不同,“0”为0.56ms,“1”为1.68ms,所以必须根据高电平的宽度区别“0”和“1”。如果从0.56ms低电平过后,开始延时,0.56ms以后,若读到的电平为低,说明该位为“0”,反之则为“1”,为了可靠起见,延时必须比0.56ms长些,但又不能超过1.12ms,否则如果该位为“0”,读到的已是下一位的高电平,因此取(1.12ms+0.56ms)/2=0.84ms最为可靠,一般取0.84ms左右均可。并且,应该等待9ms的起始码和4.5ms的结果码均完成后才能读码。
2 数据储存系统
红外线遥控器上每个按键都对应了一组键值(如“16”对应按键“0”,“0C”对应按键“1”等)。解码完毕我们就可以得到这个用户按下的按键键值。通过匹配内置的键值表,系统就能识别出用户的按键信息:数字键、清空键、退格键、速度调节键、启动键等等。经过若干条件语句的筛选,可以对不同用户行为进行相应动作:
当用户按下数字按键时,单片机内部的专用数组就会按顺序记录该按键对应的数值(0~9)。(当然这只是初步的调试。当系统更加完善之后,还要增加将数字转换为字母的子过程)。当用户按下退格键时,数组将会剔除最新一个字符,也就是退格效果;当用户按下清空键时,输出重置,恢复空数组。当用户按下速度调节键,系统会相应增加或减少变量“speed”的值,用于之后控制LED显示滚动速度的调整。当用户按下启动键后,信息展示系统被激活,开始LED显示屏的滚动文本显示。
3 信息展示系统
以逐行扫描方式的LED点阵为例。行编码决定哪一行被接通(相当于位码,如下面第一幅图为第一行接通的情况),列编码决定该行上的哪些LED点亮(相当于段码,如下面第一幅图为第二至第七和LED点亮)。行从上向下扫描即显示出一帧完整的图像。利用视觉暂留原理,以很快的速度依次亮起LED,使人眼无法区别先后亮起顺序,于是得到了LED屏幕完整的可见内容。
人眼观察到的图象如图所示:
以上为LED点阵静态显示的原理。但仅仅是静态显示远远不能满足我们的需要。由于需要显示的文本长度较长,故不可能把所有数据都只显示在一个屏幕内,所以我们需要动态的滚动显示。也就是在静态显示的基础上,每隔Δt时间,将前一个文字左移一个单位,后一个文字进入屏幕内一个单位,然后继续保持静态输出,之后再隔Δt时间重复上述步骤,于是就形成了滚动效果,如下图展示了文本“58”的滚动效果。
当用户按下启动按键后,单片机进入一个永久循环,其中一个计数器不断累加,每到能被“speed”变量整除的时间点,屏幕内容便会向左位移一列,此时就形成了新的一帧画面,此画面将被循环扫描直到下一个整除时间点的出现。通过改变除数的大小来改变每一帧画面的扫描次数,由此就实现了滚动速度的调节,实现文字一个一个的从右向左滚动出现的效果。当用户输入的文字全部显示一遍之后,会出现若干空格,标志着第一遍已经显示完毕,之后会重新回到第一个字的滚动显示,形成不断循环往复出现的信息展示屏。
使用方法
接通电源,数码管显示0,代表目前没有字符。按下数字键0~9,点阵显示对应文本,同时数码管示数增加,代表目前文本区有若干字符待显示。按下退格键,数码管示数减小,代表字符被删除。按下清空,数码管回复显示0,代表文本被清空。编辑好带显示文本后,按下“滚动/停止”按钮,字符看是循环滚动。此时按速度调节按钮可以改变滚动速率。同时在滚动状态不可编辑文本内容,停止滚动后回复编辑文本状态。
单片机源代码
//2012.3.27
//P0--J12(排线)
//P2--J20(排线)
//P1-JP3(排线)
//P3.5--J8 蜂鸣器(单线)
//遥控LED显示板,最多存储9个数字,滚动播放,退格、清空、速度调节。
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
#define SPEED 8
void delay(uchar x); //x*0.14MS
void delay1(int ms);
void beep();
sbit IRIN = P3^2; //红外接收器数据线
sbit BEEP = P3^5; //蜂鸣器驱动线
unsigned char code IRCode[] = "160C185E081C5A42524A0D19441509"; //解码结果对应表
unsigned char code LEDCode[] = {~0x3F,~0x06,~0x5B,~0x4F,~0x66,~0x6D,~0x7D,~0x07,~0x7F,~0x6F}; //数码管段选
unsigned char code tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //逐列开启
unsigned char code digittab[11][8]={
{0x00,0x00,0x3e,0x41,0x41,0x41,0x3e,0x00}, //0 的第1列,2....8
{0x00,0x00,0x00,0x00,0x21,0x7f,0x01,0x00}, //1
{0x00,0x00,0x27,0x45,0x45,0x45,0x39,0x00}, //2
{0x00,0x00,0x22,0x49,0x49,0x49,0x36,0x00}, //3
{0x00,0x00,0x0c,0x14,0x24,0x7f,0x04,0x00}, //4
{0x00,0x00,0x72,0x51,0x51,0x51,0x4e,0x00}, //5
{0x00,0x00,0x3e,0x49,0x49,0x49,0x26,0x00}, //6
{0x00,0x00,0x40,0x40,0x40,0x4f,0x70,0x00}, //7
{0x00,0x00,0x36,0x49,0x49,0x49,0x36,0x00}, //8
{0x00,0x00,0x32,0x49,0x49,0x49,0x3e,0x00}, //9
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //空白
};
int list[10];
int length;
int run;
uchar IRCOM[7];
unsigned char j,time,shift;
int speed=SPEED;
main()
{
unsigned char i,line;
int ch1,ch2;
IRIN=1; //I/O口初始化
BEEP=1;
delay1(10); //延时
IE = 0x81; //允许总中断中断,使能 INT0 外部中断
TCON = 0x01; //触发方式为脉冲负边沿触发
length=0;
P1=LEDCode[0];
list[0]=10;
run=0;
while(1)
{
if (run==0)
{
for (i=0;i<8;i++)
{
P0=digittab[10][0]; //空白
P2=tab[i];
P0=digittab[list[length]][i];
delay(10);
}
}
if (run==1)
{
time++;
if (time%speed==0) //滚动
{
shift++;
if (shift==8)
{
shift=0;
P1=LEDCode[j%10];
if (length==0){j=0;ch1=list[0];ch2=list[0];} //空字符
else
{
ch1=list[j];
if (j==0) time=1;
if (j+1>length) {ch2=list[0];j=0;} else {ch2=list[j+1];j++;}
}
}
}
line=0;
for (i=shift;i<8;i++) //第i列
{
P0=digittab[10][0]; //空白
P2=tab[line];
P0=digittab[ch1][i];
line++;
delay(10);
}
for (i=0;i<shift;i++) //第i列
{
P0=digittab[10][0]; //空白
P2=tab[line];
P0=digittab[ch2][i];
line++;
delay(10);
}
}
}
}
void IR_IN() interrupt 0 using 0 //中断,IR解码
{
unsigned char i,j,k,N=0;
EX0 = 0; //外部中断:禁止
delay(15);
if (IRIN==1) //确认IR信号出现
{
EX0 =1;
return;
}
while (!IRIN) {delay(1);} //等IR变为高电平,跳过9ms的前导低电平信号。
for (j=0;j<4;j++) //收集四组数据
{
for (k=0;k<8;k++) //每组数据有8位
{
while (IRIN) {delay(1);} //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
while (!IRIN) {delay(1);} //等 IR 变为高电平
while (IRIN) //计算IR高电平时长
{
delay(1);
N++;
if (N>=30)
{
EX0=1;
return;
} //0.14ms计数过长自动离开。
} //高电平计数完毕
IRCOM[j]=IRCOM[j] >> 1; //数据最高位补“0”
if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;} //数据最高位补“1”
N=0;
}
}
if (IRCOM[2]!=~IRCOM[3]) {EX0=1; return;}
IRCOM[5]=IRCOM[2] & 0x0F; //取键码的低四位
IRCOM[6]=IRCOM[2] >> 4; //右移4次,高四位变为低四位
if(IRCOM[5]>9) {IRCOM[5]=IRCOM[5]+0x37;}
else IRCOM[5]=IRCOM[5]+0x30;
if(IRCOM[6]>9) {IRCOM[6]=IRCOM[6]+0x37;}
else IRCOM[6]=IRCOM[6]+0x30;
//解码完成,第一位:IRCOM[6] 第二位:IRCOM[5]
N=-1;
for(i=0;i<=14;i++)
{
if ((IRCOM[6]==IRCode[2*i])&&(IRCOM[5]==IRCode[2*i+1])) {N=i;}
}
//N:键值(0~9数字,10清空,11退格,12滚动, 13、14速度)
if (run==0)
{
if ((N>=0)&&(N<10)&&(run==0))
{
length++;
list[length]=N;
}
else if (N==10) length=0;
else if (N==11) {if (length>0) length--;}
P1=LEDCode[length%10];
}
if (N==12) {if (run==0) {j=0;time=0;shift=7;run=1;}else {run=0;P1=LEDCode[length%10];}}
if (N==14) if (speed>2) speed-=2;
if (N==13) if (speed<20) speed+=2;
beep();
EX0 = 1;
}
/*蜂鸣器*/
void beep()
{
unsigned char i;
for (i=0;i<100;i++)
{
delay(4);
BEEP=!BEEP; //BEEP取反
}
BEEP=1; //关闭蜂鸣器
}
/*延时函数*/
void delay(unsigned char x) //x*0.14MS
{
unsigned char i;
while(x--)
{
for (i = 0; i<13; i++) {}
}
}
void delay1(int ms)
{
unsigned char y;
while(ms--)
{
for(y = 0; y<250; y++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
系统特点
这款LED显示屏主要有以下两个特点:体积小便于移动,以及显示内容遥控,可及时迅速改变。它的摆放位置可以十分灵活并且可以通过修改显示内容在多个应用场合之间迅速转换功能。由于这个特点,该系统适用于中小型活动中的展示任务,比如它可以在校园活动中充分发挥一定的作用。
系统局限
由于所配遥控器的键位个数有限,我们无法使用该款遥控器输入除空格键以外的标点符号,否则会导致输入法过于繁琐。一方面考虑到在LED显示屏的显示内容中不会存在过于复杂的特殊符号,另一方面考虑到遥控器的键位可扩展性,我们设计的便携式遥控LED显示屏可以通过改进在实际应用中完成对常用标点符号的输入,而这一改进会使LED显示屏的显示内容更加符合人们需求。
从另一方面来看,该便携式遥控LED显示屏采用的红外遥控解码技术是单片机通用的红外解码方式。这将导致任意一个相同型号的遥控器均可以直接遥控并修改LED显示屏的显示内容。由于任意拥有相同型号的遥控器的人可以未经允许修改显示屏显示内容,这对于实际需求来说是非常不安全,也是不方便的(比如两个系统无法同时使用)。对于这个缺陷的改进,可以修改遥控器红外线的发射频率使得每一个LED显示屏都对应唯一的红外线频率,这样只有与相应LED显示屏对应的遥控器才能控制显示屏的显示内容。
展开阅读全文