Работа с TM1639

Lictor
Offline
Зарегистрирован: 01.10.2015

Добрый день.

Пробую писать скетч для работы с TM1639 (библиотеки под него нет), но что-то не получается.

int dataPin = 8;  //Передача данных
int clockPin = 9; //Синхронизация передачи данных
int strobePin = 10; //Chip select,выбор микросхемы, разрешение/запрет записи данных

byte info[] = {B00001111, B00001111, B00000000, B00000000, //индикатор1 горит, 2 не горит
               B00001111, B00001111, B00000000, B00000000,
               B00001111, B00001111, B00000000, B00000000,
               B00001111, B00001111, B00000000, B00000000,
              }; //Значения для 8 сегментов, загораются через один
/************
   Байт передачи D7  D6  D5  D4  D3  D2  D1  D0
   первый         0  0    0   0   D   C   B   A
   второй         0  0    0   0   H   G   F   E
************/
void setup() {
  pinMode(dataPin, OUTPUT); //Настроим пины как выходы
  pinMode(clockPin, OUTPUT);
  pinMode(strobePin, OUTPUT);

  digitalWrite(strobePin, HIGH);  //Запретим запись в TM1639
  delay(1); //Время на запуск TM1639 после подачи питания

  digitalWrite(strobePin, LOW);  //Первый полученый байт - инструкция
  /******************
    Команда                                                     B7  B6  B5  B4  B3 B2 B1 B0
    Команда передачи, приема данных                             0   1   0   0   0  0  0  0
    Команда управления работы дисплея                           1   0   0   0   0  0  0  0
    Команда указания адреса загружаемых данных для отображения  1   1   0   0   0  0  0  0
  ******************/

  send(B01000000);  //Начать прием данных
  send(B11000000);  //Адрес первого индикатора
  send(info[0]);
  send(B11000001);  //Адрес первого индикатора
  send(info[1]);
  digitalWrite(strobePin, HIGH);

}

void loop() {

}

void send(byte data)  //Функция передачи данных
{
  for (int i = 0; i < 8; i++) { //Переберем биты отправляемого байта
    digitalWrite(clockPin, LOW); //Установим синхр. вывод в 0
    digitalWrite(dataPin, data & 1 ? HIGH : LOW); //В зависимости от значения бита выставим 0/1 на выводе Data
    data >>= 1; //Выберем следующий бит
    digitalWrite(clockPin, HIGH); //TM1639 считывает данные по фронту сигнала синхр. вывода
    delay(1);
  }
}

После загрузки индикаторы не горят

Ссылка на сайт с примером

И даташит

svm
Онлайн
Зарегистрирован: 06.11.2016

На сайте с примером вроде есть библиотеки. Да и без библиотек они нормально работают. Перед отправкой данных, должна быть инициализация и настройка регистров. 1639 похожа на 1650. Посмотрите здесь http://arduino.ru/forum/programmirovanie/kontroller-led-i-klaviatury-fd650v-kak-im-upravlyat#comment-232263   может там более понятно как с ним работать. И сюда загляните https://github.com/maxint-rd/TM16xx

Lictor
Offline
Зарегистрирован: 01.10.2015

Нет, не помогло, видимо я не понимаю чего-то фундаментального. 

Можно на примере моего кода, что там не хватает? Перечитал даташит, вроде все делаю правильно:

1. Отправляю команду на запись данных в регистр

2. Отправляю адрес сегмента

3. Отправляю что там и как должно гореть

svm
Онлайн
Зарегистрирован: 06.11.2016

Lictor пишет:

Нет, не помогло, видимо я не понимаю чего-то фундаментального. 

Можно на примере моего кода, что там не хватает? Перечитал даташит, вроде все делаю правильно:

1. Отправляю команду на запись данных в регистр

2. Отправляю адрес сегмента

3. Отправляю что там и как должно гореть

Сначала нужно инициализировать. Указать яркость, режим работы включен или выключен и что-то еще должно быть. Во всяком случае в 1650 так. Без этого он не включится.

Lictor
Offline
Зарегистрирован: 01.10.2015

Работает, пока только на вывод сообщений из массива info[]

Может кому поможет

int dataPin = 8;  //Передача данных
int clockPin = 9; //Синхронизация передачи данных
int strobePin = 10; //Chip select,выбор микросхемы, разрешение/запрет записи данных

byte info[] = {B10000001, B10000001, B10000001, B10000001, //данные для вывода
               B10000001, B10000001, B10000001, B11111111,
              };

void setup() {
  pinMode(dataPin, OUTPUT); //Настроим пины как выходы
  pinMode(clockPin, OUTPUT);
  pinMode(strobePin, OUTPUT);

  digitalWrite(strobePin, HIGH);  //Запретим запись в TM1639
  digitalWrite(clockPin, HIGH); //Уровень яркости 2/16
  delay(1); //Время на запуск TM1639 после подачи питания

  //////////////////////////////////////// инициализация
  sendCommand(0x40);  //Аналогично B01000000 - Запись данных для отображения
  sendCommand(B10000001);
  ////////////////////////////////////////

  //////////////////////////////////////// очистка буфера микросхемы
  digitalWrite(strobePin, LOW);
  send(0x00); //Команда из нулей (первое число после strobePin в 0 - воспринмается как команда)
  for (int i = 0; i < 16; i++) {  //Перебираем 16 байт что бы обнулить состояние всех 8 сегментов
    send(0x00); //Отправляем 16 байт, т.к. 1 сегмент управляется 2 полубайтами
  }
  digitalWrite(strobePin, HIGH);
  ////////////////////////////////////////

  //////////////////////////////////////// выведем что-нибудь на экран
  draw();
}

void loop() {

}

void sendCommand(byte cmd)  //Функция передачи команды
{
  digitalWrite(strobePin, LOW); //Разрешим запись выбрав микросхему
  send(cmd);  //Данные для передачи в микросхему
  digitalWrite(strobePin, HIGH);  //Запретим запись
}

void send(byte data)  //Функция передачи данных
{
  for (int i = 0; i < 8; i++) { //Переберем биты отправляемого байта
    digitalWrite(clockPin, LOW); //Установим синхр. вывод в 0
    digitalWrite(dataPin, data & 1 ? HIGH : LOW); //В зависимости от значения бита выставим 0/1 на выводе Data
    data >>= 1; //Выберем следующий бит
    digitalWrite(clockPin, HIGH); //TM1639 считывает данные по фронту сигнала синхр. вывода
    delay(1);
  }
}

void draw() {   //Функция вывода данных
  for (int i = 0; i < 8; i++) {
    int pos = B11000000;  //Команда указания адреса загружаемых данных для отображения
    int data; //Вспомогательная переменная 1
    int data2;  //Вспомогательная переменная 2
    for (int a = 0; a < 4; a++) { //Переберем первые 4 значащих байта 
      bitWrite(data, a, bitRead(info[a], i)); //и запишем их в первую вспомогательную переменную
    }
    for (int a = 4; a < 8; a++) {
      bitWrite(data2, a - 4, bitRead(info[a], i));  //а вторые во вторую переменную
    }
    sendData((pos + i * 2), data);  //отправим первый полубайт данных по первому адресу сегмента
    sendData((pos + i * 2 + 1), data2); //отправим второй полубай по второму адресу сегмента
  }
  sendCommand(0x40);  //Аналогично B01000000 - Запись данных для отображения
  sendCommand(B10001000); //Команда "Включить дисплей"
}

void sendData(byte address, byte data)  //Передадим данные по адресу
{
 // sendCommand(0x42);  //ЗАЧЕМ???
  digitalWrite(strobePin, LOW);
  send(0x00 | address); //Побитовое "или", по сути задаем адрес сегмента
  send(data); //Передаем данные для конкретного адреса
  digitalWrite(strobePin, HIGH);
}

 

Lictor
Offline
Зарегистрирован: 01.10.2015

Что бы темы не плодить... Пытаюсь прочесть состояние нажатия кнопок, но что-то не читается...

Что я делаю не так?

Чтение идет в цикле void loop()

 

int dataPin = 8;  //Передача данных
int clockPin = 9; //Синхронизация передачи данных
int strobePin = 10; //Chip select,выбор микросхемы, разрешение/запрет записи данных

byte info[] = {B11111111, B11111111, B11111111, B11111111, //данные для вывода
               B11111111, B11111111, B11111111, B11111111,
              };

void setup() {
  Serial.begin(9600);
  
  pinMode(dataPin, OUTPUT); //Настроим пины как выходы
  pinMode(clockPin, OUTPUT);
  pinMode(strobePin, OUTPUT);

  digitalWrite(strobePin, HIGH);  //Запретим запись в TM1639
  digitalWrite(clockPin, HIGH); //Тактовый пин в 1
  delay(1); //Время на запуск TM1639 после подачи питания

  //////////////////////////////////////// инициализация
  sendCommand(0x40);  //Аналогично B01000000 - Запись данных для отображения
  sendCommand(B10000001); //Яркость дисплея 2/16
  ////////////////////////////////////////

  //////////////////////////////////////// очистка буфера микросхемы
  digitalWrite(strobePin, LOW);
  send(0x00); //Команда из нулей (первое число после strobePin в 0 - воспринмается как команда)
  for (int i = 0; i < 16; i++) {  //Перебираем 16 байт что бы обнулить состояние всех 8 сегментов
    send(0x00); //Отправляем 16 байт, т.к. 1 сегмент управляется 2 полубайтами
  }
  digitalWrite(strobePin, HIGH);
  ////////////////////////////////////////

  //////////////////////////////////////// выведем что-нибудь на экран
  draw();
}

void loop() {
  delay(500);
  pinMode(dataPin, INPUT);
  digitalWrite(clockPin, LOW);
  digitalWrite(strobePin, LOW);
  Serial.println();
  
  sendCommand(0x42);  //Команда на запрос состояния кнопок
  for (int i = 0; i < 16; i++) {  //Перебираем 16 байт
    digitalWrite(clockPin, HIGH);
    Serial.print(digitalRead(dataPin));
    Serial.print(" ");
    digitalWrite(clockPin, LOW);
  }
  digitalWrite(strobePin, HIGH);
  
  pinMode(dataPin, OUTPUT);
}

void sendCommand(byte cmd)  //Функция передачи команды
{
  digitalWrite(strobePin, LOW); //Разрешим запись выбрав микросхему
  send(cmd);  //Данные для передачи в микросхему
  digitalWrite(strobePin, HIGH);  //Запретим запись
}

void send(byte data)  //Функция передачи данных
{
  for (int i = 0; i < 8; i++) { //Переберем биты отправляемого байта
    digitalWrite(clockPin, LOW); //Установим синхр. вывод в 0
    digitalWrite(dataPin, data & 1 ? HIGH : LOW); //В зависимости от значения бита выставим 0/1 на выводе Data
    data >>= 1; //Выберем следующий бит
    digitalWrite(clockPin, HIGH); //TM1639 считывает данные по фронту сигнала синхр. вывода
    delay(1);
  }
}

void draw() {   //Функция вывода данных
  for (int i = 0; i < 8; i++) {
    int pos = B11000000;  //Команда указания адреса загружаемых данных для отображения
    int data; //Вспомогательная переменная 1
    int data2;  //Вспомогательная переменная 2
    for (int a = 0; a < 4; a++) { //Переберем первые 4 значащих байта
      bitWrite(data, a, bitRead(info[a], i)); //и запишем их в первую вспомогательную переменную
    }
    for (int a = 4; a < 8; a++) {
      bitWrite(data2, a - 4, bitRead(info[a], i));  //а вторые во вторую переменную
    }
    sendData((pos + i * 2), data);  //отправим первый полубайт данных по первому адресу сегмента
    sendData((pos + i * 2 + 1), data2); //отправим второй полубай по второму адресу сегмента
  }
  sendCommand(0x40);  //Аналогично B01000000 - Запись данных для отображения
  sendCommand(B10001000); //Команда "Включить дисплей"
}

void sendData(byte address, byte data)  //Передадим данные по адресу
{
  // sendCommand(0x42);  //ЗАЧЕМ???
  digitalWrite(strobePin, LOW);
  send(0x00 | address); //Побитовое "или", по сути задаем адрес сегмента
  send(data); //Передаем данные для конкретного адреса
  digitalWrite(strobePin, HIGH);
}

 

Lictor
Offline
Зарегистрирован: 01.10.2015

Выдержка из даташита, вроде все верно, отправил команду 0х42 на считывание, считал 2 байта даных

Lictor
Offline
Зарегистрирован: 01.10.2015

Немного поправил функцию loop, остальное без изменений, но все так же не работает, в мониторе порта только 0

void loop() {
  delay(500);
  digitalWrite(clockPin, LOW);
  Serial.println();

  digitalWrite(strobePin, LOW);
  send(0x42);  //Команда на запрос состояния кнопок
  delay(1);
  pinMode(dataPin, INPUT);
  delay(1);
  for (int i = 0; i < 8; i++) {  //Перебираем 8 байт

    digitalWrite(clockPin, HIGH);
    delay(1);
    Serial.print(digitalRead(dataPin));
    Serial.print(" ");
    digitalWrite(clockPin, LOW);
  }

  delay(1);
  for (int p = 0; p < 8; p++) {  //Перебираем 8 байт

    digitalWrite(clockPin, HIGH);
    delay(1);
    Serial.print(digitalRead(dataPin));
    Serial.print(" ");
    digitalWrite(clockPin, LOW);
  }
  pinMode(dataPin, OUTPUT);
  digitalWrite(strobePin, HIGH);

}

 

Lictor
Offline
Зарегистрирован: 01.10.2015

Вопрос снят, все работает.

Lictor
Offline
Зарегистрирован: 01.10.2015

Может кому пригодится 

https://github.com/MaximAivazov/Arduino-TM1639.git