Разбираюсь с низкоуровневым программированием матрицы. Это жесть!
Логика работы такая.
Матрица фактически разделена на два блока, верхние 16 строк и нижние 16 строк. В первые пишут через R1, G1 и B1, во вторые, соответственно, через R2, G2 и B2.
Одновременно светится только одна строка. Для полноценного свечения нужно просто организовывать развёртку. Фактически памяти там в каждой половине экрана — один сдвиговый регистр + выбор адреса, куда ему светить.
Сигналом LAT (пиком высокого уровня) сигнализируем, чтобы сдвиговый регистр принял строку данных. Дальше в цикле 64 раза выставляем данные (R1,G1,B1,R2,G2,B2) и запихиваем их низким импульсом CLK. Сразу в оба сдвиговых регистра.
Входами A, B, C, D выбираем строку, в которой светится этот сдвиговый регистр. Точнее, будут светиться две строки, в первой и второй половинах.
Для того, чтобы избегать мерцания и призраков, высоким уровнем OE на время манипуляций можно гасить отображение.
Т.е. полный цикл выглядит примерно так:
code cpp
// Цикл по строкам в каждой половине экрана
for(int row=0; row<16; row++)
{
// Вырубаем отображение
digitalWrite(OE, HIGH);
// Указываем принять данные
digitalWrite(LAT, HIGH);
digitalWrite(LAT, LOW);
// Цикл вывода светодиодов в строке
for(int i=0; i<64; i++)
{
// Выставляем биты включения светодиодов
digitalWrite(R1, r1);
digitalWrite(G1, g1);
digitalWrite(B1, b1);
digitalWrite(R2, r2);
digitalWrite(G2, g2);
digitalWrite(B2, b2);
// Отправляем выставленное значение
digitalWrite(CLK, LOW);
digitalWrite(CLK, HIGH);
}
// К этому месту строка светодиодов загружена
// Выставляем адрес для отображения
digitalWrite(A, row & B00000001);
digitalWrite(B, row & B00000010);
digitalWrite(C, row & B00000100);
digitalWrite(D, row & B00001000);
digitalWrite(OE, LOW);
}
Правда, в таком виде цикл вывода будет работать ОЧЕНЬ медленно (digitalWrite работает медленно!), экран будет очень тёмный и будет мерцать, т.к. заполнение матрицы будет происходить бОльшую часть времени.
Для ускорения работы нужно делать запись сразу всего блока цветов одной записью в регистр. Например, в случае MEGA вешаем R1,G1,B1,R2,G2,B2 на, соответственно, 24,25,26,27,28 и 29 пин. И тогда это будут биты со 2 по 7 регистра PORTA. А CLK пусть висит на 11 порту, это 5 бит PORTB. Внутренний цикл станет примерно таким:
code cpp
// Цикл вывода светодиодов в строке
for(int i=0; i<64; i++)
{
// Выставляем биты включения светодиодов (младшие два бита обнуляются)
PORTA = (r1<<2) | (g1 << 3) | (b1 << 4) | (r2 << 5) | (g2 << 6) | (b2 << 7
…
Дальше »»»
… чтобы понять рекурсию, нужно сперва понять рекурсию …
![4](/_bors/images/browsers/opera.gif)