【Z】Arduino也能驱动LED显示屏,LED业界标准Arduino驱动方案解析

现在市面上有很多很多的LED显示屏,但大多都基于同一种,或者同一类型的驱动方式,简称08驱动方式,它内部有LED点阵,74HC595,以及138行扫芯片组成,但毫无例外的,是主控板都采用了STC方案,或者串口方案,而Arduino驱动却鲜有人用,今天,小Z就带了LED业界标准Arduino驱动方案的介绍与解析

QQ图片20130629164530.jpg

2013-6-29 16:45 上传
(96.58 KB)



市场上主流的显示屏有F3.75和F3.0两种,F后面代表的点阵屏单体LED的直径,而今天,小Z用的是F2.0的超密集进口点阵,显示效果个人很喜欢,下面是市场上常见的2种屏幕(F3.75 F3.0)和今天所使用的F2.0屏幕(分辨率均为16*64)的对比图,可以很轻松的看出大小的差别。

QQ截图20130629164945.jpg

2013-6-29 16:50 上传
(191.77 KB)





随后的重点便是行驱的模式,今天我推荐两种驱动模式,分别是1616驱动模式,和1664直接驱动模式,这两种模式各有特点,1616即是汉字是一个一个取模,一个一个显示,而1664是取模软件直接取出一幅完整的图像。如果是显示汉字的同学,推荐采用第一种,而显示图形的同学,推荐采用第二种。



下面,先把主体的演示代码发一下。

ARDUINO 代码复制打印

#define RowA 2 #define RowB 3#define RowC 4#define RowD 5//业界所采用的ABCD 08驱动模式int hc138en=6; //EN口//使用了硬件SPI,以下脚不能更改#define R1 11    //数据出  MOSI#define CLK 13   //时钟  SCK#define STB 10   //595 刷新显示SS#define DATAIN12 //数据入,读FLASH时有用MISO byte row=0;byte zzz[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF1,0xFF,0xE3,0xFF,0xC0,0x00,0x00,0xFF,0xF1,0xFF,0xE3,0xFF,0xC0,0x00,0x00,0x00,0x70,0x00,0xE0,0x01,0xC0,0x00,0x00,0x00,0xE0,0x01,0xC0,0x03,0x80,0x00,0x00,0x01,0xC0,0x03,0x80,0x07,0x00,0x00,0x00,0x03,0x80,0x07,0x00,0x0E,0x00,0x00,0x00,0x07,0x00,0x0E,0x00,0x1C,0x00,0x00,0x00,0x0E,0x00,0x1C,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0x38,0x00,0x70,0x00,0x00,0x00,0x38,0x00,0x70,0x00,0xE0,0x00,0x00,0x00,0x70,0x00,0xE0,0x01,0xC0,0x00,0x00,0x00,0xE0,0x01,0xC0,0x03,0x80,0x00,0x00,0x00,0xFF,0xF1,0xFF,0xE3,0xFF,0xC0,0x00,0x00,0xFF,0xF1,0xFF,0xE3,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};void spi_transfer(volatile char data){SPDR = data;      // Start the transmissionwhile (!(SPSR & (1<<SPIF))) // Wait the end of the transmission{};//return SPDR;      // return the received byte}void hc138sacn(byte r){//输出行线状态ABCD (A低,D高)  digitalWrite(RowA,(r & 0x01));  digitalWrite(RowB,(r & 0x02));  digitalWrite(RowC,(r & 0x04));  digitalWrite(RowD,(r & 0x08));}void hc595senddata(byte data){// 高位在前反相(1亮0灭) for (byte i=0; i<8;i++) { digitalWrite(CLK,0); if (data & 0x80) {   digitalWrite(R1, 0);  } else {   digitalWrite(R1, 1); } data=data<<1; digitalWrite(CLK,1); }}void setup () {  pinMode(RowA, OUTPUT);  pinMode(RowB, OUTPUT);  pinMode(RowC, OUTPUT);  pinMode(RowD, OUTPUT); //138片选  pinMode(hc138en, OUTPUT); //138 使能  pinMode(R1, OUTPUT);//595 数据  pinMode(CLK, OUTPUT); //595 时钟  pinMode(STB, OUTPUT); //595 使能  pinMode(DATAIN, INPUT); //595 使能 //digitalWrite(hc138d, HIGH);  Serial.begin(19200);  //SPI硬件设置  // SPCR = 01010000  //interrupt disabled,spi enabled,msb 1st,master,clk low when idle,  //sample on leading edge of clk,system clock/4 rate (fastest)  SPCR = (1<<SPE)|(1<<MSTR);  delay(10);}void loop () {if (Serial.available() > 0) {// read the incoming byte:row = Serial.read();// say what you got:Serial.print("I received: ");Serial.println(row, DEC);}for(row=0;row<16;row++){  for (int i=0;i<8;i++){    spi_transfer(~(zzz[i+row8]));   }  digitalWrite(hc138en, 1);//关闭显示  hc138sacn(row);    //换行  digitalWrite(STB, 0);  //595刷新     digitalWrite(STB, 1);  delayMicroseconds(500) ; //节电用,  digitalWrite(hc138en, 0);//开启显示  delayMicroseconds(500) ;//刷新频率调,差不多60HZ,1/16间隔}}
#define RowA 2 

#define RowB 3

#define RowC 4

#define RowD 5

//业界所采用的ABCD 08驱动模式

int hc138en=6; //EN口



//使用了硬件SPI,以下脚不能更改

#define R1 11 //数据出 MOSI

#define CLK 13 //时钟 SCK

#define STB 10 //595 刷新显示SS

#define DATAIN12 //数据入,读FLASH时有用MISO



byte row=0;

byte zzz[] =



{

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF1,0xFF,0xE3,0xFF,0xC0,0x00,0x00,

0xFF,0xF1,0xFF,0xE3,0xFF,0xC0,0x00,0x00,0x00,0x70,0x00,0xE0,0x01,0xC0,0x00,0x00,

0x00,0xE0,0x01,0xC0,0x03,0x80,0x00,0x00,0x01,0xC0,0x03,0x80,0x07,0x00,0x00,0x00,

0x03,0x80,0x07,0x00,0x0E,0x00,0x00,0x00,0x07,0x00,0x0E,0x00,0x1C,0x00,0x00,0x00,

0x0E,0x00,0x1C,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0x38,0x00,0x70,0x00,0x00,0x00,

0x38,0x00,0x70,0x00,0xE0,0x00,0x00,0x00,0x70,0x00,0xE0,0x01,0xC0,0x00,0x00,0x00,

0xE0,0x01,0xC0,0x03,0x80,0x00,0x00,0x00,0xFF,0xF1,0xFF,0xE3,0xFF,0xC0,0x00,0x00,

0xFF,0xF1,0xFF,0xE3,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

};







void spi_transfer(volatile char data)

{

SPDR = data; // Start the transmission

while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission

{

};

//return SPDR; // return the received byte

}





void hc138sacn(byte r){//输出行线状态ABCD (A低,D高)

digitalWrite(RowA,(r & 0x01));

digitalWrite(RowB,(r & 0x02));

digitalWrite(RowC,(r & 0x04));

digitalWrite(RowD,(r & 0x08));

}



void hc595senddata(byte data){// 高位在前反相(1亮0灭)

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

digitalWrite(CLK,0);

if (data & 0x80) {

digitalWrite(R1, 0);

} else {

digitalWrite(R1, 1);

}

data=data<<1;

digitalWrite(CLK,1);

}



}





void setup () {



pinMode(RowA, OUTPUT);

pinMode(RowB, OUTPUT);

pinMode(RowC, OUTPUT);

pinMode(RowD, OUTPUT); //138片选

pinMode(hc138en, OUTPUT); //138 使能



pinMode(R1, OUTPUT);//595 数据

pinMode(CLK, OUTPUT); //595 时钟

pinMode(STB, OUTPUT); //595 使能

pinMode(DATAIN, INPUT); //595 使能





//digitalWrite(hc138d, HIGH);

Serial.begin(19200);



//SPI硬件设置

// SPCR = 01010000

//interrupt disabled,spi enabled,msb 1st,master,clk low when idle,

//sample on leading edge of clk,system clock/4 rate (fastest)

SPCR = (1<<SPE)|(1<<MSTR);

delay(10);

}



void loop () {

if (Serial.available() > 0) {

// read the incoming byte:

row = Serial.read();



// say what you got:

Serial.print("I received: ");

Serial.println(row, DEC);

}



for(row=0;row<16;row++){



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

spi_transfer(~(zzz[i+row
8]));

}





digitalWrite(hc138en, 1);//关闭显示

hc138sacn(row); //换行

digitalWrite(STB, 0); //595刷新

digitalWrite(STB, 1);

delayMicroseconds(500) ; //节电用,

digitalWrite(hc138en, 0);//开启显示



delayMicroseconds(500) ;//刷新频率调,差不多60HZ,1/16间隔



}



}



从上面代码可以轻松的看出驱动原理并不复杂,其实就是把取模软件生成的字模,储存到一个数组里,然后调用arduino的硬件SPI通讯接口,把每8个LED看成是一个十六进制编码,然后一行一行的发送出去,发完一行后,再发出换行指令,就是这么简单。
置于16*16单个汉字取模显示,只要把主loop里的代码改为即可,其实就是简单的数学原理,把数组里的十六进制数按照一组一组提取显示而已~
ARDUINO 代码复制打印
for(row=0;row<16;row++){  for (int i=0;i<4;i++){//8片595   //硬件SPI发送8字节耗时:22US      spi_transfer(~(zzz[i*32+row*2]));//硬件SPI     spi_transfer(~(zzz[i*32+row*2+1]));//硬件SPI    }
for(row=0;row<16;row++){

for (int i=0;i<4;i++){//8片595
//硬件SPI发送8字节耗时:22US
spi_transfer(~(zzz[i*32+row*2]));//硬件SPI
spi_transfer(~(zzz[i*32+row*2+1]));//硬件SPI
}


取模软件请选择横向顺序扫描~下载在附件哦~

QQ截图20130629170050.jpg

2013-6-29 17:01 上传
(104.97 KB)


字模III Pro.zip

(1.99 MB, 下载次数: 738)

2013-6-29 17:02 上传
点击文件名下载附件



下面就是小Z做的演示品~主控为Arduino Tiny~欢迎大家根据此来完成各种有趣的Ardunio点阵屏作品~希望此文能给大家拓宽一定的思维~

QQ图片20130629164530.jpg

2013-6-29 17:08 上传
(96.58 KB)




QQ图片20130629164533.jpg

2013-6-29 16:45 上传
(139.58 KB)


QQ图片20130629164527.jpg

2013-6-29 16:45 上传
(116.17 KB)


QQ截图20130629164641.png

2013-6-29 16:47 上传
(396.5 KB)




QQ截图20130629164954.jpg

2013-6-29 16:50 上传
(87.21 KB)



via - 极客工坊

标签: Arduino教程