Отправка данных перед повышением края часов
Я пытаюсь управлять светодиодной лентой со специальным протоколом (разработанным выше I2C).
Но в моих тестах мне удалось выяснить, как это работает:
Вы устанавливаете Clk на ноль, отправляете бит в строке данных, затем устанавливаете Clk на высокий уровень. Основываясь на количестве пикселей, я должен отправить 16 бит для каждого цвета (красный, зеленый, синий).
Я смог сгенерировать тактовый сигнал на частоте 8 МГц с помощью этого кода:
const byte Clock = 9;
const byte Data = 10;
void setup ()
{
pinMode (Clock, OUTPUT);
pinMode (Data, OUTPUT);
digitalWrite(Data, HIGH);
TCCR1A = bit (COM1A0);
TCCR1B = bit (WGM12) | bit (CS10);
OCR1A = 0;
}
void loop ()
{
...
}
Мои вопросы: Как я могу отправить данные в это конкретное время, когда часы стоят на нуле?
Обратите внимание, что использование функции digitalWrite() не работало из-за ограничения частоты использования этой функции.
Спасибо за любую полезную информацию.
2 ответа
Лучший ответ:
После ночи непрерывных тестов я выяснил, как правильно управлять светодиодной лентой, используя следующее:
1- Чтобы применить любое значение RGB (пиксель), вы должны отправить полный кадр данных на все пиксели. В моей полосе 12 пикселей, поэтому, чтобы превратить, например, первый пиксель в красный, я должен отправить 11 нулевых пикселей, а затем красный пиксель.
2- Задержка и синхронизация, как упоминалось выше @Majenko, были ключевыми, вы просто устанавливаете данные и пульсируете clk , это легко.
3- используемый протокол не является SPI или I2C, это пользовательский протокол, основанный на специальном драйвере, разработанном частной компанией (не драйвер для общего использования или рынка, он был разработан для большого проекта настенного освещения).
#define setPin(b) ( (b)<8 ? PORTD |=(1<<(b)) : PORTB |=(1<<(b-8)) )
#define clrPin(b) ( (b)<8 ? PORTD &=~(1<<(b)) : PORTB &=~(1<<(b-8)) )
#define Data 7
#define Clk 9
void setup() {
pinMode(Data,OUTPUT);
pinMode(Clk, OUTPUT);
Serial.begin(9600);
}
void loop() {
int i, j, k, q, r, lim_j, lim_i;
int red, green, blue;
for(k=0; k<12; k++)
{
r= k%3;
lim_j = 2 - r;
q = k/3;
lim_i = 3 - q;
Serial.print(lim_i); Serial.println(lim_j);
clrPin(Clk);
delayMicroseconds(5);
setPin(Clk);
delayMicroseconds(5);
for(i=0; i<4; i++)
{
for(j=0; j<3; j++)
{
if(i==lim_i && j==lim_j)
one_pixel(1200, 0, 0);
else
one_pixel(0, 0, 0);
}
}
clrPin(Clk);
delay(1000);
}
}
int one_pixel(int red, int green, int blue)
{
rapid_serialize(red);
delayMicroseconds(5);
rapid_serialize(green);
delayMicroseconds(5);
rapid_serialize(blue);
delayMicroseconds(5);
clrPin(Clk);
}
inline void rapid_serialize (uint16_t color) // пока просто копия, а не указатель
{
uint16_t bit_shift = 32768;
while (bit_shift)
{
clrPin(Clk);
bit_shift = bit_shift>>1;
if ((bit_shift & color) == 0)
clrPin(Data);
else
setPin(Data);
delayMicroseconds(5);
setPin(Clk);
delayMicroseconds(5);
}
}
Похоже, у вас есть некоторые неправильные представления.
Чтобы работать с тактовыми сигналами, такими как в SPI, вы устанавливаете линии данных на желаемое значение, а затем повышаете тактовый сигнал с низкого на высокий. Приемное устройство обнаруживает переход от низкого к высокому уровню и считывает состояние линий данных.
Если вы сделаете это в другом порядке (переключите тактовый сигнал с низкого на высокий, затем установите контакт(ы) данных), то приемник обнаружит нарастающий фронт тактового сигнала и попытается считать значение данных до того, как оно будет установить правильно.
С тактовой линией, как в вашей настройке, связь не зависит от фиксированного времени. Линия часов сообщает приемнику, когда данные доступны, и вы можете использовать любую синхронизацию часов (вплоть до максимальной скорости, поддерживаемой оборудованием).
Абсолютно верно, я нашел решение после кошмара тестирования. Проблема была на самом деле с драйвером светодиода, он не работал ни с одним распространенным последовательным протоколом. Спасибо за помощь, @Mohammed BENHADINE
- Как сделать очень долгую функцию delay(), несколько часов
- Разница между «time_t» и «DateTime»
- Получение BPM из данного кода
- Создание таймера с использованием часов реального времени с указанием времени начала и остановки
- Arduino непрерывно считывает значение АЦП с помощью прерывания
- Генерация стабильной частоты
- Как исправить ошибку компиляции для tone (), используя тот же таймер, что и другая функция
- Использовать timer0, не влияя на millis() и micros().
@Nick Gammon: думаю, я должен упомянуть тебя :p, @Mohammed BENHADINE
Для меня это больше похоже на SPI, чем на I2C. Вы можете изменить полярность синхронизации и фронт выборки, изменив режим SPI., @Majenko
SPI отправляет байты, разделенные небольшим интервалом времени, нельзя ли отправить несколько битов без интервала времени?, @Mohammed BENHADINE
Когда у вас есть синхронные часы, нет понятия «интервал времени». Время не имеет значения. Вот почему у вас есть тактовый сигнал. Имеет значение только изменение уровня сигнала в часах. Если у вас есть что-то, что требует данных в точное время без разницы во времени, то у вас нет тактового сигнала, и связь является асинхронной (например, UART)., @Majenko
я имел в виду задержку между передачей байт, @Mohammed BENHADINE
Если у вас не очень-очень странное устройство, то **задержки никого не волнуют**. SPI даже не *имеет* понятие байтов., @Majenko
В этом весь смысл* протокола, который является *синхронным*. Это все *синхронизируется* по тактовому сигналу. Данные считываются, когда часы *переходят* с LOW на HIGH (или наоборот для некоторых устройств). Неважно, *когда* это изменение произойдет. На том, что это *действительно* происходит., @Majenko
Однако, если бы вы дали нам подсказку, *что* на самом деле представляет собой эта светодиодная лента и ее протокол, мы были бы в лучшем положении, чтобы помочь вам. Без этого мы просто писаем по ветру., @Majenko
Спасибо за это ясное и простое объяснение того, как работает SPI, я уверен, что SPI - это выбор, приведенный выше код включает все светодиоды с высокой интенсивностью, поскольку данные всегда равны 1. Теперь я попытаюсь создать экземпляр связь SPI со светодиодами и посмотреть, как это работает., @Mohammed BENHADINE
Однако есть некоторые странные протоколы. Не могли бы вы *пожалуйста* поделиться устройством и таблицей данных, с которыми вы работаете?, @Majenko
Там нет указания на номер версии драйвера, я прикрепил изображения к сообщению, я попытался отладить и протестировать, чтобы увидеть распиновку драйвера (также прилагается) ..., @Mohammed BENHADINE
Ни на одной из фишек нет номеров?, @Majenko
Ничего, какая-то маска закрывает все фишки, @Mohammed BENHADINE