单片机点阵如何扫描_单片机点阵 - CSDN
精华内容
参与话题
  • 点阵LED扫描法介绍

    千次阅读 2017-12-07 10:46:05
    点阵LED一般采用扫描式显示,实际运用分有三种方式

    点阵LED一般采用扫描式显示,实际运用分为三种方式:

    (1) 点扫描;

    (2) 行扫描;

    (3) 列扫描。

    若使用第一种方式,其扫描频率必须大于16×64=1024Hz,周期小于1ms即可。若使用第二和第三种方式,则频率必须大于16×8=128Hz,周期小于7.8ms即可符合视觉暂留要求。此外一次驱动一列或一行(8颗LED)时需外加驱动电路提高电流,否则LED亮度会不足。

    展开全文
  • LED点阵扫描显示 象棋小子 1048272975 LED点阵屏发光亮度强,指示效果好,可以制作运动的发光图文,更容易吸引人的注意力,信息量大,随时更新,有着非常好的广告和告示效果。笔者此处就LED点阵屏动态扫描显示作...

    51单片机开发系列四

    LED点阵扫描显示

    象棋小子    1048272975

    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) / ID

    VCC为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) / IB

    VCC为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}, {2, 5}, {1,4}, {1, 3}, {2, 2},

    };

     

    // 以定时器时间为计时标准,记录时间间隔

    static volatileunsigned int SystemTick = 0;

     

    // 定时器1.5ms中断处理进行数码管刷新

    void T0_Interrupt()interrupt 1

    {

        TH0 = (65536-1500) / 256;

        TL0 = (65536-1500) % 256;

        SystemTick++; // 记录时间间隔

        MatrixScan(); // 刷新数码管

    }

     

    void T0_Init()

    {

        TMOD = 0x01; // 定时器0工作方式1

        // 1.5ms计时中断(12M)

        TH0 = (65536-1500) / 256;

        TL0 = (65536-1500) % 256;

        ET0 = 1; // 定时器T0中断允许

        EA = 1; // 总中断允许

    }

     

     

    void main()

    {

        unsigned char *pBuffer;

        unsigned char State = 0;

        unsigned char Point;

        unsigned char Direction;

        unsigned char DataAnd;

        unsigned char i;

        // 定时器初始化

        T0_Init();

        // 获得点阵显存,以作数据处理

        pBuffer = MatrixGetBuffer();

        // 点阵屏清屏

        MatrixClearScreen();

        // 开启定时器进行计时以及点阵扫描

        TR0 = 1;

     

        Point = 0;

        while(1) {

           switch (State) {

           case 0:    //状态0为逐点打出心形

               if (SystemTick > 334) { // 500ms打心形的一个点

                  SystemTick = 0;

               MatrixSetPoint(HeartShape[Point][0],HeartShape[Point][1], CLEAR);

                  Point++;

                  if (Point >sizeof(HeartShape)/sizeof(HeartShape[0])) {

                      State = 1; // 心形打完,进入状态1,是否到边界判断

                      Direction = TL0& 0x3; // 随机得出心形的移动方向

                  }                

               }

               break;

     

           case 1:    // 状态1为心形是否移动到点阵屏边界的判断

               switch (Direction) { // 移动方向判断是否到相应方向的边界

               case 0:    // 左边界判断

                  // 第一列的点有一个亮,则认为图形到了左边界

                  if (pBuffer[0] !=0xff) {

                      Direction = TL0& 0x3; // 重新选择移动方向

                  } else {

                      State = 2; // 未到左边界,进入状态2进行左平移

                  }

                  break;

               case 1:    // 右边界判断

                  // 第八列的点有一个亮,则认为图形到了右边界

                  if (pBuffer[7] !=0xff) {

                      Direction = TL0& 0x3; // 重新选择移动方向

                  } else {

                      State = 2; // 未到右边界,进入状态2进行右平移

                  }

                  break;

               case 2:    // 上边界判断

                  // 所有列的第一行点有一个亮,则认为图形到了上边界

                  DataAnd = 0xff;

                  for (i=0; i<8; i++) {

                      DataAnd &= pBuffer[i];

                  }

                  if (DataAnd & 0x1) {

                      State = 2; // 未到上边界,进入状态2进行上平移                           

                  } else {

                      Direction = TL0& 0x3; // 重新选择移动方向

                  }

                  break;

               case 3:    // 下边界判断

                  // 所有列的第八行点有一个亮,则认为图形到了下边界

                  DataAnd = 0xff;

                  for (i=0; i<8; i++) {

                      DataAnd &= pBuffer[i];

                  }

                  if (DataAnd & 0x80) {

                      State = 2; // 未到下边界,进入状态2进行下平移                           

                  } else {

                      Direction = TL0& 0x3; // 重新选择移动方向

                  }

                  break;

               default:

                  break;

               }

               break;

     

           case 2:    // 状态2为对点阵屏平移

               if (SystemTick < 667){  // 1s平移1次

                  continue;

               }

               SystemTick = 0;

               switch (Direction) {

               case 0:    // 左平移,平移后的空缺位置灭

                  MatrixMove(MOVE_LEFT, 0xff);

                  break;

               case 1: // 右平移,平移后的空缺位置灭

                  MatrixMove(MOVE_RIGHT,0xff);

                  break;

               case 2:    // 上平移,平移后的空缺位置灭

                  MatrixMove(MOVE_UP, 0xff);

                  break;

               case 3:    // 下平移,平移后的空缺位置灭

                  MatrixMove(MOVE_DOWN, 0xff);

                  break;

               default:

                  break;

               }

               State = 1; // 平移后再进入状态1进行边界检测

               break;

     

           default:

               break;

           }  

        }

    }

    附录:

    此章节的Keil工程,包含源码,Preteus仿真,包含仿真电路,可直接查看效果,Matrix.rar。

    http://pan.baidu.com/s/1dDchpYh

     

     

    展开全文
  • 单片机8X8点阵滚动显示C程序,LED8*8滚动显示,列扫描,低电平有效,取模方式,阴码,列扫描,逆向。
  • led点阵点亮图案仍然使用动态扫描的方式,方法同“51单片机实验5:动态数码管”https://blog.csdn.net/cax1165/article/details/86557551 D0口到D7口依次控制点阵的第8到1行(注意顺序),P0^0到P0^7口依次控制点阵...

    开发板led点阵模块电路图如下:

     

     

    点阵内部led连接方式如下图:

    led点阵点亮图案仍然使用动态扫描的方式,方法同“51单片机实验5:动态数码管”https://blog.csdn.net/cax1165/article/details/86557551

    D0口到D7口依次控制点阵的第8到1行(注意顺序),P0^0到P0^7口依次控制点阵的第8到1列(注意顺序)。

    显然,根据点阵内部led连接电路,74HC595控制高电平输出,P0口控制低电平输出。

    以移位寄存器74HC595控制段选,P0口控制位选!

    注意:写程序时需要考虑74HC595移位寄存器的工作特点。

    程序可参考“51单片机实验8:led点阵(1):点亮一个点 ”https://blog.csdn.net/cax1165/article/details/86607762

    #include<reg52.h>
    #include<intrins.h>
    #define uc unsigned char
    sbit srclk=P3^6;
    sbit rclk=P3^5;
    sbit ser=P3^4;
    uc ledduan[]={0x00,0x00,0x3e,0x41,0x41,0x41,0x3e,0x00};
    uc ledwei[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
    void delay(uc x)
    {
    	uc i,j;
    	for(i=1;i<=x;i++)
    		for(j=1;j<=110;j++);
    }
    void c74hc595(uc dat)
    {
    	uc i;
        srclk=rclk=0;
    	for(i=1;i<=8;i++)
    	{
    		ser=dat>>7;
    		dat<<=1;
    		srclk=1;
    		_nop_();
    		srclk=0;
    	}
    	rclk=1;
    	_nop_();
    	rclk=0;
    }
    void main()
    {
    	uc i;
    	while(1)
    	{
    		//P0=0x7f;
            for(i=1;i<=8;i++)
    		{
    			P0=ledwei[i-1];
    			c74hc595(ledduan[i-1]);
    			delay(1);
    			c74hc595(0x00);
    		}
    	}
    }

     

    展开全文
  • 本文介绍了彩色点阵的使用,以及利用51单片机控制点阵制作的沙漏型交通灯,希望对打算用点阵做课程设计的同学有点帮助。一、效果展示 二、彩色点阵的使用这里使用的是在淘宝上买的彩色点阵,有32个引脚,这里以背面...

                                                                  

    本文介绍了彩色点阵的使用,以及利用51单片机控制点阵制作的沙漏型交通灯,希望对打算用点阵做课程设计的同学有点帮助。

    一、效果展示

        

       二、彩色点阵的使用

    彩色点阵有32个引脚,这里以背面图来讲解:

    从背面看到点阵型号(就是能正看到一串数字和英文),上面的一排从左到右为

    1234,      56789101112,   13141516

    行控制高电平输入             列:低电平点亮绿灯                       行控制高电平输入

                             

    下面一排从左到右

    1718192021222324,   2526272829303132

    列:低电平点亮红灯                                    列:低电平点亮蓝灯

    这里建议高电平输入接有上拉电阻的IO,然后控制不同颜色的IO口输出低电平点亮不同的灯,通过控制三种颜色调出不同的颜色,所以叫彩色点阵。

      后面的电路版是自己画的51贴片最小系统,测试用线接51最小系统即可,我用的是P0口作为高电平输入P1控制红灯,P2控制绿灯,所以P0焊接了一排上拉电阻,交通灯的黄色是用红色加绿色调出来的,所以没用到蓝色。

    三.函数介绍


    点亮黄等需要点亮红灯与绿灯,然后染成黄色,利用动态扫描,点亮绿灯之后再点亮红灯,这里调节delay()函数可以改变颜色,如把上面黄灯delay(1)改成delay(20),就可以染出绿黄色,相当于绿灯先亮的比较久,其他颜色也是如此调节,理论上能调出7种颜色。

    四、注意事项

    1. 不能用VCC直接给点阵供电,很容易烧坏LED

    2. 数组要记得加code,不然单片机的运存可能会不够




     以上是点阵背面的原理图和PCB图

    需要源代码或者PCB图可以跳转点击打开链接


     

     

     

     

     

     

     

     

    展开全文
  • 利用51单片机的LED点阵输出生日快乐

    千次阅读 2018-09-02 17:26:58
    根据点阵原理图,P00-P07接低电平,D0-D7接高电平时led点亮,由于单片机控制端口有限,于是只能每次点亮一列,逐列扫描,利用人眼的视觉暂留形成同时点亮的现象。将要点亮的LED灯标记为1,每一列根据D0-D7...
  • 51单片机——8X8点阵显示

    千次阅读 2019-01-11 16:49:53
    74hc595.h: #ifndef __74hc595_H__ #define __74hc595_H__ /************************************位定义************************************/ sbit DATA_IN = P1^0; //串行数据输入 sbit ST_CK = P1^1;...
  • 51单片机基于Proteus的8X8点阵滚动显示心形

    万次阅读 多人点赞 2018-09-16 17:17:16
    代码及仿真原理图下载地址: ... 一、效果展示及连线方式 ...1、Proteus中8x8点阵   8x8点阵主要分为以下两种:   第一种为行共阴,第二种为行共阳   详细介绍可以参考这位大神说的: http...
  • 51单片机点亮LED点阵

    千次阅读 2019-03-24 22:46:33
    共阴极双色点阵 Led点阵就是很多led放在一起组成的矩阵灯。原理很简单,如果我们要点亮图中左上的绿灯。那么管脚5接高电平,管脚24接低电平,那么这个绿色led就会亮,其他的led亦是如此。我们要显示需要的内容,...
  • 在LED点阵上绘制图案最主要的应用两个模块: LED点阵模块(笔者所用的是16*16) 74HC595模块 首先介绍74HC191模块,该模块最主要的功能就是扩展C51的IO口,实现串转并的功能。该模块的内部结构这里就不多说,主要...
  • 51单片机学习记录(8) “8x8点阵” 8x8点阵就是由64个小led灯组成的矩阵,现在先让我们看一下点阵的内部结构 从图中可以了解到 (从行看去)每一行的小灯的阳极相连在一起排成了一列 (从列看去)每一列的小灯的阴极...
  • a 单色点阵与双色点阵发光原理 1)单色点阵 单色LED点阵等效图如下: 8X8点阵共需要64个发光二极管组成,且每个发光二极管是放置在行线和列线的交叉点上,当对应的某一列置1电平,某一行置0...
  • 扫描的接法写个向上移动的程序很容易,列扫描的接法写个左右移动的程序很容易,只是通过字模的数组不同取法就可以实现但上面的接法明显不符合实际要求,行扫描的时候一般都是要左右移动显示,列扫描的时候一般是...
  • 基于51单片机的贪吃蛇小程序(8*8LED点阵实现)by_jy

    千次阅读 热门讨论 2019-05-02 13:35:55
    基于51单片机的贪吃蛇小程序(8*8LED点阵实现)by_jy ** 一直很想写一个贪吃蛇的小程序,这两天终于抽空完成了,这里把我的思路分享给大家,仅供参考! 代码如下: 先放段主函数压压惊 void main() { x_s[0] = 2; ...
  • 51单片机8*8点阵LED显示原理及程序

    万次阅读 2008-01-21 17:06:00
    2007-12-25 10:36:16 在8X8点阵LED上显示柱形,让其先从左到右平滑移动三次,其次从右到左平滑移动三次,再次从上到下平滑移动三次,最后从下到上平滑移动三次,如此循环下去。1. 程序设计内容 8X8点阵LED...
  • 单片机点阵毕业设计

    2020-07-23 23:30:45
    点阵的毕业设计。。本文介绍一种基于PIC16F877A...此设计采用动态扫描方式,通过单片机控制3-8译码器74LS138和数据移位寄存器74HC595来驱动显示屏的显示,此方案实用简单,软件编程方便,价格低廉,具有应用推广价值。
  • //列扫描,低电平有效 /*--------------------------------------------------------------*/ //包含头文件 #include &lt;reg52.h&gt; #include "74HC595.H" #include&lt;intrins.h&gt; /...
  • 下面我们就用程序来实现一下,特别注意,控制点阵左侧引脚的 74HC138是原理图上的 U4,8 个引脚自上而下依次由 U4 的 Y0~Y7 输出来控制。 #include <reg52.h> sbit ADDR0 = P1^0; sbit ADDR1 = P1^1; sbit ...
  • 8*8点阵原理图

    2020-07-17 17:53:35
    8×8点阵LED电路原理 点阵LED扫描法介绍
1 2 3 4 5 ... 20
收藏数 701
精华内容 280
关键字:

单片机点阵如何扫描