ИМС PT6312 — это контроллер вакуумного люминесцентного дисплея (VFD). Поддерживает работу от 4 сеток при 16 сегментах и до 11 сеток при 11 сегментах. Управление ИМС PT6312 3-Wire.
ИМС PT6312 помимо работы как драйвер VFD, имеет сканер клавиатуры 6х4, порты для подключения светодиодов и 4-х разрядный порт общего назначения, но в данной статье будет рассмотрена работа ИМС PT6312 только как драйвер VFD.
Применение PT6312 в качестве драйвера вакуумного люминесцентного дисплея, позволяет реализовать динамическую индикацию вакуумного люминесцентного дисплея с минимальным числом компонентов, сама схема драйвера практически не содержит внешних компонентов. В данной статье будет описан пример создания часов на базе вакуумного люминесцентного индикатора ИВ-21. Но перед рассмотрением проекта часов необходимо ознакомится с программной частью управления ИМС PT6312.
PT6312 содержит всего несколько регистров, которые позволяют сконфигурировать драйвер и управлять его памятью.
Регистр — DISPLAY MODE SETTING COMMANDS
Регистр задает основной режим работы, определяющий кол-во линий сеток и сегментов. Кол-во линий сегментов может быть равно или быть больше чем применяется в индикаторе.
Регистр — DATA SETTING COMMANDS
Регистр задает режим работы драйвера, можно активировать режим работы драйвера VFD, активировать порт светодиодов, включить сканер клавиатуры или активировать пользовательский порт.
Так как состояние линии сегментов зависит от содержимого памяти ИМС PT6312, то в этом регистре можно определить режим заполнения памяти с фиксированным адресом или с автозаполнением адреса.
Регистр — DISPLAY CONTROL COMMANDS
Регистр управляет скважностью работы драйвера, по сути это регулятор яркости.
Регистр — ADDRESS SETTING COMMANDS
Регистр адреса памяти, за ним следует байт данных.
Например мы используем 8-разрядный семисегментный индикатор, нам необходимо вывести символ в первом разряде. К первому разряду соответствует линия сеток 1 (DIG1), которая может управлять 16-и сегментами, но нам нужно только 8. Поэтому отправляем запрос к адресу 0x00:
0B11000000 // регистр ADDRESS SETTING COMMANDS , адрес 00000
и далее байт данных, которые содержат информацию о выводимом на индикатор символе
0b01001111 // на индикаторе будет выводится цифра 3
Повторяем запросы к оставшимся разрядам индикатора: 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E.
*Соответственно сетки индикатора подключены к выводам ИМС PT6312 GR1, GR2, GR3, GR4, GR5, GR6, GR7, GR8, а сегменты к выводам SG1, SG2, SG3, SG4, SG5, SG6, SG7, SG8, которые соответствуют сегментам A,B,C,D,E,F,G и точка (dp).
Для записи регистров я подготовил две функции:
write_byte1_PT6312(byte_data) и write_byte2_PT6312(byte_addr, byte_data) (см. скетч ниже)
Первая функция отправляет байт в регистр, а вторая обращается к памяти, где первый байт регистр адреса памяти, а второй байт данные байта памяти, при этом байт памяти содержит информацию о выводимом символе в следующем формате (при подключении как указано выше *):
7 6 5 4 3 2 1 0 // биты
dp g f e d c b a // сегмент
Как ранее отмечалось интерфейс управления PT6312 интерфейс 3-Wire, с котором используется три сигнала:
- STB — сигнал разрешения работы
- DIN — данные байта, причем данные начинают отсылать с младшего бита
- CLK — тактовый сигнал, причем бит данных записывается в регистр при восходящем фронте тактового импульса
Порядок передачи данных следующий:
После передачи байта следует запрещающий сигнал STB (высокий уровень), но при отправке данных в память
между байтом адреса и данными памяти запрещающий сигнал STB отсутствует .
Сам алгоритм передачи данных очень простой, вот пример функции для записи байта в регистр:
void write_byte1_PT6312(byte data){
digitalWrite(STB,LOW);
for(int i = 0; i <= 7; i++){
digitalWrite(CLK,LOW);
digitalWrite(DIN, (data >> i) & 1);
digitalWrite(CLK,HIGH);
}
digitalWrite(STB,HIGH);delay(1);
}
Далее рассмотрим пример создания часов на индикаторе ИВ-21.
ИВ-21 — индикатор вакуумный люминесцентный многоразрядный для отображения информации в виде цифр, точек и знаков. Оформление — стеклянное. Индикация производится через боковую поверхность баллона. Размер знакоместа 2,4×5 мм. Число разрядов девять. Изображение формируется из светящихся анодов-сегментов. Цвет свечения — зеленый. Масса 13 г.
Часы состоят всего из нескольких компонентов:
- Индикатор ИВ-21
- ИМС PT6312
- Часы реального времени (модуль) DS3231
- Плата разработчика Arduino на базе контроллера Atmega328 или LGT8F328
- Преобразователь напряжения
Схема часов
Основное питание схемы 5 В, оно подается на преобразователь напряжения и на вход 5V платы контроллера.
Преобразователь имеет трансформатор выполненный из ферритового сердечника (гантельный сердечник) на который намотано 3 обмотки проводом диаметром 0,3 мм.
Первая обмотка содержит 20 витков, вторая 10 витков с отводом от середины, третья содержит 110 витков.
Если напряжение накала будет намного меньше 2,5 В, то поменяйте местами выводы обмотки II.
Скетч
#define STB 4 #define DIN 2 #define CLK 3 #define SET 5 #define UP 6 #define DW 7 #include <Wire.h> #include <DS3231.h> // http://rcl-radio.ru/wp-content/uploads/2022/10/DS3231.zip DS3231 clock;RTCDateTime DateTime; int a[8]; long times,times0; int hour,minut,secon,temp,set; bool d,mig; void setup(){ Serial.begin(9600);clock.begin(); // clock.setDateTime(__DATE__, __TIME__); // Устанавливаем время на часах, основываясь на времени компиляции скетча pinMode(STB,OUTPUT); pinMode(DIN,OUTPUT); pinMode(CLK,OUTPUT); pinMode(SET,INPUT_PULLUP); pinMode(UP,INPUT_PULLUP); pinMode(DW,INPUT_PULLUP); delay(100); digitalWrite(STB,HIGH);delay(200); // PWM OUTPUT D9 TIMER 1 TCCR1A = 0;TCCR1B = 0; TCCR1A = (1 << COM1A1)|(1 << WGM11); TCCR1B = (1 << WGM13)|(1 << WGM12)|(1 << CS10); DDRB = 1 << DDB1; // OUTPUT PWM (OCR1A) OCR1A = 16; ICR1 = 40; write_byte1_PT6312(0b01000100);// command 2 write_byte1_PT6312(0b00000100);// command 1 8dig/14seg write_byte1_PT6312(0b10001111);// command 4 display on } void loop(){ DateTime = clock.getDateTime(); hour = DateTime.hour; minut = DateTime.minute; secon = DateTime.second; if(millis()-times>10000){temp=clock.readTemperature()*10;times=millis();} if(digitalRead(SET)==LOW){set++;if(set>3){set=0;} delay(300);} if(digitalRead(UP)==LOW&&set==1){hour++;if(hour>23){hour=23;} clock.setDateTime(2024, 2, 22, hour, minut, secon);delay(100);} if(digitalRead(DW)==LOW&&set==1){hour--;if(hour<0){hour=0;} clock.setDateTime(2024, 2, 22, hour, minut, secon);delay(100);} if(digitalRead(UP)==LOW&&set==2){minut++;if(minut>59){minut=59;} clock.setDateTime(2024, 2, 22, hour, minut, secon);delay(100);} if(digitalRead(DW)==LOW&&set==2){minut--;if(minut<0){minut=0;} clock.setDateTime(2024, 2, 22, hour, minut, secon);delay(100);} if(digitalRead(UP)==LOW&&set==3){secon=0; clock.setDateTime(2024, 2, 22, hour, minut, secon);delay(100);} if(digitalRead(DW)==LOW&&set==3){secon=0; clock.setDateTime(2024, 2, 22, hour, minut, secon);delay(100);} if(millis()-times0<200){mig=1;} if(millis()-times0>200){mig=0;} if(millis()-times0>400){times0=millis();} if(secon<55||set>0){ d=0; if(set!=3){a[0]=secon%10;} if(set!=3){a[1]=secon/10%10;} if(set==3&&mig==0){a[0]=secon%10;} if(set==3&&mig==0){a[1]=secon/10%10;} if(set==3&&mig==1){a[0]=10;} if(set==3&&mig==1){a[1]=10;} a[2]=11; if(set!=2){a[3]=minut%10;} if(set!=2){a[4]=minut/10%10;} if(set==2&&mig==0){a[3]=minut%10;} if(set==2&&mig==0){a[4]=minut/10%10;} if(set==2&&mig==1){a[3]=10;} if(set==2&&mig==1){a[4]=10;} a[5]=11; if(set!=1){a[6]=hour%10;} if(set!=1){a[7]=hour/10%10;} if(set==1&&mig==0){a[6]=hour%10;} if(set==1&&mig==0){a[7]=hour/10%10;} if(set==1&&mig==1){a[6]=10;} if(set==1&&mig==1){a[7]=10;} } if(secon>=55&&set==0){ d=1; a[0]=10; a[1]=13; a[2]=12; a[3]=temp%10; a[4]=temp/10%10; a[5]=temp/100%10; a[6]=10; a[7]=10; } //dp g f e d c b a write_byte2_PT6312(0b11000000,seg(a[0],0));//GR1 write_byte2_PT6312(0b11000010,seg(a[1],0));//GR2 write_byte2_PT6312(0b11000100,seg(a[2],0));//GR3 write_byte2_PT6312(0b11000110,seg(a[3],0));//GR4 write_byte2_PT6312(0b11001000,seg(a[4],d));//GR5 write_byte2_PT6312(0b11001010,seg(a[5],0));//GR6 write_byte2_PT6312(0b11001100,seg(a[6],0));//GR7 write_byte2_PT6312(0b11001110,seg(a[7],0));//GR8 } byte seg(int a, bool dp){ byte segm; switch(a){ case 0: segm=0b00111111+(dp<<7);break; case 1: segm=0b00000110+(dp<<7);break; case 2: segm=0b01011011+(dp<<7);break; case 3: segm=0b01001111+(dp<<7);break; case 4: segm=0b01100110+(dp<<7);break; case 5: segm=0b01101101+(dp<<7);break; case 6: segm=0b01111101+(dp<<7);break; case 7: segm=0b00000111+(dp<<7);break; case 8: segm=0b01111111+(dp<<7);break; case 9: segm=0b01101111+(dp<<7);break; case 10:segm=0b00000000;break;// пусто case 11:segm=0b01000000;break;// - case 12:segm=0b01100011;break;// градус case 13:segm=0b00111001;break;// С } return segm; } void write_byte1_PT6312(byte data){ digitalWrite(STB,LOW); for(int i = 0; i <= 7; i++){ digitalWrite(CLK,LOW); digitalWrite(DIN, (data >> i) & 1); digitalWrite(CLK,HIGH); } digitalWrite(STB,HIGH);delay(1); } void write_byte2_PT6312(byte reg, byte data){ digitalWrite(STB,LOW); for(int i = 0; i <= 7; i++){ digitalWrite(CLK,LOW); digitalWrite(DIN, (reg >> i) & 1); digitalWrite(CLK,HIGH); } delay(1); for(int i = 0; i <= 7; i++){ digitalWrite(CLK,LOW); digitalWrite(DIN, (data >> i) & 1); digitalWrite(CLK,HIGH); } digitalWrite(STB,HIGH);delay(1); }
После сборки часов необходимо настроить работу повышающего преобразователя, делается это при помощи регистра OCR1A.
Установите значение регистра равным 10 и замерьте анодное напряжение, оно должно находиться в пределах от -24 до -36 В. При необходимости измените значение регистра. В моем случает в OCR1A установлено значение 16 (20 = ШИМ 50%), анодное напряжение -35 В (под нагрузкой).
OCR1A = 10;
Часы содержат кнопки коррекции времени, так же в течении 5 секунд каждую минуту на индикатор выводится температура с датчика который находится в часах реального времени.
Форум — http://forum.rcl-radio.ru/viewtopic.php?pid=9523#p9523
Доработка
- Программная регулировка яркости, значение яркости сохраняется в энергонезависимой памяти
Форум — http://forum.rcl-radio.ru/viewtopic.php?pid=9524#p9524