虽然单片机可以驱动液晶屏,但是在实际的应用领域,数码管仍然是主流的显示器件。
如果提到多位数码管显示,一般都要讲各个位轮流显示的动态显示技术。
这种方法虽然可以节省单片机的输出接口,但是使得单片机的软件负担较重,程序必须保证不间断的显示,否则就会出现亮度不均、闪烁、或停止发光的现象。
MAX7219是一块专用的LED显示驱动芯片,它能够以动态形式驱动8位数码显示器。
还可以用 n 片MAX7219进行级连,以驱动8 * n位数码显示。
MAX7219与数码显示器的之间的电路极为简单,几乎连限流电阻都不用。
MAX7219与单片机之间也仅仅需要连接3条引线。
当单片机把数据送到MAX7219后,它就可以独立的进行动态扫描显示,无需单片机再进行干预。
对于单片机来说,这些数码显示器,看起来似乎都是在进行静态显示。
MAX7219可以说是驱动多位数码显示器的最佳选择。
DIP封装的MAX7219芯片如下:
MAX7219需要初始化,按照规则,设置一些东西。
用数码管显示数字,可以设置为:译码和非译码,两种方式。
利用MAX7219驱动数码管的显示电路如下:
图片链接:http://xiangce.baidu.com/picture/detail/feedf64b49d2e5192469b151b556780582b97ee9
MAX7219还可以驱动8 * 8点阵模块,仿真截图如下:
图片链接:http://xiangce.baidu.com/picture/detail/bc7297044e6f36dbc04ab92b5b9e00dfdf5d30e9
在上面的点阵图中,执行的还是原来驱动数码管的程序,把数码管的各个段,显示在各个点上。
仔细看看点阵的显示,还能看出来是显示“51--7219”的段码吗?
用MAX7219驱动点阵模块,应该采用非译码形式,然后认真编写需要显示的各个点阵数据,再输出到MAX7219即可。
显示“I love U”的点阵画面如下:
看出来了吗?有一行,需要从最下面,移动到最上面去,然后再编写点阵。
上图电路的显示程序如下:
//================================================
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define DecodeMode 0x09 //译码模式寄存器
#define Intensity 0x0a //亮度寄存器
#define ScanLimit 0x0b //扫描位数寄存器
#define ShutDown 0x0c //低功耗模式寄存器
#define DisplayTest 0x0f //显示测试寄存器
#define ShutdownMode 0x00 //低功耗方式
#define NormalOperation 0x01 //正常操作方式
#define ScanDigit 0x07 //扫描位数设置,显示8位数码管
#define DecodeDigit 0xff //译码设置,8位均为BCD码
#define IntensityGrade 0x0a //亮度级别设置
#define TestMode 0x01 //显示测试模式
#define TextEnd 0x00 //显示测试结束,恢复正常工作模式
sbit DIN = P2^0; //MAX7219串行数据输入
sbit CLK = P2^2; //MAX7219串行时钟
sbit LOAD = P2^1; //MAX7219显示数据锁存控制
uchar Disp_Buff[8] = {9, 1, 2, 7, 10, 10, 1, 5};//定义显存
//**********延时t毫秒***************************
void delay(uint t)
{
uint i;
while(t--) for (i = 0; i < 125; i++);
}
//**********向MAX7219写入一字节*****************
void SendChar (char ch)
{
char i, temp;
for (i = 0; i < 8; i++) { //8位
temp = ch & 0x80; //取最高位
CLK = 0; //时钟线置低
if(temp) DIN = 1;
else DIN = 0;
ch = ch << 1; //左移一位
CLK = 1; //上升沿,DIN的数据写入到7219
}
}
//**********向MAX7219寄存器写入数据*************
void WriteWord (char addr, char num)
{
LOAD = 0; _nop_();
SendChar(addr); _nop_();
SendChar(num); _nop_();
LOAD = 1; //锁存
}
//**********把显存内容写入MAX7219***************
void Write7219 (void)
{
char i;
for (i = 0; i < 8; i++) WriteWord(i + 1, Disp_Buff[i]);
//7219的数据寄存器编号: 1~8
}
//**********MAX7219初始化***********************
void InitDisplay (void)
{
WriteWord(ScanLimit, ScanDigit); //设置扫描界限
WriteWord(DecodeMode, DecodeDigit); //设置译码模式
WriteWord(Intensity, IntensityGrade); //设置亮度
WriteWord(ShutDown, NormalOperation); //设置为正常工作模式
}
//----------------------------------------------
void main(void)
{
uchar i, j, k;
uchar code data_ilu[4][8] = { //I love U !
0x00,0x00,0xc0,0xff,0xff,0xc0,0x00,0x00, // I
0x1c,0x3e,0x3f,0x9f,0x9f,0x3f,0x3e,0x1c, //桃心
0x00,0x7f,0xff,0x81,0x81,0xff,0x7f,0x00, // U
0x00,0x00,0x00,0xfd,0xfd,0x00,0x00,0x00}; // !
InitDisplay(); //MAX7219初始化
WriteWord(DisplayTest, TestMode); //显示测试,点亮所有LED
delay(1000); //延时约1s
WriteWord(DisplayTest, TextEnd); //退出显示测试
WriteWord(DecodeMode, 0x00); //8位皆为非译码
for (k = 0; k < 8; k++) Disp_Buff[k] = 255;
Write7219(); //将缓存内容写入7219
while(1) {
for (i = 0; i < 4; i++) {
for (j = 0; j < 8; j++) {
for (k = 7; k > 0; k--) Disp_Buff[k] = Disp_Buff[k - 1];
Disp_Buff[0] = data_ilu[i][j];
Write7219(); //将缓存内容写入7219
delay(300); //延时约300ms
}
if (j == 8 && i != 3) delay(1000);
} }
}
//================================================