51单片机LED点阵实验:从点亮一个点到显示数字和图像

文章目录

  • 一、LED点阵介绍
  • 二、硬件设计
  • 三、软件设计
  • 1.LED点阵(点亮一个点)
  • 2.LED点阵(显示数字)
  • 3.LED点阵(显示图像)
  • 四、实验现象
  • 1.LED 点阵(点亮一个点)
  • 2. LED 点阵(显示数字)
  • 3. LED 点阵(显示图像)
  •   开发板上使用了 64 个红色
    LED 按照行列排布组成的
    8*8 LED 点阵。下面介绍
    LED点阵的使用。

    一、LED点阵介绍

      LED 点阵是由发光二极管排列组成的显示器件,在我们日常生活的电器中随处可见,被广泛应用于汽车报站器,广告屏等。如下所示:

      通常应用较多的是 8*8 点阵,然后使用多个 8*8 点阵可组成不同分辨率的 LED点阵显示屏,比如 16*16 点阵可以使用 4 个 8*8 点阵构成。因此理解了 8*8LED点阵的工作原理,其他分辨率的 LED 点阵显示屏都是一样的。这里以 8*8LED 点阵来做介绍。其内部结构图如下所示:

      8*8 点阵共由 64 个发光二极管组成,且每个发光二极管是放置在行线和列线的交叉点上,当对应的某一行置 1 电平,某一列置 0 电平,则相应的二极管就亮;如要将第一个点点亮,则 1 脚接高电平 a 脚接低电平,则第一个点就亮了;如果要将第一行点亮,则第 1 脚要接高电平,而(abcdefgh )这些引脚接低电平,那么第一行就会点亮;如要将第一列点亮,则第 a 脚接低电平,而(1、2、3、4、5、6、7、8)接高电平,那么第一列就会点亮。由此可见,LED点阵的使用也是非常简单的。

    二、硬件设计

      本实验使用到硬件资源如下:

  • 8*8LED 点阵模块
  • 74HC595 模块
  •   74HC595 模块、8*8LED 点阵模块电路在前面章节都介绍过,电路如下:

    从上图中可以看出,74HC595 需要用到的控制管脚 SERRCLKSRCLK 直接连接到 51 单片机的 P3.4-P3.6 IO 口上,输出端则是直接连接到 LED 点阵模块的行端口上,即为 LED 发光二极管的阳极,LED 点阵的列则为发光二极管的阴极。
      要想控制 LED 点阵,可以将单片机管脚按照 74HC595 芯片的通信时序要求来传输数据,这样即可控制 LED 点阵的行数据。根据 LED 发光二极管导通原理,当阳极为高电平,阴极为低电平则点亮,否则熄灭。因此通过单片机 P0 口可控制点阵列,74HC595 可控制点阵行。

    三、软件设计

      本节所要实现的功能是:在点阵屏上点亮一个点,上述功能实现后再显示数字和图形。

    1.LED点阵(点亮一个点)

      我们直接复制前面创建好的工程模板,将复制过来的模板文件夹重新命名为“11-LED点阵实验”。打开工程直接在 main.c 源文件内进行编程,main.c 内代码如下:

    /*
    实验名称:LED 点阵实验(点亮一个点)
    接线说明:
    实验现象:下载程序后,8*8LED 点阵点亮左上角第一个点
    注意事项:LED 点阵旁的 J24 黄色跳线帽短接到 GND 一端
    */
    
    #include "reg52.h"
    
    //对系统默认数据类型进行重定义 
    typedef unsigned char u8;
    typedef unsigned int u16;
    
    //定义74HC595控制管脚
    sbit SER = P3^4;	//串行数据输入
    sbit rCLK = P3^5;	//存储寄存器时钟输入
    sbit SrCLK = P3^6;	//移位寄存器时钟输入
    
    //使用宏定义点阵列控制口
    #define LEDDZ_COL_PORT P0
    
    /*
    函 数 名 : delay_10us
    函数功能 : 延时函数,ten_us=1 时,大约延时 10us
    输 入 : ten_us
    */
    void delay_10us(u16 ten_us)
    {
    	while (ten_us--);
    }
    
    /*
    函 数 名 : hc595_write_data(u8 dat)
    函数功能 : 向 74HC595 写入一个字节的数据,一位一位的传输
    输 入 : dat:数据
    输 出 : 无
    */
    void hc595_write_data(u8 dat)
    {
    	u8 i = 0;
    	//循环8次将一个字节写入移位寄存器
    	for (i=0;i<8;i++)
    	{
    		SER = dat>>7; //优先传输一个字节的高位
    		dat <<= 1;   //将次高位移到高位
    		//SRCLK先是低电平后是高电平,产生上升沿
    		SrCLK = 0;	 //低电平
    		delay_10us(1);
    		SrCLK = 1;   //高电平
    		delay_10us(1); //移位寄存器时钟上升沿将端口数据送入寄存器中
    	}
    
    	//当RCLK上升沿到来时,移位寄存器的8位数据一次性传入到存储寄存器当中		
    	rCLK = 0;
    	delay_10us(1);
    	rCLK = 1;  //存储寄存器时钟上升沿将前面写入到寄存器的数据输出	
    }
    
    
    /*
    函 数 名 : main
    函数功能 : 主函数
    */
    void main()
    {	
    	u8 i = 0;
    	//将 LED 点阵左边第一列设置为 0,即 LED 阴极为低电平,其余列为1,即高电平
    	LEDDZ_COL_PORT=0x7f;
    
    	while (1)
    	{  	
    		//将 LED 点阵上边第一行设置为 1,即 LED 阳极为高电平,其余行为 0,即低电平
    		hc595_write_data(0x80);
    	}
    }
    

    至此,整个程序就编写完成,我们编译一下,如下图所示:

    可以看到没有错误,也没有警告。

    这里主要是理解如何让 LED 点阵的左上角第一个点点亮,实际上就是将第一个点对应的行为高电平,列为低电平即可。也就是让 74HC595 输出 0X80(1000 0000),这样点阵第一行就是高电平,而 P0 口输出 0X7F(0111 1111),这样点阵第一列就是低电平,从而让 LED 点阵第一个点点亮。

    2.LED点阵(显示数字)

      点亮一个点很简单,可是如何点亮多个点呢?如果需要一次显示多个怎么办?从原理图上可以看到每一行上都连接着多个 LED 灯,每一列上也都连接着多个 LED 灯,如果要点亮一个,按照上面原理可以,但是要同时点亮多个怎么办?
      那么就需要用到动态数码管的动态扫描原理。首先,如何点亮一行上面多个灯或者一列上面多个灯?明显需要某行或某列有效,同时使多列或多行有效。比如在第一行有效(输出高电平)的情况下,有效列(输出低电平)与这一行交点上的 LED 灯就会被点亮。那么实现一行或一列点亮会比较容易。如何实现不同行不同列上的灯被多个点亮呢? 是否是行有效,列有效就可以?并不是!
      要实现行列不同位置亮灯,需要使用动态显示的方法,也要结合扫描的方法。在第一行亮灯一段时间以后灭掉,点亮第二行一段时间以后灭掉,点亮第三行一段时间以后灭掉,如此点亮,直到八行全部点亮一次,在第一行点亮到最后一行灭掉的总时间不能超过人肉眼可识别的时间,即 24 毫秒。在每一行点亮的时候,给列一个新的数据,此时对应列的数据就可以体现在这行上要点亮的灯上。这样就和动态数码管的显示一样,只不过数码管的 LED 灯是段值。这里使用 LED 点阵显示数字,也是多个 LED 同时点亮。
      要想在点阵上显示数字等字符,首先要获取在 LED 点阵上显示数字字符所需的数据,即一个数字字符在LED 点阵上显示,对应的每行每列都会有一些灯点亮或者熄灭,这样就会构成一组数据,也就是数字字符的显示数据,我们只要将这些数据通过 74HC595 发送到点阵对应的行或列就能显示数字字符。
      数字字符数据如何获取呢?这里给大家介绍一个非常好用的工具-取字模软件。文字取模软件如下所示:

      双击打开该软件,首先选择“基本操作->新建图像”,设置图像的宽度和高度为8,点击确定后将在显示窗口出现一个8*8的白色格子,这个就类似于8*8LED点阵,具体操作如下:


    可以看到上图 8*8 点阵区域非常小,我们可以将其放大,选择“模拟动画”,后点击“放大格点”,如下所示:

      然后可以在这个 8*8 白色格子里面点击,点击后即会在对应位置出现一个黑点,表示在 LED 点阵对应位置的 LED 灯点亮,未点击位置(白色)表示LED 点阵对应位置的 LED 灯熄灭。
      比如在 8*8LED 点阵上显示数字 0,那么可以在图中 8*8 白色框内通过点击对应位置描出一个数字 0 的外形,如下所示:

      然后设置取模数据的取模方式等内容,选择“参数设置”后点击“其他选项”,具体操作如下:

      然后点击“取模方式”,选择 C51 格式选项,然后在点阵生成区自动会生成数字字符对应的数据(如果是使用汇编编程,那么汇编对应的汉字数据可选择 A51 格式)。如下所示:

    到这里我们就将数字 0 的数据生成了,然后将生成的数据复制到我们程序定义的数组中,如下所示:

    u8 gled_row[8]={0x00,0x7C,0x82,0x82,0x82,0x7C,0x00,0x00};//LED 点阵显示数字 0 的行数据
    

    这些数据其实就是上述描绘的数字 0 从左到右依次每列对应的行数据。
      既然是动态扫描,就需要不断的扫描每列,因此可以把 LED 点阵的列控制也用数组存储起来,为后面循环调用提供方便。根据数字 0 取模的数据特点是从左至右每列对应的行数据,因此扫描时也应该从左至右的顺序,如下:

    u8 gled_col[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//LED 点阵显示数字 0 的列数据
    

      我们直接复制前面创建好的工程模板,将复制过来的模板文件夹重新命名为“12-LED点阵实验(显示数字)”。打开工程直接在 main.c 源文件内进行编程,main.c 内代码如下:

    /*
    实验名称:LED 点阵实验(点亮数字图像)
    接线说明:
    实验现象:下载程序后,8*8LED 点阵显示数字 0
    注意事项:LED 点阵旁的 J24 黄色跳线帽短接到 GND 一端
    */
    
    #include "reg52.h"
    
    //对系统默认数据类型进行重定义 
    typedef unsigned char u8;
    typedef unsigned int u16;
    
    //定义74HC595控制管脚
    sbit SER = P3^4;	//串行数据输入
    sbit rCLK = P3^5;	//存储寄存器时钟输入
    sbit SrCLK = P3^6;	//移位寄存器时钟输入
    
    //使用宏定义点阵列控制口
    #define LEDDZ_COL_PORT P0
    
    ///LED 点阵显示数字 0 的行数据
    u8 gled_row[8] = {0x00,0x7C,0x82,0x82,0x82,0x7C,0x00,0x00};
    //LED 点阵显示数字 0 的列数据
    u8 gled_col[8] = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
    
    /*
    函 数 名 : delay_10us
    函数功能 : 延时函数,ten_us=1 时,大约延时 10us
    输 入 : ten_us
    */
    void delay_10us(u16 ten_us)
    {
    	while (ten_us--);
    }
    
    /*
    函 数 名 : hc595_write_data(u8 dat)
    函数功能 : 向 74HC595 写入一个字节的数据,一位一位的传输
    输 入 : dat:数据
    输 出 : 无
    */
    void hc595_write_data(u8 dat)
    {
    	u8 i = 0;
    	//循环8次将一个字节写入移位寄存器
    	for (i=0;i<8;i++)
    	{
    		SER = dat>>7; //优先传输一个字节的高位
    		dat <<= 1;   //将次高位移到高位
    		//SRCLK先是低电平后是高电平,产生上升沿
    		SrCLK = 0;	 //低电平
    		delay_10us(1);
    		SrCLK = 1;   //高电平
    		delay_10us(1); //移位寄存器时钟上升沿将端口数据送入寄存器中
    	}
    
    	//当RCLK上升沿到来时,移位寄存器的8位数据一次性传入到存储寄存器当中		
    	rCLK = 1;
    	delay_10us(1);
    	rCLK = 0;  //存储寄存器时钟上升沿将前面写入到寄存器的数据输出	
    }
    
    
    /*
    函 数 名 : main
    函数功能 : 主函数
    */
    void main()
    {	
    	u8 i = 0;
    	
    	while (1)
    	{  	
    		for(i=0;i<8;i++)  //循环8次扫描8行8列
    		{
    			 LEDDZ_COL_PORT = gled_col[i]; //传送列选数据
    			 hc595_write_data(gled_row[i]); //传送行选数据
    			 delay_10us(100); //延时一段时间,等待显示稳定
    			 hc595_write_data(0x00); //消影
    		}
    	}
    }
    

    至此,整个程序就编写完成,我们编译一下,如下图所示:

    可以看到没有错误,也没有警告。

    main 函数中主要是在 while 循环内从上至下,从左至右不断扫描 8 行、列,即首先设置左边第一列有效(P0.7 输出低电平),其余列无效(P0.6-P0.0 输出高电平),然后通过74HC595 输出该列对应的行数据,延时一段时间等待显示稳定,最后清除列对应的行数据,即消影。从整个流程下来与动态数码管显示程序是很相似的。

    3.LED点阵(显示图像)

      该取模软件不仅可以用来取汉字、数字等字符数据,还可以用来取图像数据,这里以“心”形图像为例,教大家如何使用该软件来获取图像数据。

    1. 新建图像。弹出选择框,开发板 LED 点阵是 8X8 的,就建一个高 8 宽8 的。

    2. 选中图像需用格点。这里每一个格点代表一个 LED 灯,点击可选中,再次点击也可取消。在界面上点出爱心。如下图:

    3. 参数设置。“参数设置” 选项中有许多可选项,可以自己进行设置,得到自己想要的结果。可参考前面取模里面的设置。如下所示:

    4. 生成数据。设计好图案和参数以后,就需要生成可用数据。当点击格式以后会出现相应数据。如下图所示

      这里将生成的图形数据复制出来粘贴到上一实验中,替换数字 0 的数据,如下:

      u8 gled_row[8]={0x38,0x7C,0x7E,0x3F,0x3F,0x7E,0x7C,0x38};//LED 点阵显示图像的行数据
      

    四、实验现象

    1.LED 点阵(点亮一个点)

      使用 USB 线将开发板和电脑连接成功后(电脑能识别开发板上 CH340 串口),把编译后产生的.hex 文件烧入到芯片内,实现现象如下:8*8LED 点阵左上角显示第一个点。

    2. LED 点阵(显示数字)

      使用 USB 线将开发板和电脑连接成功后(电脑能识别开发板上 CH340 串口),把编译后产生的.hex 文件烧入到芯片内,实现现象如下:8*8LED 点阵显示数字0。

    3. LED 点阵(显示图像)

      使用 USB 线将开发板和电脑连接成功后(电脑能识别开发板上 CH340 串口),把编译后产生的.hex 文件烧入到芯片内,实现现象如下:8*8LED 点阵显示心形。

    注意:当不使用 LED 点阵时,将 LED 点阵旁的 J24 黄色跳线帽短接到 VCC 一端。这是因为 LED 点阵使用到了 P0 口,而数码管也使用到 P0 口,为了不干扰后续数码管显示的一些实验,所以短接到 VCC 一端。

    物联沃分享整理
    物联沃-IOTWORD物联网 » 51单片机LED点阵实验:从点亮一个点到显示数字和图像

    发表评论