Подключение и использование ЖК сегментного индикатора
- Войдите на сайт для отправки комментариев
Вс, 09/12/2012 - 08:08
Привет всем.. нашел в закромах сегментный жк индикатор с контроллером HT1621B
Подключил по статье китайцев, но показывает пока только статичные сегменты
#include "HT1621.h"
#define DATA_PIN 2
#define WR_PIN 13
#define RD_PIN 4
#define CS_PIN 5
HT1621 ht1621(DATA_PIN, WR_PIN, RD_PIN, CS_PIN);
void setup()
{
Serial.begin(9600);
if (! ht1621.begin()) {
Serial.println("Could not init device!\n");
}
//degrees celsius
// ht1621.writeMem(1, 0b1000);
// ht1621.writeMem(2, 0b1011);
}
int i = 0;
void loop()
{
ht1621.writeMem(0, 40);
// ht1621.writeMem(1, 0x1100);
// ht1621.writeMem(2, 0xfe);
// ht1621.writeMem(3, 0x7e);
// ht1621.writeMem(4, 0b1111);
// ht1621.writeMem(5, 0b1111);
// ht1621.writeMem(6, 0b1111);
// ht1621.writeMem(7, 0b1111);
ht1621.writeMem(6, 40);
// ht1621.writeMem(6, 41);
// ht1621.writeMem(1, 13);
// Serial.println(i);
// i++;
// delay(20000);
}
как запустить индикацию в динамике - ?
Это понятно но как допустим запустить отображение
к примеру
lcd.print(millis() / 1000);
те сформировать из сегментов цифру
Добрый вечер!
Интересно, получилось ли запустить индикатор?
А то и у меня таких парочка валяется (от старых кассовых аппаратов). Хотелось бы как-то их пристроить в дело.
Кто в теме, отпишитесь, пожалуйста!
Конечно получилось.
Только что вам писать?
Хотелось бы узнать источник вышеприведенного кода, схему подключения, описание библиотеки HT1621. Попытки поиска в сети дали скудные результаты. Видимо, довольно редкий контроллер. Прошу прощения за, может, наивные вопросы.
Я не волшебник - я только учусь...(С)
Пример, библиотека, как подключать понятно из примера.
Спасибо, Макс!
Завтра попробую раскурить тему.
Вопрос подключения ЖК от ККМ для меня тоже очень интересен.
У самого пока ничего не вышло.
Вот ссылка на схему моего модуля идикации от ЭКР 2102
Вопрос подключения ЖК от ККМ для меня тоже очень интересен.
У самого пока ничего не вышло.
Вот ссылка на схему моего модуля идикации от ЭКР 2102
И не выидет, если будете пытаться использовать "родной драйвер дисплея" собранный на микроЭВМ КР1820, потому как какой там протокол обмена знает только тот кто его придумал.
Сейчас на руках модуля нет, но там стоит HT1621+ плюс дополнительные элементы (1 транзистор и резисторы)
Следующим шагом планирую все отрезать, оставив лишь индикатор и HT1621
А зачем тогда ссылку левую дали?
Я подключал дисплей от 130-го меркурия (у byteman наверное он и есть), на этом драйвере, все работает, но очень криво (я бы даже сказал через ж..пу) разнесена память по сегментам, поэтому "плюнул на него" и выбросил.
Макс есть твой пример чет не могу разобратся как сегменты задавать
Доброго здоровья, уважаемые единомышленники!



С праздником Победы!
Символично, что именно в такой день получилось написАть о том, как я всё-таки "победил" это злополучное устройство - плату ЖК индикатора от старого ЭКР-3102 на контроллере HT1621B (тип самого ЖКИ установить не удалось, да и не очень-то хотелось :), обычный 8-разрядный с децимальными точками в каждом разряде). Вот он, красавец:
и
С "наскока" заставить его работать так, как я хотел, не получилось ;( пришлось немного повозиться.
Итак, я хотел, подключив данное устройство к Ардуине, с помощью несложных команд типа "позиция-цифра" выводить на индикатор нужную информацию. Для реализации задуманного пришлось изучить даташит на контроллер HT1621B
http://www.alldatasheet.com/datasheet-pdf/pdf/96976/HOLTEK/ht1621b.html
схему подключения его к ЖКИ
https://dl.dropboxusercontent.com/u/70315839/HT1621_LCD.tif
а также библиотеки HT1621.h и HT1621.cpp:
http://code.google.com/p/wirejungle/source/browse/trunk/libraries/HT1621/HT1621.cpp
В результате получилась небольшая программка, смысловым "стержнем" которой является функция writeDigit(pos, val), где pos - номер позиции 1...8 (слева направо), а val - цифра или знак, который требуется там отобразить.
Вот скриншот работающей программы вывода 4-значного числа, полученного с аналогового входа 0 (если, как у меня, вход не подключен, выводит "шумовые" случайные числа):
В скетче есть кое-какие поясняющие комментарии. Извиняйте, что на русском языке. Я не думаю, что данное устройство доступно где-нибудь за пределами русскоязычного пространства. Хотя там и без комментариев всё понятно.
Может быть, нужны какие-то пояснения по десятичной точке. Дело в том, что каждая точка "привязана" к своему знакоместу, и отобразить её независимо от цифры нельзя. Поэтому для отображения цифры с точкой пользуйтесь функцией writeDigitPoint(pos, val).
Символ "минус" в массиве констант находится под номером 16, пробел - под 17, поэтому отображать их надо через writeDigit(pos, 16) и writeDigit(pos, 17) соответственно.
#include "HT1621.h" #define DATA_PIN 2 #define WR_PIN 3 #define CS_PIN 4 #define RD_PIN 5 HT1621 ht1621(DATA_PIN, WR_PIN, RD_PIN, CS_PIN); byte pos; byte val; //массив констант для отображения цифр, минуса и пробела: byte arr[18][3]={ { 6,12, 6}, //0 { 0, 0, 6}, //1 { 2,14, 4}, //2 { 0,14, 6}, //3 { 4, 2, 6}, //4 { 4,14, 2}, //5 { 6,14, 2}, //6 { 0, 4, 6}, //7 { 6,14, 6}, //8 { 4,14, 6}, //9 { 6, 6, 6}, //A { 6,10, 2}, //b { 6,12, 0}, //C { 2,10, 6}, //d { 6,14, 0}, //E { 6, 6, 0}, //F { 0, 2, 0}, //- { 0, 0, 0} // }; //массив констант для отображения цифр с точкой: byte arr_point[10][3]={ { 6,12, 14}, //0. { 0, 0, 14}, //1. { 2,14, 12}, //2. { 0,14, 14}, //3. { 4, 2, 14}, //4. { 4,14, 10}, //5. { 6,14, 10}, //6. { 0, 4, 14}, //7. { 6,14, 14}, //8. { 4,14, 14} //9. }; //создаём новую функцию для отображения по шаблону "позиция-цифра": void writeDigit(byte pos, byte val){ for (byte i = 0; i < 3; i++) ht1621.writeMem(3*pos+5+i, arr[val][i]); } //а эта для отображения цифры с точкой: void writeDigitPoint(byte pos, byte val){ for (byte i = 0; i < 3; i++) ht1621.writeMem(3*pos+5+i, arr_point[val][i]); } void setup(){ pinMode(DATA_PIN, OUTPUT); pinMode(WR_PIN, OUTPUT); pinMode(CS_PIN, OUTPUT); Serial.begin(9600); if (! ht1621.begin()) { Serial.println("Could not init device!\n"); } } /**********************************************************************/ //эта короткая программка получает с аналогового входа 0 4-значное число //от 0 до 1023 и отображает его в первых 4-х разрядах: void loop() { int AI0=analogRead(0); for (byte i=4; i>0; i--) { writeDigit(i, AI0%10); AI0=(AI0-AI0%10)/10; } delay (100); } /******************************************************************/ //прикольная программка - как в американских боевиках "подбор кода": //раскомментируйте, кому интересно (не забыв закомментировать LOOP, который выше) /* void loop() { pos = random(9); val = random(10); writeDigit(pos, val); delay(pos*val+50); } */ //или вот так: /* void loop() { for (byte pos = 1; pos <= 8; pos++) { val = random(10); writeDigit(pos, val);} delay(100); } */Всё работало на версии Arduino 0022. На более поздних не проверял.
Всем успехов, ещё раз с праздником!
PS: Не пинайте сильно, если где чего не так. Буду очень рад, если поступят ещё какие предложения по улучшению и усовершенствованию.
Спасибо! Вечером попробую. Отпишусь.
Да, забыл сказать о подключении:
Провода с номерами 5 и 6 (маркировка на разъёме) извлекаются из фишки, "одеваются" в синюю и красную термоусадку и втыкаются в "-" и "+" Ардуины соответственно. А провода с номерами 1...4 подключаются соответственно к портам 2...5 Ардуины. На фотке видно.
Может потребоваться небольшая подстройка напряжения регулировки контрастности, т.к. +5 вольт, выдаваемые Ардуиной, могут немного отличаться от тех +5, которыми ЖКИ питался раньше.
А вот скетч для отображения миллисекунд во всех 8-ми разрядах, как спрашивал VovaRino:
#include "HT1621.h" #define DATA_PIN 2 #define WR_PIN 3 #define CS_PIN 4 #define RD_PIN 5 HT1621 ht1621(DATA_PIN, WR_PIN, RD_PIN, CS_PIN); byte pos; byte val; byte arr[10][3]={ { 6,12, 6}, //0 { 0, 0, 6}, //1 { 2,14, 4}, //2 { 0,14, 6}, //3 { 4, 2, 6}, //4 { 4,14, 2}, //5 { 6,14, 2}, //6 { 0, 4, 6}, //7 { 6,14, 6}, //8 { 4,14, 6} //9 }; //создаём новую функцию для отображения по шаблону "позиция-цифра": void writeDigit(byte pos, byte val){ for (byte i = 0; i < 3; i++) ht1621.writeMem(3*pos+5+i, arr[val][i]); } void setup(){ pinMode(DATA_PIN, OUTPUT); pinMode(WR_PIN, OUTPUT); pinMode(CS_PIN, OUTPUT); ht1621.begin(); } void loop() { unsigned long AI0=millis(); for (byte i=8; i>0; i--) { writeDigit(i, AI0%10); AI0=(AI0-AI0%10)/10; } delay (10); }Здравствуйте всем! У меня в закромах валяется такой-же индикатор от экр2102. Хочу его тоже запустить. Но пишу на бейсике. Не могли бы рассказать "на пальцах", как его инициализировать. Т.е. какие команды подать на 1621,прежде чем выводить информацию на экран. При включении сразу выводить не получается. Спасибо.
Лучше, чем написано в фирменном даташите (ссылку на него ищите выше в посте #14), рассказать "на пальцах" Вам не сможет никто. В-частности, там на стр. 14 приведены временнЫе диаграммы команд управления, а на стр. 18-19 - список всех доступных команд. Я пользовал штатную библиотеку HT1621.h/HT1621.cpp. Естественно, на С++. Что касаемо Бейсика, я помню его только 25-летней давности (ZX-Spectrum) и вряд ли он имеет много общего с современным Бейсиком. По крайней мере, мне было проще изучить С++, чем пытаться переучиваться со старого Бейсика на новый.
Ну это понятно. Пишу в БаскомАВР, команду в 1621 я могу послать. Вопрос как его заставить работать с данным индикатором. Какой BIAS включать?. библиотеки нет, поэтому делаю так shiftout bias, shiftout sys_en, shiftout lcd_on. После чего включаются все сегменты. При команде lcd_off он отключается. Если отправляю команду b101000111111111......(т.е. обращаюсь к озу с адреса(), и заношу туда еденици, ну или нули(пробовал по разному)) - реакции нет. Что ещё я не включил, какой мультиплекс у индикатора?
А посмотрите схему, она в отличном качестве; хорошо видно, что используются 3 линии COM (COM0, COM1 и COM2) и 24 линии адреса сегментов (с 8 по 31). Там же приведена таблица посегментной распиновки ЖКИ. Например, чтобы отобразить цифру "0", скажем, в 3-м разряде, надо по адресам 14, 15, 16 (0b01110, 0b01111, 0b10000) записать соответственно 6, 12, 6 (0b0110, 0b1100, 0b0110).
Таким образом, для того чтобы включились все сегменты, надо последовательно (хотя не обязательно по порядку) по адресам с 8 по 31 записать все единицы (0b1111). Почему у Вас сразу после команды инициализации включаются сразу все сегменты, я не знаю. Могу только посоветовать попробовать поизменять напряжение управления контрастностью (вывод 16 контроллера).
Может кому понадибится.
Моя моделька этого индикатора для Proteus.
http://kazus.ru/forums/showpost.php?p=691031&postcount=1539
Спасибо! Кстати На этом контроллере есть ещё индикатор от ккм "Меркурий 130" . В нём 10 знакомест, нет чёрточек и размер всего блока- размер индикатора. Я такой уже заюзал.
Не завёл, пробывал 0022 ругается и не компилит...
ЗАвёл. Не скажу, что с первого раза.
https://www.youtube.com/watch?v=OKxM_Um8YhQ
Я даже немного доработал
тоже давно валялся данный дисплей,стало интересно-заведется или нет - запустился!!! надо будет изготовить что нибудь из измерительного,темпер или вольтметр или часики сделать...
по поводу последнего дисплея я уже находил проект часов на мега8
Вот ссылка http://sxem.org/forum/chasy/298-chasy-na-zhki-ht1621b?start=75
В протеусе работает эта прошивка TC_ATM8_LCD1621B1
как ее прицепить в среду Ардуино подскажите в этом я ещё новичек
хотелось бы ещё что-нибудь сделать с этим индикатором
Для настройки времени отправте текущие время в монитор порта в формате 03:25:06 Скетчь написан для ардуина уна
// HT1621_Clock.ino // Часы на базе дисплея HT1621B (от ЭКР-2102) // Отображает ЧЧ-ММ-СС (дефис – средний сегмент G) #define sbi(x, y) (x |= (1 << y)) #define cbi(x, y) (x &= ~(1 << y)) #define uchar unsigned char #define uint unsigned int // Команды HT1621 #define ComMode 0x48 // 4COM, 1/2bias #define RCosc 0x30 // встроенный RC-генератор #define LCD_on 0x06 // включить LCD #define LCD_off 0x04 // выключить LCD #define Sys_en 0x02 // включить системный генератор #define CTRl_cmd 0x80 // команда управления #define Data_cmd 0xa0 // команда записи данных // Пины Arduino #define CS 2 #define WR 3 #define DATA 4 #define CS1 digitalWrite(CS, HIGH) #define CS0 digitalWrite(CS, LOW) #define WR1 digitalWrite(WR, HIGH) #define WR0 digitalWrite(WR, LOW) #define DATA1 digitalWrite(DATA, HIGH) #define DATA0 digitalWrite(DATA, LOW) // Таблицы соответствия сегментов для 8 разрядов (по 9 элементов на разряд: A..G, DP, UpperLine) const byte HT1621_Address[] = { 0x04,0x05,0x05,0x04,0x04,0x04,0x04,0x05,0x0E, 0x06,0x06,0x06,0x06,0x05,0x05,0x06,0x06,0x04, 0x07,0x08,0x08,0x07,0x07,0x07,0x07,0x08,0x05, 0x09,0x09,0x09,0x09,0x08,0x08,0x09,0x09,0x07, 0x0A,0x0B,0x0B,0x0A,0x0A,0x0A,0x0A,0x0B,0x08, 0x0C,0x0C,0x0C,0x0C,0x0B,0x0B,0x0C,0x0C,0x0A, 0x0D,0x0E,0x0E,0x0D,0x0D,0x0D,0x0D,0x0E,0x0B, 0x0F,0x0F,0x0F,0x0F,0x0E,0x0E,0x0F,0x0F,0x0D }; const byte HT_1621_Value[] = { 0x04,0x40,0x20,0x08,0x20,0x40,0x02,0x80,0x08, 0x40,0x04,0x02,0x80,0x02,0x04,0x20,0x08,0x80, 0x04,0x40,0x20,0x08,0x20,0x40,0x02,0x80,0x08, 0x40,0x04,0x02,0x80,0x02,0x04,0x20,0x08,0x80, 0x04,0x40,0x20,0x08,0x20,0x40,0x02,0x80,0x08, 0x40,0x04,0x02,0x80,0x02,0x04,0x20,0x08,0x80, 0x04,0x40,0x20,0x08,0x20,0x40,0x02,0x80,0x08, 0x40,0x04,0x02,0x80,0x02,0x04,0x20,0x08,0x80 }; // Маска для 7-сегментных цифр 0-9 (порядок A B C D E F G) const byte b7SegDsp[] = { 0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xE6 }; // Виртуальный экран (16 байт) byte HT1621_Screen[16]; // Номера позиций на дисплее (всего 8 разрядов) #define POS_HOUR_TEN 0 #define POS_HOUR_UNIT 1 #define POS_DASH1 2 #define POS_MIN_TEN 3 #define POS_MIN_UNIT 4 #define POS_DASH2 5 #define POS_SEC_TEN 6 #define POS_SEC_UNIT 7 // --------------------------------------------------------------- // Базовые функции работы с HT1621 // --------------------------------------------------------------- void SendBit_1621(uchar sdata, uchar cnt) { uchar i; for(i = 0; i < cnt; i++) { WR0; delayMicroseconds(1); if(sdata & 0x80) DATA1; else DATA0; delayMicroseconds(1); WR1; delayMicroseconds(1); sdata <<= 1; } delayMicroseconds(1); } void SendCmd_1621(uchar command) { CS0; SendBit_1621(0x80, 4); SendBit_1621(command, 8); CS1; } void Write_1621(uchar addr, uchar sdata) { addr <<= 3; CS0; SendBit_1621(0xa0, 3); SendBit_1621(addr, 6); SendBit_1621(sdata, 8); CS1; } void Init_1621(void) { SendCmd_1621(Sys_en); SendCmd_1621(RCosc); SendCmd_1621(ComMode); SendCmd_1621(LCD_on); } void HT1621_Clear(void) { for(byte j = 0; j < 16; j++) { HT1621_Screen[j] = 0x00; } } void HT1621_Show(void) { for(byte i = 0; i < 16; i++) { Write_1621(i, HT1621_Screen[i]); } } // --------------------------------------------------------------- // Вывод цифры (0-9) в заданную позицию (0..7) // --------------------------------------------------------------- void HT1621_Display(byte bPos, byte bNum, byte lDecimalPoint, byte lUpperLine) { byte bCheckByte = b7SegDsp[bNum]; for(byte i = bPos * 9; i <= bPos * 9 + 6; i++) { if(bCheckByte & 0x80) { byte bAddr = HT1621_Address[i]; byte bValue = HT_1621_Value[i]; HT1621_Screen[bAddr] |= bValue; } bCheckByte <<= 1; } if(lDecimalPoint) { byte bAddr = HT1621_Address[bPos * 9 + 7]; byte bValue = HT_1621_Value[bPos * 9 + 7]; HT1621_Screen[bAddr] |= bValue; } if(lUpperLine) { byte bAddr = HT1621_Address[bPos * 9 + 8]; byte bValue = HT_1621_Value[bPos * 9 + 8]; HT1621_Screen[bAddr] |= bValue; } } // --------------------------------------------------------------- // Вывод дефиса (средний сегмент G) в заданную позицию // --------------------------------------------------------------- void DisplayDash(byte bPos) { byte idx = bPos * 9 + 6; // сегмент G (индекс 6 в группе из 9) byte bAddr = HT1621_Address[idx]; byte bValue = HT_1621_Value[idx]; HT1621_Screen[bAddr] |= bValue; } // --------------------------------------------------------------- // Обновление всего дисплея по часам, минутам, секундам // --------------------------------------------------------------- void UpdateDisplay(byte hours, byte minutes, byte seconds) { HT1621_Clear(); // Часы HT1621_Display(POS_HOUR_TEN, hours / 10, 0, 0); HT1621_Display(POS_HOUR_UNIT, hours % 10, 0, 0); // Первый дефис (между часами и минутами) DisplayDash(POS_DASH1); // Минуты HT1621_Display(POS_MIN_TEN, minutes / 10, 0, 0); HT1621_Display(POS_MIN_UNIT, minutes % 10, 0, 0); // Второй дефис (между минутами и секундами) DisplayDash(POS_DASH2); // Секунды HT1621_Display(POS_SEC_TEN, seconds / 10, 0, 0); HT1621_Display(POS_SEC_UNIT, seconds % 10, 0, 0); HT1621_Show(); } // --------------------------------------------------------------- // Установка времени через Serial (формат ЧЧ:ММ:СС) // --------------------------------------------------------------- void SetTimeFromSerial(byte &h, byte &m, byte &s) { if(Serial.available() >= 8) { byte buf[8]; for(byte i = 0; i < 8; i++) buf[i] = Serial.read(); if(buf[2] == ':' && buf[5] == ':') { h = (buf[0] - '0') * 10 + (buf[1] - '0'); m = (buf[3] - '0') * 10 + (buf[4] - '0'); s = (buf[6] - '0') * 10 + (buf[7] - '0'); if(h > 23) h = 23; if(m > 59) m = 59; if(s > 59) s = 59; Serial.print("Time set to "); Serial.print(h); Serial.print(":"); Serial.print(m); Serial.print(":"); Serial.println(s); } } } // --------------------------------------------------------------- // setup() // --------------------------------------------------------------- void setup() { pinMode(CS, OUTPUT); pinMode(WR, OUTPUT); pinMode(DATA, OUTPUT); Init_1621(); HT1621_Clear(); HT1621_Show(); Serial.begin(9600); Serial.println("HT1621 Clock. Send time like 12:34:56"); } // --------------------------------------------------------------- // loop() // --------------------------------------------------------------- unsigned long previousMillis = 0; unsigned long secondsCounter = 0; byte hours = 0, minutes = 0, seconds = 0; void loop() { unsigned long currentMillis = millis(); if(currentMillis - previousMillis >= 1000) { previousMillis = currentMillis; secondsCounter++; hours = (secondsCounter / 3600) % 24; minutes = (secondsCounter % 3600) / 60; seconds = secondsCounter % 60; UpdateDisplay(hours, minutes, seconds); } SetTimeFromSerial(hours, minutes, seconds); if(Serial.available()) { // Пересчитываем счётчик секунд после установки времени secondsCounter = (unsigned long)hours * 3600 + minutes * 60 + seconds; } }