Arduino案例实操 -- 点阵屏汉字显示(MAX7219级联)

LED点阵屏

LED点阵屏通过LED(发光二极管)组成,以灯珠亮灭来显示文字、图片、动画、视频等,是各部分组件都模块化的显示器件,通常由显示模块、控制系统及电源系统组成。LED点阵显示屏制作简单,安装方便,被广泛应用于各种公共场合,如汽车报站器、广告屏以及公告牌等。
在这里插入图片描述

显示原理

以简单的8X8点阵为例,它共由64个发光二极管组成,且每个发光二极管是放置在行线和列线的交叉点上,当对应的某一行置1电平,某一列置0电平,则相应的二极管就亮。
在这里插入图片描述模块外围有16个引脚,序号如下。
在这里插入图片描述
而内部线序却不与外部引脚一致,点亮点阵屏中的LED需要按照内部线序来操作,如要将第一个点点亮,则9脚接高电平13脚接低电平,则第一个点就亮了;如果要将第一行点亮,则第9脚要接高电平,而(13、3、4、10、6、11、15、16)这些引脚接低电平,那么第一行就会点亮;如要将第一列点亮,则第13脚接低电平,而(9、14、8、12、1、7、2、5)接高电平,那么第一列就会点亮。
在这里插入图片描述

8x8点阵屏引脚连接

如上一节介绍,要正常点亮LED点阵需要连接16根线,也就是需要用到16个IO口,根据内部线序正确连接LED点阵的正极引脚和负极引脚(实质上为内部LED点亮的正极引脚与负极引脚);点阵屏的(9, 14, 8, 12, 1, 7, 2, 5)分别连接Arduino控制板的(6,11, 5, 9, 14, 4, 15, 2),这8个引脚为内部LED的正极引脚,点阵屏的(13, 3, 4, 10, 6, 11, 15, 16)分别连接开发板的(10,16, 17, 7, 3, 8, 12, 13),这8个引脚为内部LED的负极引脚。(如果你用的控制板是UNO和NANO这些,模拟引脚A0 - A5 也可以当点阵屏的控制引脚

LED点阵屏 Arduino UNO
正极引脚连接
9 6
14 11
8 5
12 9
1 A0
7 4
2 A1
5 2
负极引脚连接
13 10
3 A2
4 A3
10 7
6 3
11 8
15 12
16 13

8x8点阵屏代码编写

int leds[8] = {
    
    6, 11, 5, 9, A0, 4, A1, 2}; 		//点阵屏正极引脚
int gnds[8] = {
    
    10, A2, A3, 7, 3, 8, 12, 13}; 	//点阵屏负极引脚

void setup() {
    
    
  for (int i = 0; i < 8; i++)
  {
    
    
  	//将所有引脚配置为输出引脚
    pinMode(leds[i], OUTPUT);
    pinMode(gnds[i], OUTPUT);
    
    digitalWrite(gnds[i], HIGH); 	//内部LED负极引脚给高电平,熄灭所有LED
  }
}

//点亮点阵屏
void ledopen()
{
    
    
  //将点阵屏正极引脚拉高,负极引脚拉低,开启显示
  for (int i = 0; i < 8; i++)
  {
    
    
    digitalWrite(leds[i], HIGH);
    digitalWrite(gnds[i], LOW);
  }
}

//熄灭点阵屏
void ledclose()
{
    
    
  //将点阵屏正极引脚拉低,负极引脚拉高,关闭显示
  for (int i = 0; i < 8; i++)
  {
    
    
    digitalWrite(leds[i], LOW); 
    digitalWrite(gnds[i], HIGH);
  }
}

//逐列扫描
void ledCol()
{
    
    
  for (int i = 0 ; i < 8; i++)
  {
    
    
    digitalWrite(gnds[i], LOW); 
    for (int j = 0; j < 8; j++)
    {
    
    
      digitalWrite(leds[j], HIGH);
      delay(40);
    }
    digitalWrite(gnds[i], HIGH);
    ledclean();
  }
}

//逐行扫描
void ledRow()
{
    
    
  for (int i = 0 ; i < 8; i++)
  {
    
    
    digitalWrite(leds[i], HIGH);
    for (int j = 0; j < 8; j++)
    {
    
    
      digitalWrite(gnds[j], LOW);
      delay(40);
    }
    digitalWrite(leds[i], LOW);
    ledclean();
  }
}

void loop() {
    
    

  ledopen(); 	//点阵屏打开
  delay(500);
  ledclose(); 	//点阵屏关闭
  delay(500);
  ledCol(); 	//列扫描
  ledRow(); 	//行扫描

}

8x8点阵屏实验现象

根据程序控制的效果,点阵屏的显示为全亮,全灭,列扫描,行扫描,如下。
在这里插入图片描述

MAX7219

传统的点阵模块点亮需要用到16个IO引脚,这对IO口有限的控制板来说负担太大,接线也变得相对复杂,因此有了新的LED点阵屏解决方案 – MAX7219。

MAX7219 是美国MAXIM 公司推出的多位LED 显示驱动器,采用3 线串行接口传送数据,可直接与单片机接口连接,用户能方便修改其内部参数,以实现多位LED 显示。它内含硬件动态扫描电路、BCD译码器、段驱动器和位驱动器。此外,其内部还含有8X8 位静态RAM,用于存放8 个数字的显示数据。显然,它可直接驱动64 段LED点阵显示器。当多片MAX7219 级联时,可控制更多的LED 点阵显示器。显示的数据通过单片机数据处理后,送给MAX7219 显示。
在这里插入图片描述

MAX7219/MAX7221是一种集成化的串行输入/输出共阴极显示驱动器,它连接微处理器与8位数字的7段数字LED显示,也可以连接条线图显示器或者64个独立的LED。其上包括一个片上的B型BCD编码器、多路扫描回路,段字驱动器,而且还有一个8*8的静态RAM用来存储每一个数据。 只有一个外部寄存器用来设置各个LED的段电流。 MAX7221与SPI™、 QSPI™以及 MICROWIRE™相兼容,同时它有限制回转电流的段驱动来减少EMI(电磁干扰)。 一个方便的四线串行接口可以联接所有通用的微处理器。 每个数据可以寻址在更新时不需要改写所有的显示。MAX7219/MAX7221同样允许用户对每一个数据选择编码或者不编码。 整个设备包含一个150μA的低功耗关闭模式,模拟和数字亮度控制,一个扫描限制寄存器允许用户显示1-8位数据,还有一个让所有LED发光的检测模式。
在这里插入图片描述

MAX7219内部原理框图

在这里插入图片描述

MAX7219典型应用框图

关于MAX7219的应用框图如下,控制器连接MAX7219输入端,MAX7219控制端连接8位数码管或者是8x8LED点阵屏。同时也不要被图片的接线所误导,图中DIG 0 - DIG
7
是指的MAX7219 DIG0,DIG1,DIG2,DIG3,DIG4,DIG5,DIG6,DIG7这7个引脚,同理SEG A-G,SEG DP也是指的MAX7219的8个引脚。
在这里插入图片描述

扫描二维码关注公众号,回复: 12640018 查看本文章
  • DIN引脚:串行数据输入端口。在时钟上升沿时数据被载入内部的16位寄存器。 2,3,5-8,10,11 DIG 0–DIG7 八个数据驱动线路置显示器共阴极为低电平。关闭时7219此管脚输出高电平,7221呈现高阻抗。
  • LOAD 引脚(MAX7219): 载入数据。连续数据的后16位在LOAD端的上升沿时被锁定。CS (MAX7221) 片选端。该端为低电平时串行数据被载入移位寄存器。连续数据的后16位在cs端的上升沿时被锁定。
  • CLK 引脚:时钟序列输入端。最大速率为 10MHz.在时钟的上升沿, 数据移入内部移位寄存器。 下降沿时, 数据从DOUT端输出。对MAX7221来说,只有当cs端为低电平时时钟输入才有效。
  • DIG0~DIG7:8位LED位选线,从共阴极LED中吸入电流。
  • SEG A~SEG G 、SEG DP :7段驱动和小数点驱动。

简单来说,MAX7219芯片可以驱动一块8x8的LED点阵,而连接控制板的就只需要3根线,即采用MAX7219方案只需要3根线可以控制一块8x8LED点阵屏。

MAX7219点阵显示模块

MAX7219点阵显示模块,通过16位数据串行输入输出方式完成控制64个LED,全程仅需3个IO口。市面上售卖的MAX7219点阵显示模块有两种规格,如下面的横向级联式:
在这里插入图片描述
靠近MAX7219芯片一端的是输入引脚,另一端是级联下一个MAX7219点阵显示模块的输出引脚,同样是5个引脚,只是输入的DIN引脚变为输出的DOUT引脚;可级联多个点阵模块,但基本只能是作为横向级联用。
下面是另一种规格,因为电路板的大小与点阵屏大小一致或略微小于点阵屏,这样就很方便将8x8点阵屏拼接成16x16或是32x32的大点阵屏:
在这里插入图片描述

点阵显示模块接线

模块接线。

MAX7219点阵模块 Arduino UNO
VCC 5V
GND GND
DIN 5
CS 4
CLK 3

点阵显示模块示例代码

int clk =3;
int cs=4;
int din=5;

unsigned char disp1[12][8]={
    
    
{
    
    0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},		//0
{
    
    0x08,0x18,0x28,0x08,0x08,0x08,0x08,0x08},		//1
{
    
    0x7E,0x2,0x2,0x7E,0x40,0x40,0x40,0x7E},		//2
{
    
    0x3E,0x2,0x2,0x3E,0x2,0x2,0x3E,0x0},			//3
{
    
    0x8,0x18,0x28,0x48,0xFE,0x8,0x8,0x8},			//4
{
    
    0x3C,0x20,0x20,0x3C,0x4,0x4,0x3C,0x0},			//5
{
    
    0x3C,0x20,0x20,0x3C,0x24,0x24,0x3C,0x0},		//6
{
    
    0x3E,0x22,0x4,0x8,0x8,0x8,0x8,0x8},			//7
{
    
    0x0,0x3E,0x22,0x22,0x3E,0x22,0x22,0x3E},		//8
{
    
    0x3E,0x22,0x22,0x3E,0x2,0x2,0x2,0x3E},			//9
{
    
    0x08,0x7F,0x49,0x49,0x7F,0x08,0x08,0x08},		//中
{
    
    0xFE,0xFE,0x92,0xFE,0x9A,0xFE,0x82,0xFE},		//国
};
 
void setup(){
    
    
  //设置引脚为输出
  pinMode(cs,OUTPUT);	
  pinMode(clk,OUTPUT);
  pinMode(din,OUTPUT);

  //初始化MAX7219
  Init_MAX7219();
}

void loop(){
    
    
  char i,j;
 
 //字体扫描显示
  for(j=0;j<12;j++)
  {
    
    
     for(i=1;i<9;i++)
     {
    
    
       Write_Max7219(i,disp1[j][i-1]);
       delay(100);
     }
     delay(500);
  }  
 
}
 
void Write_Max7219_byte(char DATA)         
{
    
    
     char i;    
     digitalWrite(cs,0);                
     for(i=8;i>=1;i--)
     {
    
                      
     	digitalWrite(clk,0);
     	if((DATA&0x80)>0){
    
    
     		digitalWrite(din,1);
        }else{
    
    
        	digitalWrite(din,0);
        }
     	//提取最高位给DIN端口
     	DATA=DATA<<1;			//左移一位
     	digitalWrite(clk,1);
    }                                 
}
void Write_Max7219(char address,char dat)
{
    
     
    digitalWrite(cs,0);
    Write_Max7219_byte(address);           //写入地址,即数码管编号
    Write_Max7219_byte(dat);               //写入数据,即数码管显示数字 
    digitalWrite(cs,1);                        
}
void Init_MAX7219(void)
{
    
    
	Write_Max7219(0x09, 0x00);				//译码方式:BCD码
	Write_Max7219(0x0a, 0x01);				//亮度 
	Write_Max7219(0x0b, 0x07); 				//扫描界限;8个数码管显示
	Write_Max7219(0x0c, 0x01);  			//掉电模式:0,普通模式:1
	Write_Max7219(0x0f, 0x00);
	delay(500); 							//显示测试:1;测试结束,正常显示:0
}

点阵显示模块实验现象

按照代码轮流显示数字 “1 - 9” 以及中文 “中”,“国”,如图8x8点阵用于显示的话最好是显示数字及字母,中文的话显示少比划的字会比较直观,显示笔画较多或者复杂文字的话,就会显得有点尬了,可以参考下面的 “国” 字。
在这里插入图片描述

16x16点阵屏

用于显示文字用16x16点阵屏更为合适,如下16x16的字模预览图。
在这里插入图片描述
市面上级联的点阵屏方案有很多,用于做案例的话基本是用四块8x8的LED拼接成的16x16点阵屏,可以买现成的16x16 LED点阵屏UART控制模块。
在这里插入图片描述
或者是自己动手将四块8x8点阵屏拼接起来,但最好是先跑一编程序过后再将四块8x8点阵屏粘起来或者用透明胶圈在一起,否正将出现以下情况,某块8x8的点阵屏跟其他8x8点阵屏的文字朝向不同,或者四块点阵屏是四个朝向,那就很尴尬了,如下图可以看到左上角的8x8点阵方向与其他点阵屏方向不同,导致一个字不能完整的显示出来。
在这里插入图片描述

16x16点阵屏编程

不管是8x8或16x16的点阵显示,有字模软件都是可以很方便的生成所需字模,例如16x16所要用到的字模软件,很方便的将多个汉字的字模一起提取出来。
在这里插入图片描述

字模提取

需要注意的一点是,字模软件上不管是提取一个汉字或者多个汉字,生成的字模并不是直接就能放进代码里面的,先以一个字为例,“科” 字取模,能得到的一组16进制数组如下:

{
    
    0x00,0x24,0x24,0xA4,0xFE,0xA3,0x22,0x00,0x22,0xCC,0x00,0x00,0xFF,0x00,0x00,0x00,
0x00,0x08,0x06,0x01,0xFF,0x00,0x01,0x04,0x04,0x04,0x04,0x04,0xFF,0x02,0x02,0x02}

因为每个汉字都是显示在16x16点阵上,所以每个8x8点阵都需要分担四分之一的汉字显示区域,即是一个汉字生成的数组字模,也需要分成四份,给到四块8x8点阵,将软件生成的单个汉字的32个16进制数组按8个,8个分成4组,如下:

unsigned char disp1[1][8] = {
    
    
{
    
    0x00,0x24,0x24,0xA4,0xFE,0xA3,0x22,0x00},	//科1 (左上角8x8点阵显示)
};

unsigned char disp2[1][8] = {
    
    
{
    
    0x22,0xCC,0x00,0x00,0xFF,0x00,0x00,0x00},	//科2 (右上角8x8点阵显示)
};

unsigned char disp3[1][8] = {
    
    
{
    
    0x00,0x08,0x06,0x01,0xFF,0x00,0x01,0x04},	//科3 (左下角8x8点阵显示)
};

unsigned char disp4[1][8] = {
    
    
{
    
    0x04,0x04,0x04,0x04,0xFF,0x02,0x02,0x02},	//科4 (右下角8x8点阵显示)
};

如果要显示两个字交替显示的话,字模数组这么写:

unsigned char disp1[1][8] = {
    
    
{
    
    0x00,0x24,0x24,0xA4,0xFE,0xA3,0x22,0x00},	//科1 
{
    
    0x00,0x10,0x10,0x10,0xFF,0x10,0x90,0x08},	//技1
};

unsigned char disp2[1][8] = {
    
    
{
    
    0x22,0xCC,0x00,0x00,0xFF,0x00,0x00,0x00},	//科2 
{
    
    0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x08},	//技2
};

unsigned char disp3[1][8] = {
    
    
{
    
    0x00,0x08,0x06,0x01,0xFF,0x00,0x01,0x04},	//科3 
{
    
    0x00,0x04,0x44,0x82,0x7F,0x01,0x80,0x80},	//技3
};

unsigned char disp4[1][8] = {
    
    
{
    
    0x04,0x04,0x04,0x04,0xFF,0x02,0x02,0x02},	//科4 
{
    
    0x40,0x43,0x2C,0x10,0x28,0x46,0x81,0x80},	//技4
};

16x16点阵屏代码

提取出字模后直接写代码。

//引脚定义
int clk =13;
int cs=10;
int din=11;

//字模数组
unsigned char disp1[4][8]={
    
    
{
    
    0x00,0xFE,0x02,0x02,0xFA,0x82,0x82,0xF2},
{
    
    0x80,0x80,0xFE,0x80,0xFC,0x00,0xFE,0x20},
{
    
    0x00,0xFC,0x04,0x04,0x04,0xFC,0x40,0x40},
{
    
    0x00,0x80,0xFE,0x02,0x04,0x00,0x00,0xFE},
};
 
unsigned char disp2[4][8]={
    
    
{
    
    0x82,0xA2,0x92,0xFA,0x02,0x02,0xFE,0x02},
{
    
    0x90,0x8C,0x92,0xE0,0x98,0x84,0x80,0x00},
{
    
    0xFE,0x40,0x20,0x20,0x12,0x0A,0x06,0x02},
{
    
    0x10,0x10,0x20,0x20,0xC0,0x30,0x08,0x04},
};
 
unsigned char disp4[4][8]={
    
    
{
    
    0x00,0x3F,0x20,0x20,0x2F,0x20,0x20,0x27},
{
    
    0x00,0x00,0x3F,0x00,0x1F,0x01,0x7F,0x02},
{
    
    0x00,0x1F,0x10,0x10,0x10,0x1F,0x10,0x10},
{
    
    0x01,0x00,0x1F,0x10,0x21,0x01,0x01,0x7F},
};
 
unsigned char disp3[4][8]={
    
    
{
    
    0x20,0x20,0x20,0x2F,0x20,0x20,0x3F,0x20},
{
    
    0x04,0x18,0x65,0x02,0x0C,0x30,0x02,0x01},
{
    
    0x1F,0x10,0x10,0x10,0x12,0x14,0x18,0x10},
{
    
    0x02,0x04,0x0C,0x03,0x00,0x01,0x06,0x38},
};
 
void setup(){
    
    
  pinMode(cs,OUTPUT);
  pinMode(clk,OUTPUT);
  pinMode(din,OUTPUT);
  Init_MAX7219();
}

void loop(){
    
    
  char i,j;

  //“国泰民安”轮流显示
  for(j=0;j<4;j++)
  {
    
    
	  for(i=1;i<9;i++){
    
    
	    Write_Max7219_1(i,disp1[j][i-1]);
	    Write_Max7219_2(i,disp2[j][i-1]);
	    Write_Max7219_3(i,disp3[j][i-1]);
	    Write_Max7219_4(i,disp4[j][i-1]);
	  }
	  delay(500);
  } 
}
 
void Write_Max7219_byte(char DATA)         
{
    
    
    char i;    
    digitalWrite(cs,0);                
    for(i=8;i>=1;i--)
    {
    
                      
    	digitalWrite(clk,0);
    	
    	if((DATA&0x80)>0) 	digitalWrite(din,1);
    	else 				digitalWrite(din,0);
    	
    	//提取最高位给DIN端口
    	DATA=DATA<<1;			//左移一位
    	digitalWrite(clk,1);
    }                                 
}
 
void Write_Max7219_1(char address1,char dat1)
{
    
     
     digitalWrite(cs,0);
     Write_Max7219_byte(address1);           //写入地址,即数码管编号
     Write_Max7219_byte(dat1);               //写入数据,即数码管显示数字 
     digitalWrite(cs,1);                        
}
 
void Write_Max7219_2(char address2,char dat2)
{
    
     
     digitalWrite(cs,0);
     Write_Max7219_byte(address2);           //写入地址,即数码管编号
     Write_Max7219_byte(dat2);				 //写入数据,即数码管显示数字 
     digitalWrite(clk,1);
     Write_Max7219_byte(0x00);
     Write_Max7219_byte(0x00);
     digitalWrite(cs,1);
 
}
 
void Write_Max7219_3(char address3,char dat3)
{
    
     
     digitalWrite(cs,0);
     Write_Max7219_byte(address3);           //写入地址,即数码管编号
     Write_Max7219_byte(dat3);				 //写入数据,即数码管显示数字 
     digitalWrite(clk,1);
     Write_Max7219_byte(0x00);
     Write_Max7219_byte(0x00);
     Write_Max7219_byte(0x00);
     Write_Max7219_byte(0x00);
     digitalWrite(cs,1);
 
}
 
void Write_Max7219_4(char address4,char dat4)
{
    
     
     digitalWrite(cs,0);
     Write_Max7219_byte(address4);           //写入地址,即数码管编号
     Write_Max7219_byte(dat4);				 //写入数据,即数码管显示数字 
     digitalWrite(clk,1);
     Write_Max7219_byte(0x00);
     Write_Max7219_byte(0x00);
     Write_Max7219_byte(0x00);
     Write_Max7219_byte(0x00);
     Write_Max7219_byte(0x00);
     Write_Max7219_byte(0x00);
     digitalWrite(cs,1);
 
}
 
void Init_MAX7219(void)
{
    
    
	Write_Max7219_1(0x09, 0x00);  	//译码方式:BCD码
	Write_Max7219_1(0x0a, 0x01);	//亮度 
	Write_Max7219_1(0x0b, 0x07); 	//扫描界限;8个数码管显示
	Write_Max7219_1(0x0c, 0x01);  	//掉电模式:0,普通模式:1
	Write_Max7219_1(0x0f, 0x00);
	 
	Write_Max7219_2(0x09, 0x00);	//译码方式:BCD码
	Write_Max7219_2(0x0a, 0x01);	//亮度 
	Write_Max7219_2(0x0b, 0x07); 	//扫描界限;8个数码管显示
	Write_Max7219_2(0x0c, 0x01);  	//掉电模式:0,普通模式:1
	Write_Max7219_2(0x0f, 0x00);
	 
	Write_Max7219_3(0x09, 0x00);	//译码方式:BCD码
	Write_Max7219_3(0x0a, 0x01);	//亮度 
	Write_Max7219_3(0x0b, 0x07); 	//扫描界限;8个数码管显示
	Write_Max7219_3(0x0c, 0x01);  	//掉电模式:0,普通模式:1
	Write_Max7219_3(0x0f, 0x00);
	 
	Write_Max7219_4(0x09, 0x00);	//译码方式:BCD码
	Write_Max7219_4(0x0a, 0x01);	//亮度 
	Write_Max7219_4(0x0b, 0x07); 	//扫描界限;8个数码管显示
	Write_Max7219_4(0x0c, 0x01);  	//掉电模式:0,普通模式:1
	Write_Max7219_4(0x0f, 0x00);	//显示测试:1;测试结束,正常显示:0
	delay(500); 
}

16x16汉字显示

程序效果如下
在这里插入图片描述
好了,赶快动手把你的点阵屏也玩起来吧。


8x8汉字取模和16x16汉字取模打包链接 → 字模资源链接

猜你喜欢

转载自blog.csdn.net/qq_36955622/article/details/114090207