zoukankan      html  css  js  c++  java
  • 最新 Arduino 驱动 12接口/户外 LED显示屏/LED点阵屏/LED单元板

    起因

    现有的驱动LED显示屏的资料,比较好的只有这个。但是它驱动的是08接口的室内显示屏,而我要驱动的是12接口的户外显示屏。两种屏幕的区别在于户外屏幕点阵比较稀疏,而且二者的扫描方式,驱动方式都不太一样。我花了一个下午才摸索出了它的使用方式,因此分享给大家,希望大家不必再绕弯路。

    材料准备

    • 12接口(户外)LED单元板一块:比如我是从[这里]买的,大家搜索“半户外 LED 单元板”就可以了。我的板是16x32大小。
    • Arduino Uno一块
    • 5V电源一个(比如充电宝、给手机充电的头)

    硬件搭建

    1.显示屏电源的焊接

    LED单元板使用的是5V的电源,但是它只提供了两个旋螺丝的地方供接电源。因此我们要进行如下焊接:USB公头的+,-接到导线的+,-。这样之后USB直接插入手机充电器/充电宝,导线链接到显示屏的电源上。

    2.Arduino与显示屏的连接

    首先我们要知道12接口每个引脚的定义:

    OE   A
    N    B
    N    C
    N    CLK
    N    HS
    N    R
    N    G
    GND  D
    • N:表示没有任何用
    • A,B,C,D:行选择。由于我们是16x32的板,所以只会用到A,B(也就是0~3),至于为什么等到后面再说
    • OE:使能。如果是高电平则屏幕会亮,低电平则强制所有灯都灭
    • GND:地。(这些引脚中没有VCC脚...我也不知道为啥它能正常工作)
    • CLK,HS,R:就是74HC595中的SHCP,STCP,DS。具体自行学习595芯片。
    • G:本来指绿色,我们因为是单色所以没用。

    接下来就是把它们连接到Arduino的引脚上了。我的库的默认设置如下:

    const int A=2,const int B=3,const int CLK=12,const int STB=10,const int R=11,const int OE=9

    当然,你也可以在库初始化的时候修改。

    软件搭建

    1.库的代码

    我自己写了一个库,代码如下:

    #include <Arduino.h>
    #include "DotMatrix.h"
    
    class LEDScreenHelper {
    public:
        LEDScreenHelper(const int WIDTH=32,
                const int A=2,const int B=3,const int CLK=12,
                const int STB=10,const int R=11,const int OE=9):
                HEIGHT(16),WIDTH(WIDTH),A(A),B(B),SHCP(CLK),STCP(STB),DS(R),OE(OE){}
        
        void setup(){
            pinMode(A,OUTPUT);
            pinMode(B,OUTPUT);
            pinMode(STCP,OUTPUT);
            pinMode(SHCP,OUTPUT);
            pinMode(DS,OUTPUT);
            pinMode(OE,OUTPUT);
        }
        
        void setRow(byte row){
            digitalWrite(A,row&0x01);
            digitalWrite(B,row&0x02);
        }
        
        void sendColData(byte data){
            for(int i = 0;i<8;++i){
                digitalWrite(DS,(data&0x80));
                data<<=1;
                digitalWrite(SHCP,0);
                digitalWrite(SHCP,1);
            }
        }
        
        void setOE(bool enable){
            digitalWrite(OE, enable);
        }
        
        void display(DotMatrix &data){
            for(int row = 0;row<4;++row){
                digitalWrite(OE,0);
                for(int col = 0;col<WIDTH/2;++col){
                    byte val = data.get((12-((col&3)<<2)+row),(col>>2));
                    sendColData(~val);
                }
                setRow(row);
                digitalWrite(STCP,0);
                digitalWrite(STCP,1);
                digitalWrite(OE,1);
            }
            digitalWrite(OE,0);
        }
        
    private:
        const int HEIGHT,WIDTH;
        const int A,B,SHCP,STCP,DS,OE;
    };

    其中需要#include "DotMatrix.h"如下:

    #ifndef DOT_MATRIX
    #define DOT_MATRIX
    
    typedef unsigned char uchar;
    #define THROW(str) ;
    
    #define BYTE_LEN 8
    #define CHECK_VAR(i,j) if((i)<0||(j)<0||(i)>=height||(j)>=width)THROW("Index out of Bound")
    #define POS(matrix,i,j) (*((matrix) + (i) * (width) + (j)))
    #define POS_BIT_GET(matrix,i,j) (POS((matrix),(i),(j)/BYTE_LEN) & (1<<(BYTE_LEN-(j)%BYTE_LEN-1)))
    #define POS_BIT_SET_TRUE(matrix,i,j) (POS((matrix),(i),(j)/BYTE_LEN) |= (1<<(BYTE_LEN-(j)%BYTE_LEN-1)))
    #define POS_BIT_SET_FALSE(matrix,i,j) (POS((matrix),(i),(j)/BYTE_LEN) &= (0xFF ^ (1<<(BYTE_LEN-(j)%BYTE_LEN-1))))
    #define POS_BIT_SET(m,i,j,b) ((b)!=0)?POS_BIT_SET_TRUE((m),(i),(j)):POS_BIT_SET_FALSE((m),(i),(j))
    
    /**
     * Remember: This class will only use `matrix` but NOT DELETE it
     */
    class DotMatrix {
    public:
        DotMatrix(int w,int h,uchar *matrix, bool isNowClearMatrix=true):
                width(w),height(h),matrix(matrix){
            if(isNowClearMatrix)clearData();
        }
        DotMatrix(const DotMatrix &src){
            Serial.println("DotMatrix copy construction - please avoid");
            width = src.width;
            height = src.height;
            matrix = src.matrix;
        }
        ~DotMatrix(){}
    
        void clearData(){
            memset(matrix,0,width*height*1);
        }
    
        inline void set(int i,int j,uchar val){
            CHECK_VAR(i,j);
            POS(matrix,i,j) = val;
        }
    
        inline uchar get(int i,int j){
            CHECK_VAR(i,j);
            return POS(matrix,i,j);
        }
    
        inline void setBit(int i,int jBit, bool b){
            CHECK_VAR(i,jBit/8);
            POS_BIT_SET(matrix,i,jBit,b);
        }
    
        inline bool getBit(int i,int jBit){
            CHECK_VAR(i,jBit/8);
            return POS_BIT_GET(matrix,i,jBit);
        }
    
        void fillTo(DotMatrix &fillTo, int xOffset, int yOffset, int scale){
            this->fillTo(fillTo,xOffset,yOffset,scale,scale,0,0,width*BYTE_LEN,height);
        }
    
        /**
         * fill the rect [xSrcBeg,ySrcBeg,xSrcEnd,ySrcEnd] to `fillTo` by the `offset` and `scale`
         * @param The things by **bit**
         */
        void fillTo(DotMatrix &fillTo, int xOffset, int yOffset, int xScale, int yScale,
                int xSrcBeg, int ySrcBeg, int xSrcEnd, int ySrcEnd) {
            for(int i = ySrcBeg;i<ySrcEnd;++i){
                for(int j = xSrcBeg;j<xSrcEnd;++j){
                    for(int ii=0;ii<yScale;++ii){
                        for(int jj=0;jj<xScale;++jj){
                            //VAR_DUMP_INLINE(i);VAR_DUMP_INLINE(j);VAR_DUMP_INLINE(ii);VAR_DUMP(jj);
                            fillTo.setBit(yOffset+(i-ySrcBeg)*yScale+ii, xOffset+(j-xSrcBeg)*xScale+jj, POS_BIT_GET(matrix,i,j));
                        }
                    }
                }
            }
        }
    
        void print(){
            for(int i = 0;i<height;++i){
                for(int j = 0;j<width;++j){
                    for(int k = 7;k>=0;--k){
                        Serial.print((get(i,j) & (1<<k))!=0);
                    }
                    Serial.print(" ");
                }
                Serial.println(" ");
            }
            Serial.flush();
        }
    
        int getWidth(){
            return width;
        }
    
        int getHeight(){
            return height;
        }
    
        uchar *getMatrix(){
            return matrix;
        }
    private:
        int width,height;
        uchar *matrix;
    private:
        friend class DisplayHelper;
    };
    #undef BYTE_LEN
    #undef POS
    #undef POS_BIT
    
    #endif

    解释一下,DotMatrix这个类是一个二维矩阵的操作类,只要给它一个一维数组作为存储空间,它就可以模拟出一个二维的数组。这样可以减少Arduino上的内存分配与销毁。

    2.库的使用

    #include <Arduino.h>
    #include "LEDScreenHelper.h"
    
    LEDScreenHelper helper;
    unsigned char data[4*16];
    DotMatrix matrix(4,16,data);
    
    void setup(){
        helper.setup();
        for(int i = 0;i<16;++i){
            for(int j = 0;j<4;++j){
                matrix.set(i,j,i+j*16);
            }
        }
    }
    
    void loop(){
        helper.display(matrix);
    }

    例程如上。它的效果是把屏幕想象成一个左上角为(0,0)的坐标系,然后8个点(1byte)看成一块,每一块的0-3bit表示y坐标,4-5bit表示j坐标。

    效果如下:

    原理

    LED显示屏的原理答大体如下:首先对于一“行”,使用74HC595进行点亮,因此可以做到锁存之类。接下来,通过不停地切换“行选择”来达到点亮每一行的效果。从这个原理可以看出,我们的代码必须不停地对显示屏进行输出,否则最多只有一行会正常显示,其它全部会暗掉。

    注意事项

    1. 如果就驱动那一块单元板,不需要买40块那种的开关电源!就算你要买,也先问清楚怎么和220V接,貌似要自己搞连接线。
    2. 程序中不要让它一直亮着,而要让大部分时间内OE=0,也就是不亮。这样子相当于PWM,能够让它的功耗降低,从而5V 2A的电源才足够。
    3. 貌似显示屏的电源不接也可以,接了会更亮一点;貌似显示屏电源和Arduino电源不共地也可以,虽然有人说要共地,有人甚至说要同一个电源。这个我不知道到底要怎么做,有知道的人麻烦告诉我一下,谢谢
  • 相关阅读:
    dp有哪些种类
    hibernate 双向n-n
    TextView——setCompoundDrawables说明
    Codeforces Round #FF (Div. 2)
    波折yosemite下载过程
    谁,例如下列方法区的指导下
    [LeetCode] 032. Longest Valid Parentheses (Hard) (C++)
    TCP/IP的经典网络编程
    NYOJ353 3D dungeon 【BFS】
    Ubuntu 14.04 grub2 温馨提示
  • 原文地址:https://www.cnblogs.com/turtlegood/p/4692534.html
Copyright © 2011-2022 走看看