ESP32. Подключение индикатора TM1637 в Espressif-IDE


В статье опишем работу с популярным индикатором, построенным на базе микросхемы TM1637 и семисегментного 4 - 6 разрядного индикатора. Обычно всю сборку называют просто TM1637.
Сразу обозначим, что статья о работе с ESP32, в Espressif-IDF, не с Arduino.
В статье опишем общий принцип работы. Сразу замечание, текст будет казаться только отображения на индикаторе. Модуль может ещё работать с клавиатурой, но нам в работе это не понадобилось и эта тема освещена не будет. 

Принцип работы

Обмен данными с модулем происходит по двум шинам CLK и DIO. Когда не происходит передача, на обеих шинах устанавливается высокий уровень сигнала.

Маркером старта передачи является переход от высокого (1) к низкому (0) уровню на шине DIO при высоком уровне (1) на шине CLK.
Маркером окончания передачи является переход от 0 к 1 на шине DIO, при 1 на шине CLK.
Между маркерами может быть передано от одного до нескольких байтов.

Передача данных происходи байтами. Для передачи одного байта требуется 9 импульсов синхронизации CLK. Биты передаются начиная с младшего. 
! Изменение состояния шины DIO должны происходить только при низком уровне на шине CLK !
Перед восходящим фронтом на шине CLK на шине DIO уже должен быть установлен уровень, соответствующий передаваемому биту.

После окончания передачи байта модуль выставляет сигнал подтверждения ACK - низкий уровень на шине DIO по заднему (спадающему) фронту восьмого импульса CLK и удерживается в течении одного такта синхронизации - до заднего фронта девятого импульса CLK.
Если после этого не будет сформирован маркер окончания передачи, то считается, что со следующим импульсом CLK пошла передача следующего байта. 
Во время передачи сигнала АСК неплохо переводить соответствующие выводы микроконтроллера на прием, но при наличии только одного индикатора, достаточно держать на выводах 0.

На рисунке выше изображено, как происходит передача байта на индикатор. 

Программная реализация

1. Для того, чтобы индикатор начал работать сначала необходимо отправить команду инициализации.
В даташите (файл приложим к статье) об этом сказано весьма непонятно. В результате экспериментов (не исключено, что это именно с нашим экземпляром индикатора, прибудут другие протестируем) выяснено, что для инициализации необходимо отправить команду инициализации.

0b10001100
(для тех кто не знает 0b - означает, что далее идет число в двоичном формате, передавать можно в любом, но так понятнее).

Bit_2 (третий справа, отсчет от 0 бита) в команде определяет режим: 1 - c фиксированным адресом знакоместа (необходимо передавать адрес для каждого разряда индикатора), 0 - с автоинкрементом адреса, об этом ещё ниже.

2. Затем команду конфигурации. 
Структура команды конфигурации следующая (слева направо):
10 - признак, что идет команда конфигурации:
Bit_7 - всегда 1
Bit_6 - всегда 0
Bit_5 - всегда 0
Bit_4 - всегда 0
Bit_3 - 1- включить индикатор, 0 - выключить индикатор
Биты с 0 по 2- градация яркости. 000 минимальная яркость, 111 - максимальная яркость
Bit_2 - 1
Bit_1 - 1
Bit_0 - 1

Пример:

0b10001100 - индикатор включен на средней яркости

Отправляя в дальнейшем команду конфигурации можно управлять включением, отключением индикатора и яркостью. 

3. Передать в устройство адрес знакоместа и данные, которые мы желаем на нем увидеть. 
Выглядеть это будет так (при передаче с фиксированным адресом знакоместа).

4. Адрес задается байтом, где первые (справа) байты задают место на индикаторе, справа налево, начиная с 0:
0b11000000 - первый справа
0b11000001 - второй
0b11000010 - третий
0b11000011 - четвертый

4. Чтобы увидеть на знакоместе необходимый символ необходимо использовать следующие картинку и таблицу.
Обозначения сегментов
DP - точка или двоеточие.

Кодирование символов
bit_7
bit_6
bit_5
bit_4
bit_3
bit_2
bit_1
bit_0
DP
G
F
E
D
C
B
A

 Например код для отображения цифры 3: 0b01001111

Программная реализация с помощью Espressif-IDE

#include <driver/gpio.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

#define TM1637_INIT 0b10001100
#define TM1637_CONFIG 0b10001100

#define TM1637_adres_0 0b11000000
#define TM1637_adres_1 0b11000001
#define TM1637_adres_2 0b11000010
#define TM1637_adres_3 0b11000011

void tm1637_start(int clk_gpio, int dio_gpio){
//Маркер начала посылки
gpio_set_level(clk_gpio, 1);
gpio_set_level(dio_gpio, 0);
}

void tm1637_finish(int clk_gpio, int dio_gpio){
//Маркер окончания посылки
gpio_set_level(clk_gpio, 1);
gpio_set_level(dio_gpio, 1);
}

//Отправка команды
void tm1637_send_command(int clk_gpio, int dio_gpio, int command){
tm1637_start(clk_gpio, dio_gpio);
//Формируем 8 импульсов и передаем значения бит
for(int i = 0; i < 8; i++){
gpio_set_level(clk_gpio, 0);

gpio_set_level(dio_gpio, command >> i & 1); //Выбираем нужный бит и устанавливаем

gpio_set_level(clk_gpio, 1);
}
//ACK
gpio_set_level(clk_gpio, 0);
gpio_set_level(dio_gpio, 0);
//Девятый импульс
gpio_set_level(clk_gpio, 1);
gpio_set_level(clk_gpio, 0);

tm1637_finish(clk_gpio, dio_gpio);
}

//Первоначальная инициализация
void tm1637_init(int clk_gpio, int dio_gpio){
esp_rom_gpio_pad_select_gpio(clk_gpio); // режим ввода-вывода

gpio_set_direction(clk_gpio, GPIO_MODE_OUTPUT); // активный выход

esp_rom_gpio_pad_select_gpio(dio_gpio); // режим ввода-вывода

gpio_set_direction(dio_gpio, GPIO_MODE_OUTPUT); // активный выход

tm1637_start(clk_gpio, dio_gpio);

tm1637_send_command(clk_gpio, dio_gpio, TM1637_INIT);

tm1637_send_command(clk_gpio, dio_gpio, TM1637_CONFIG);

tm1637_finish(clk_gpio, dio_gpio);
}

//Получение адреса знакоместа
int tm1637_address_get(int num_digit){
int res = 0b00000000;
switch (num_digit) {
case 0: res = 0b11000000; break;
case 1: res = 0b11000001; break;
case 2: res = 0b11000010; break;
case 3: res = 0b11000011; break;
case 4: res = 0b11000100; break;
case 5: res = 0b11000101; break;
}
return (res);
}

//Получение кода символа, для удобства
int tm1637_get_code_symbol(char x){
int res = 0b00000000;
switch (x) {
case 0: res = 0b00111111; break;
case 1: res = 0b00000110; break;
case 2: res = 0b01011011; break;
case 3: res = 0b01001111; break;
case 4: res = 0b01100110; break;
case 5: res = 0b01101101; break;
case 6: res = 0b01111101; break;
case 7: res = 0b00000111; break;
case 8: res = 0b01111111; break;
case 9: res = 0b01101111; break;
case '0': res = 0b00111111; break;
case '1': res = 0b00000110; break;
case '2': res = 0b01011011; break;
case '3': res = 0b01001111; break;
case '4': res = 0b01100110; break;
case '5': res = 0b01101101; break;
case '6': res = 0b01111101; break;
case '7': res = 0b00000111; break;
case '8': res = 0b01111111; break;
case '9': res = 0b01101111; break;
case 'B': res = 0b01111111; break;
case 'H': res = 0b01110110; break;
case 'L': res = 0b00111000; break;
case '=': res = 0b01001000; break;
case 'E': res = 0b01111001; break;
case 'r': res = 0b01010000; break;
case 'N': res = 0b00000000; break; // Погасить разряд
}
return (res);
}

//Отправка короткой команды без маркеров начала и окончания передачи
void tm1637_send_command_short(int clk_gpio, int dio_gpio, int command){
//Формируем 8 импульсов и передаем значения бит
for(int i = 0; i < 8; i++){
gpio_set_level(clk_gpio, 0);

gpio_set_level(dio_gpio, command >> i & 1); //Выбираем нужный бит и устанавливаем

gpio_set_level(clk_gpio, 1);
}
//ACK
gpio_set_level(clk_gpio, 0);
gpio_set_level(dio_gpio, 0);
//Девятый импульс
gpio_set_level(clk_gpio, 1);
gpio_set_level(clk_gpio, 0);
}

//Отправка команды на установку одиночного символа
void tm1637_indicator_set_one(int clk_gpio, int dio_gpio, int num_digit, char symbol){
tm1637_start(clk_gpio, dio_gpio);

tm1637_send_command_short(clk_gpio, dio_gpio, tm1637_address_get(num_digit));

tm1637_send_command_short(clk_gpio, dio_gpio, tm1637_get_code_symbol(symbol));

tm1637_finish(clk_gpio, dio_gpio);
}

//Отправка команды установки всех символов
void tm1637_indicator_set_all(int clk_gpio, int dio_gpio, char * ind_value){
for (int i = 0; i < 4; i++){
tm1637_indicator_set_one(clk_gpio, dio_gpio, i, ind_value[i]);
}
}

void app_main(void){
//Определение ног микропроцессора для работы с дисплеем
  #define TM1637_CLK GPIO_NUM_21
  #define TM1637_DIO GPIO_NUM_23

  //Инициализация
  tm1637_init(TM1637_CLK, TM1637_DIO);

 //Отправка символов
  tm1637_indicator_set_all(TM1637_CLK, TM1637_DIO, "1234");
}
 


Комментарии 1

  1. Mike Francis от 28 марта 2024 13:54
    Hi I have just took an in depth look on your systop.ru for the current search visibility and saw that your website could use a push. We will enhance your ranks organically and safely, using only state of the art AI and whitehat methods, while providing monthly reports and outstanding support. More info: https://www.digital-x-press.com/unbeatable-seo/ Regards Mike Francis Digital X SEO Experts
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.