led点阵屏发光亮度强,指示效果好,可以制作运动的发光图文,更容易吸引人的注意力,信息量大,随时更新,有着非常好的广告和告示效果。笔者此处就led点阵屏动态扫描显示作一个简单的介绍。
1. led点阵屏显示原理概述
图1-1为一种8x8的led点阵单色行共阳模块的内部等效电路图,对于红光led其工作正向电压约为1.8v,其持续工作的正向电流一般10ma左右,峰值电流可以更大。如下图,当某一行线为高电平而某一列线为低时,其行列交叉的点就被点亮,当某一行线为低电平时,无论列线如何,对应的这一行的点全部为暗。led点阵屏显示就是通过一定的频率进行逐行扫描,数据端不断输入数据显示,只要扫描频率足够高,由于人眼的视觉残留效应,就可以看到完整的文字或图案信息。通常有4、8、16线扫描方式,扫描行数越少,点阵的显示亮度越好,但相应硬件数据寄存器需求也越多。
图1-1 点阵内部原理图
2. 硬件设计
微控制器的io口均不能流过过大的电流,led点亮时有约10ms的电流,因此led点阵引脚不要直接接单片机io口,应先经过一个缓冲器74hc573。单片机io口只需很小的电流控制74hc573即可间接的控制led点阵某一行(或某一列),而74hc573输出也能负载约10ms的电流。设置led每点驱动电流为id=15ma,这个电流点亮度好,并且有一定的裕度,即使电源输出电压偏高也不会烧毁led,限流电阻值r = (vcc- vce– vol– vled) / idvcc为5v供电,vce为三极管c、e间饱和电压,估为0.2v, vol为74hc573输出低电平时电压,不同灌电流,此值不一样,估为0.2v,具体查看规格书,vled为红光驱动电压,估为1.7v,根据上式可算出限流电阻为r = 200r。
led点阵屏需接收逐个扫描信号,扫描到相应列(或行),对应的列(或行)数据有效,即显示这一列(或行)的信息。一般产生扫描信号是需要采用专门的译码器,如三线八线译码器74hc138,这样可硬件保证任意时刻只有一列(或一行)正在扫描,并且可减少微控制器的io口占用。市面上的51开发板对于led点阵屏的设计基本都没有采用译码器,直接用单片机io产生扫描信号,为兼容软件,笔者此处也不加译码器,软件保证io口产生相应的扫描信号。
当某一列(或一行)led点均点亮时,电流约15max8=90ma流过这一列(或一行)公共端,微控制器io口无法直接驱动这个电流,需加三极管驱动,由于51单片机低电平灌电流较大,因此适合采用pnp三极管作为驱动。三极管基极电流设为2ma即可让三极管饱和,最大驱动电流远大于90ma。基极偏置电阻阻值rb=(vcc- veb– vol) / ibvcc为5v供电,veb为三极管e、b间的导通电压0.7v,vol为单片机io口输出低电平时电压,可根据规格书估为0.2v,故rb= 2k即可。
图2-1 8x8共阴led点阵原理图
3. 驱动实现
led点阵数据口接p0口,扫描选择线接p2口的0~7位。对于动态扫描,都是有一个扫描频率的,led屏扫描频率下限为50hz,低于一定的扫描频率,显示会闪烁。频率过高,则亮度较差且占用cpu资源。一般整个屏扫描一遍时间为约10ms较合适(即扫描频率100hz),我们采用的是8线扫描方式,每一行点亮时间为1.5ms,扫描一遍为12ms。为保证这个刷新频率,通常是通过定时器来周期性进行点阵屏刷新。
显示屏显示往往会涉及到画点、画线、画图等复杂的运算,改变屏幕的信息,只需处理显存中的数据,因此对于显示屏,是需要开辟出一块内存空间作为显存使用的。8x8点阵每个点可用1 bit表示,一行1字节,显存8字节即可。由于点阵屏像素点太少,没有必要实现画线、画图等复杂操作,笔者此处仅对点阵屏画点、文字上下左右移动进行代码实现。
点阵屏动态显示功能模块文件matrix.c内容如下:
#include“reg52.h”
#include“matrix.h”
// 每个led点需1位保存,8x8点阵需8字节显存
static unsigned char framebuffer[8];
// 外部模块通过该函数获得显存内存位置进行处理
unsigned char *matrixgetbuffer()
{
return framebuffer;
}
// 点阵刷新,保证以一定周期调用刷新
void matrixscan()
{
static unsigned char select =0; // 记录扫描的选择线
// 列数据输出到点阵数据端口
matrixoutputdata(framebuffer[select]);
// 扫描信号输出到点阵扫描选择端口
matrixoutputselect(select);
select++; // 进入到下一行扫描
if (select 》= 8) {
select= 0; // 所有行已扫描,回到第一行再次开始扫描
}
}
// led点阵屏打点函数,对(x, y)位置进行亮,灭,状态取反
voidmatrixsetpoint(unsigned char x, unsigned char y, unsigned char operation)
{
if (x》7 “| y》7) { // 位置保证在点阵屏区域内
return;
}
switch (operation) {
case set: // (x, y)位置置位,灯灭
framebuffer[x] |= 1《《 y;
break;
case clear: // (x, y)位置清零,灯亮
framebuffer[x] &= ~(1《《 y);
break;
case negate: // (x, y)位置取反,灯状态改变
framebuffer[x] ^= 1《《 y;
break;
default:
break;
}
}
// led点阵屏清屏,显存对应1的位置,灯灭,0相应的灯才点亮
voidmatrixclearscreen()
{
unsigned char i;
for (i=0; i《8; i++) {
framebuffer[i] = 0xff;
}
}
// 点阵平移,上下左右四个方向平移1,平移空缺位置用数据filling填充
void matrixmove(unsignedchar direction, unsigned char filling)
{
unsigned char i;
switch (direction) { // 判断平衡的方向
case move_up: // 向上平移1,每列数据第7位移到第6位,如此类推
for (i=0; i《8; i++) {
framebuffer[i] =(framebuffer[i]》》1) | ((filling《《(7-i))&0x80);
}
break;
case move_down: // 向下平移1,每列数据第0位移到第1位,如此类推
for (i=0; i《8; i++) {
framebuffer[i]= (framebuffer[i]《《1) | ((filling》》i)&0x01);
}
break;
case move_left: // 向左平移1,右一列的数据移到当前列中,如此类推
for (i=0; i《7; i++) {
framebuffer[i] = framebuffer[i+1];
}
framebuffer[i] = filling;
break;
case move_right: // 向右平移1,左一列的数据移到当前列中,如此类推
for (i=7; i》=1; i--) {
framebuffer[i] = framebuffer[i-1];
}
framebuffer[i] = filling;
break;
default:
break;
}
}
我们在点阵屏模块头文件matrix.h中实现模块的宏定义及接口访问宏实现,使之方便移植及修改接口配置。模块头文件同时也引出模块的接口函数,如matrixscan()为点阵屏刷新函数,需周期性调用刷新点阵屏显示。点阵屏动态显示功能模块文件matrix.h内容如下:
#ifndef__matrix_h__
#define__matrix_h__
#ifdef__cplusplus
extern”c“ {
#endif
#define set 0x1 //置1操作
#define clear 0x2 // 清0操作
#define negate 0x3 //取反操作
#definemove_up 0x1 // 向上平移1
#definemove_down 0x2 // 向下平移1
#definemove_left 0x3 // 向左平移1
#definemove_right 0x4 // 向右平移1
// 列数据输出到p0口
#definematrixoutputdata(dat) {p0 = (dat);}
// p2口输出对应列的扫描选择线,低有效
#definematrixoutputselect(select) {p2 = ~(1《《(select));}
voidmatrixclearscreen(void);
voidmatrixmove(unsigned char direction, unsigned char filling);
unsigned char*matrixgetbuffer(void);
voidmatrixscan(void);
voidmatrixsetpoint(unsigned char x, unsigned char y, unsigned char operation);
#ifdef__cplusplus
}
#endif
#endif/*__matrix_h__*/
外部应用通过引入点阵屏的模块头文件matrix.h来实现调用点阵屏驱动函数,简单测试调用(心形在点阵屏内随机平移)实现如下:
#include”reg52.h“
#include”matrix.h“
// 心形坐标数据
static unsigned charcode heartshape[][2] = {
{3, 3}, {4, 2}, {5,3}, {5, 4}, {4, 5},
{3, 6}
来源;21ic
汽车BMS电流传感器的作用和技术要求
iOS越狱:开发者确认iOS 10.2将新增iPhone7设备的支持
代工还是研究实验室?创新源于何处?
中国芯片行业的老兵,从游戏机芯片起步,现在又走在了AI的潮头
摩摩哒眼部冷热按摩器,让我们更爱护我们的眼睛
51单片机实现LED点阵屏动态扫描显示的设计
应用案例 | 大尺寸玻璃盖板高精度快速定位,误差<0.005mm
中国电信任韦乐平表示AI正成为应对5G挑战的用力工具
华为Mate60Pro搭载麒麟9000s 强于骁龙888
电气装配技术5大规范
罗克韦尔PLC通讯身份认证的漏洞分析
讯维高清混合矩阵切换器的未来发展前景
智能医疗的现状:缺少核心运营平台的引爆点
LED台灯也分男女?适合颜控的家居风格
黄奇帆:《5G背景下金融科技的特征和发展路径》
中国5G建设速度有多快?
分享PCB布线设计规则检查分析
首届中南大学新能源科技大会在长沙开幕
Spring Cloud Feign总结问题,注意点,性能调优,切换okhttp3
芯片封装烧结银工艺