Микросхема TM1640 фирмы Titan Micro Electronics представляет собой драйвер управления 8-сегментными светодиодными индикаторами в количестве до 16 штук (Рис.1). Связь с этой микросхемой осуществляется по двухпроводной шине данных похожей по протоколу на I2C, но не совместимой с ней.
Рис.1 Микросхема TM1640
Назначение у выводов микросхемы следующее: SEG1-SEG8 — выбор сегментов индикатора (высокий уровень на выводе зажигает сегмент, низкий — гасит), GRID1-16 — выбор индикатора (низкий уровень на выводе выбирает индикатор, высокий — отменяет выбор). VDD — питание 5+-0,5В и VSS — земля. DIN и SCLK — соответственно линия данных и линия синхронизации. Эти выводы требуется подтягивать к питанию через резисторы 10 кОм (Рис.2).
Рис.2 Принцип подключения сегментных индикаторов к TM1640
Рассмотрим протокол этой двухпроводной шины. Когда сообщения не передаются, на обоих проводах должен быть высокий уровень. Любое сообщение начинается с состояния Start (при высоком уровне на SCLK осуществляется перепад на DIN с высокого уровня на низкий), а заканчивается состоянием Stop (при высоком уровне на SCLK осуществляется перепад на DIN с низкого уровня на высокий). Каждый бит передаваемый по линии DIN сопровождается импульсом на тактовой линии SCLK. На рис.3 показана структура отправки сообщения — команды. Они имеют длину 8 бит и передаются от младшего бита к старшему. В сообщениях не указывается адрес устройства которому они предназначены. Поэтому, по двум проводам возможно подключить к микроконтроллеру один единственный TM1640.
Рис.3 Структура передачи сообщения-команды.
Микросхема воспринимает команды трех типов:
1-й тип. Указание способа приема данных. Возможен прием данных с автоматическим инкрементом адреса индикатора (этот режим установлен по умолчанию, наиболее оптимальный), с фиксированным адресом, а также нормальный и тестовый режимы.
2-й тип. Установка адреса индикатора, в который будет производиться запись данных. В этом же сообщении посылаются данные на сегментные индикаторы. Длина такой команды составляет не менее 16 бит и кратна 8 битам (Рис.4).
Рис.4 Пример отправки сообщений вTM1640: Command1 — выбор способа передачи данных, Command2 — выбор адреса индикатора, с которого будет производится запись, data1-dataN — пакет данных на индикаторы, Command3 — установка яркости индикаторного дисплея.
3-й тип. Установка яркости индикаторного дисплея. Микросхема управляет индикаторами в динамическом режиме. Коэффициент заполнения ШИМ может быть выбран от 1/16 до 14/16 по таблице из даташита. Также индикаторы можно просто погасить.
Рассмотрим простейшую программную реализацию интерфейса связи с TM1640, которая будет подходить для всех микроконтроллеров Atmel серии Atmega:
Сделаем определения для задания выводов, используемых как SCLK и DIN (здесь вывод PA6 определен как SCLK, а PA7 как DIN):
//Задание выводов SCLK и DIN и определение их на выход #define SCLK_DIN_to_output DDRA|=(1<<6)|(1<<7) #define SCLK_LOW PORTA&=~(1<<6)//Низкий уровень на SCLK #define SCLK_HIGH PORTA|=(1<<6)//Высокий уровень на SCLK #define DIN_LOW PORTA&=~(1<<7)//Низкий уровень на DIN #define DIN_HIGH PORTA|=(1<<7)//Высокий уровень на DIN
В тексте основной программы обязательно инициализируем выбранные выводы для работы с шиной и установим на них высокий уровень:
//Определение на выход выводов SCLK и DIN SCLK_DIN_to_output //Подтягивание выводов SCLK и DIN SCLK_HIGH; DIN_HIGH;
Сформируем состояние Start: осуществим перепад уровня на DIN с высокого на низкий, а следом такой же перепад на SCLK. Временную задержку между командами можно не ставить даже для максимальной частоты тактирования микроконтроллера в 16 МГц. Для корректной работы этой установки на обоих линиях должен быть установлен высокий уровень.
//Установка состояния старт voidTM1640_Message_Start(void) { DIN_LOW; SCLK_LOW; }
Теперь состояние Stop: в даташите это состояние называется «End», но привычней использовать более правильный антоним. Для корректной работы этой установки на обоих линиях должен быть низкий уровень. Осуществим перепад уровня на DIN с низкого на высокий, затем такой же перепад осуществим на SCLK)
//Установка состояния стоп voidTM1640_Message_Stop(void) { SCLK_HIGH; DIN_HIGH; }
Рассмотрим отправку байта, которая по требованию протокола должна осуществляться с младшего бита: Устанавливаем требуемое значение бита данных и формируем синхроимпульс. Даже для частоты тактирования микроконтроллера в 16МГц, без использования функции задержки, длительность синхроимпульса составит более 125нс (измерено логическим анализатором Saleae Logic). Это превышает требуемое минимальное время установки бита данных на 25нс. Не забываем сбросить DIN в ноль.
//Отправка байта voidTM1640_Message_Sendbyte(unsigned char byte) { //Побитная запись с младшего бита for(signedchari=0;i<8;i++) { if(byte&(1<<i))DIN_HIGH;//Записать бит 1 else DIN_LOW;//Записать бит 0 SCLK_HIGH;//Устанавливаем синхроимпульс SCLK_LOW;//Снимаем синхроимпульс DIN_LOW;//Сбрасываем DIN в "0" } }
В этой функции, в соответствии с таблицей 9 даташита производится отправка адреса индикатора от 0 до 15.
//Установка позиции, куда будет производится запись voidTM1640_SetPos(char i) { TM1640_Message_Sendbyte(0b11000000+i); }
Чтобы с помощью приведенной функции на индикаторах отображались нужные символы, необходимо задать следующий массив и сделать определение для символов 16-битного кода.
char str[12];//Массив для вывода результата на дисплей //Массив цифр 0 1 2 3 4 5 6 7 8 9 A char led[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, // B C D E F 0x7C, 0x39, 0x5E, 0x79, 0x71}; //Определение символов 16-ричной системы счисления #define A 10 #define B 11 #define C 12 #define D 13 #define E 14 #define F 15
Функция установки яркости сделана в соответствии с таблицей 10 даташита. В ней производится отправка команды с требуемой яркостью индикаторов от 0 (погасить индикаторы) до 8 (максимальная яркость).
//Установка яркости светодиодов voidTM1640_LED_Bright(chari) { TM1640_Message_Start(); if(i!=0)TM1640_Message_Sendbyte(0b10001000+i-1); elseTM1640_Message_Sendbyte(0b10000000); TM1640_Message_Stop(); }
Иногда удобно полностью затереть все данные, отправленные на индикаторный дисплей. Для этого используем такую функцию:
//Полная очистка светодиодного индикатора void TM1640_clear(void) { TM1640_Message_Start(); TM1640_SetPos(0); for(char j=0;j<16;j++)TM1640_Message_Sendbyte(0x00); TM1640_Message_Stop(); }
Здесь приведен пример поочередной отправки символов 16-разрядного кода с последующим постепенным гашением индикаторов.
//Отправка символов 16-разрядного кода с 0 до F TM1640_Message_Start(); TM1640_SetPos(0); for(j=0;j<16;j++) { TM1640_Message_Sendbyte(led[j]);// _delay_ms(200); } TM1640_Message_Stop(); //Постепенное гашение индикаторного дисплея for(j=0;j<9;j++) { TM1640_LED_Bright(9-j); _delay_ms(200); }
Ниже представлена фотография макета на основе TM1640, собранного по схеме рис.2 (но с использованием всех выводов GRID), под управлением микроконтроллера Atmega32. Видео работы схемы, исходный код и «даташит» на микросхему имеются в приложении к статье.