很久之前写了一篇树莓派用Java驱动一个8x8 LED矩阵,传送门: Java控制树莓派8x8矩阵LED_xss13的博客-CSDN博客
今天我要吐槽一下,CSDN各种低质量的文章,没有任何用处而且还帮倒忙,驱动多个LED矩阵这个问题在开始的时候卡了我好几天,后来被迫无奈放弃了,好在今天想起来了,又拾起来再研究了一次,终于搞清楚了。
首先感谢这篇文章对我的帮助,不胜感激:
怎样将MAX7219驱动的LED矩阵8x8与ATtiny85微控制器连接-电子发烧友网 ,让我明白了一些API具体的意义,接下来再进行操作,即便不清楚,也可以慢慢的猜,慢慢的试验出来。
步入正题,首先如何接线就不多说了,之前的文章都有,上代码:
//len是数据长度,一个8x8矩阵可以用一个long表示,一个long有8个字节。
//比如len = 16,表示驱动两个led矩阵。
if (len % 8 != 0) {
return;
}
int size = len/8;
if (!isInit) {
isInit = true;
wiringPiSetup();
pinMode(DIN,OUTPUT);
pinMode(CS,OUTPUT);
pinMode(CLK,OUTPUT);
//首先要明确,CS LOW表示解锁max7219内存,此时可以将数据送入到寄存器,所以将每个led矩阵的数据全部都送入后再将CS HIGH,表示锁住内存,即完成一次数据写入。
//再者,只要addr相同,重复往寄存器写数据,就是从第一个LED开始一个一个的有顺序的写入(同一个addr写完后一定要锁定内存来通知本次数据写完,可以写下一个addr的数据)。
digitalWrite(CS, LOW);
for (int i = 0; i < size; i++) {
writeData(0x09,0x00);
}
digitalWrite(CS, HIGH);
digitalWrite(CS, LOW);
for (int i = 0; i < size; i++) {
writeData(0x0a,0x03);
}
digitalWrite(CS, HIGH);
digitalWrite(CS, LOW);
for (int i = 0; i < size; i++) {
writeData(0x0b,0x07);
}
digitalWrite(CS, HIGH);
digitalWrite(CS, LOW);
for (int i = 0; i < size; i++) {
writeData(0x0c,0x01);
}
digitalWrite(CS, HIGH);
digitalWrite(CS, LOW);
for (int i = 0; i < size; i++) {
writeData(0xff,0x00);
}
digitalWrite(CS, HIGH);
}
long []all = new long[size];
for (int i = 0; i < all.length; i++) {
//此处我用的netty的buf,通过socket将数据输送过来(len就是从buf里读出来的数据长度),这里可以替换成自己的数据,可以参见 DefaultFont8x8.getPoints()方法将数据从long转为byte或从byte转为long,本质上就是用8x8的LED矩阵拼图拼成一个大的LED屏幕
all[i]=in.readLong();
}
int index = 0;
byte[][] data = new byte[size][8];
for (int i = 0; i < size; i++) {
//该类在我的单个8x8矩阵的文章里有,可以从那里copy出来。
data[i] = DefaultFont8x8.getPoints(all[index]);
index ++;
}
//注意这里,j = 1表示写入每个8x8矩阵的第一行,2表示第二行,以此类推;
//即把所有的LED矩阵的第一行都写完了再封锁内存,然后再写第二行,直到把8行数据都写完为止。
//这样写入的数据不会存在CSDN另一篇播客用户区评论的有剪影的问题。
for (int j = 1; j <= 8; j++) {
digitalWrite(CS, LOW);
for (int i = 0; i < size; i++) {
writeData(j, data[i][j-1]);
}
digitalWrite(CS, HIGH);
}
调用到的方法:
private void writeData(int addr, int data) {
//通知要往那个地址上写
writeByte(addr);
//往这个地址上写什么样的数据,连续写两次表示写完一次数据
writeByte(data);
//表示将数据flush出去
digitalWrite(CLK,HIGH);
}
private void writeByte(int data) {
for (int i = 0; i < 8; i++) {
digitalWrite(CLK, LOW);
digitalWrite(DIN, (data & 0x80) == 0 ? LOW : HIGH);
digitalWrite(CLK, HIGH);
data <<= 1;
}
}
需要导入的包:
import static com.pi4j.wiringpi.Gpio.HIGH;
import static com.pi4j.wiringpi.Gpio.LOW;
import static com.pi4j.wiringpi.Gpio.OUTPUT;
import static com.pi4j.wiringpi.Gpio.digitalWrite;
import static com.pi4j.wiringpi.Gpio.pinMode;
import static com.pi4j.wiringpi.Gpio.wiringPiSetup;
好了,到此为止,一个多段LED驱动就告一段落了,接下来就可以尽情的玩耍了。