Увидел как-то на AliExpress интересный модуль на микросхеме TM1638. Выглядел он вот так:
Даташит (невероятно китайский) на микросхему рассказал, что это контроллер семисегментного дисплея (максимум 10 знакомест) и клавиутуры (максимум 8х3). Невероятно заинтересовавшись заказал данный девайс, благо стоимость невелика, в районе 100р. В живую модуль выглядит вот так:
Запаян, конечно, кривовато, но ничего, главное, чтобы работал. Для подключения на плате имеется пять контактов: VDD, GND, STB, CLK, DIO. Заглядываем в даташит и выясняем следующие параметры:
- напряжение питания: 5V±10%
- интерфейс: полудуплексный SPI.
- назначение выводов SPI: STB - chip select, CLK - clock, DIO - data in/out.
Гугл подсказал и схему модуля:
Теперь можно переходить к самому интересному - запуску. Подключать модуль буду к плате STM32 VL Discovery с МК STM32F103. Она была у меня под рукой, плюс SPI имеет возможность работы в полудуплексном режиме. Все функции работы с SPI вынес отдельно, так что библиотеку можно будет использовать с любым другим МК, останется лишь подставить свои функции для SPI.
Управляется микросхема довольно легко. Есть всего три типа команд:
- команды управления 0х8Х
- команды данных 0х4Х
- команды адреса 0хСХ
Теперь подробнее.
Управлять тут можно целыми двумя параметрами: яркостью и включением отображения. Для этого используется младшая половина байта. Первые три отведены на яркость и четвертый на управление включением. Соответственно, у яркости 8 градаций. Для включения микросхемы необходимо отправить любую из следующих команд:
0x88 | Отображение ВКЛ, ширина ШИМ яркости 1/16 |
0x89 | Отображение ВКЛ, ширина ШИМ яркости 2/16 |
0x8A | Отображение ВКЛ, ширина ШИМ яркости 4/16 |
0x8B | Отображение ВКЛ, ширина ШИМ яркости 10/16 |
0x8C | Отображение ВКЛ, ширина ШИМ яркости 11/16 |
0x8D | Отображение ВКЛ, ширина ШИМ яркости 12/16 |
0x8E | Отображение ВКЛ, ширина ШИМ яркости 13/16 |
0x8F | Отображение ВКЛ, ширина ШИМ яркости 14/16 |
Для отключения достаточно послать любую из вышеперечисленных команд с обнуленным 3 битом.
После включения можно отправлять и читать данные в/из регистры микросхемы. Для выбора необходимого действия с регистрами служит команда 0x4X; Как и в предыдущей команде, за все отвечает младшая половина байта, а именно 1 и 2 биты.
- 1-й бит: 1 - чтение/0 - запись
- 2-й бит: 1 - фиксированный адрес/0 - автоинкремент адреса
0x40 | Запись, автоинкремент адреса |
0x44 | Запись, фиксированный адрес |
0x42 | Чтение |
При чтении указание адреса не требуется, вычитываются все 4 регистра данных, которые составляют матрицу, содержащую данные опроса клавиатуры. Каждый бит соответствует одной кнопке. А вот при записи необходимо указывать адрес. Всего регистров отображения 16 штук. Каждый соответствует одному знакоместу. На данной плате нечетные адреса соответствуют знакоместам, а четные светодиодам (запись в эти регистры любого числа, отличного от нуля, включает светодиод). Адресация начинается с 0хС0. При автоинкременте достаточно указать начальный адрес посылки, а дальше просто отсылать весь пакет. А при фиксированном адресе, команду адреса необходимо слать перед записью каждого байта данных.
С командами разобрались, можно переходить к подключению. Использоваться будет аппаратный SPI STM32 в режиме полудуплекс. Думаю, не помешает описать этот момент чуть подробнее, т.к. именно про этот режим информации в интернете маловато. Настройка выводов абсолютно стандартная для SPI:
// SPI INIT //вывод управления SS: выход двухтактный, общего назначения,50MHz / GPIOB->CRH |= GPIO_CRH_MODE12; // GPIOB->CRH &= ~GPIO_CRH_CNF12; // GPIOB->BSRR = GPIO_BSRR_BS12; // //вывод SCK: выход двухтактный, альтернативная функция, 50MHz GPIOB->CRH |= GPIO_CRH_MODE13; // GPIOB->CRH &= ~GPIO_CRH_CNF13; // GPIOB->CRH |= GPIO_CRH_CNF13_1; // //вывод MOSI: выход двухтактный, альтернативная функция, 50MHz GPIOB->CRH |= GPIO_CRH_MODE15; // GPIOB->CRH &= ~GPIO_CRH_CNF15; // GPIOB->CRH |= GPIO_CRH_CNF15_1; //
А вот сам SPI требуется настроить немного по другому. Для переключения в полудуплексный режим служит бит:
SPI2->CR1 |= SPI_CR1_BIDIMODE; //полудуплексный режим
Так же следует обратить внимание на то, что данные передаются младшим битов вперед. Пока все просто, самое интересное начинается дальше. Т.к. режим полудуплексный, то линия MOSI служит и для передачи и для приема. Переключать режим необходимо вручную, снятием/установкой бита SPI_CR1_BIDIOE Установка бита включает режим передачи, а сброс - режим приема.
Соответственно для передачи устанавливаем SPI_CR1_BIDIOE и спокойно передаем, как в случае с обычным режимом.
void SPI_Send(uint8_t data){ SPI2->CR1 |= SPI_CR1_BIDIOE; SPI2->DR = data; while (!(SPI2->SR & SPI_SR_TXE)); while ((SPI2->SR & SPI_SR_BSY)); }
А для приема алгоритм более хитрый:
- Переключаемся в режим передачи, отправляем запрос (в нашем случае это 0x42).
- Переключаемся в режим приема
- Прочесть содержимое регистра SPIх->DR
- Не переключаясь в режим передачи записать любой число в SPIх->DR
- Повторить п.3 и п.4 необходимое количество раз
Выглядит это примерно так:
SPI_Read(uint8_t send, uint8_t *data_mas, uint8_t count){ uint8_t i = 1; SPI2->CR1 |= SPI_CR1_BIDIOE; // переключение на отправку SPI2->DR = send; // отправка данных while (!(SPI2->SR & SPI_SR_TXE)); // ожидание окончания отправки while ((SPI2->SR & SPI_SR_BSY)); SPI2->CR1 &= ~SPI_CR1_BIDIOE; // переключение в режим приема. При этом будет отправлено 8 тактовых импульсов while (!(SPI2->SR & SPI_SR_RXNE)); while ((SPI2->SR & SPI_SR_BSY)); data_mas[0] = SPI2->DR; // забираем полученные данные из регистра SPI while(count-- > 1){ // повторяем необходимое количество раз SPI2->DR = 0xFF; // запись в регистр любого значения в режиме приема инициализирует отправку тактирования while (!(SPI2->SR & SPI_SR_RXNE)); while ((SPI2->SR & SPI_SR_BSY)); data_mas[i++] = SPI2->DR; } SPI2->CR1 |= SPI_CR1_BIDIOE; }
Настройка окончена, подключаем модуль к МК (схему не привожу, думаю, все и так понятно):
Подаем питание, заливаем прошивку и наслаждаемся результатом.
Сразу выяснилась одна неприятная особенность - довольно противный писк. Оказалось, что пищат индикаторы из-за того, что частота обновления находится в слышимом диапазоне. Видимо, сказалось и качество китайских индикаторов, т.к. по сути пищать там нечему, однако факт налицо.
Проверим работу кнопок:
Вот тут разработчика поджидает один не очень приятный сюрприз. Все дело в том, что никакого выхода прерывания по нажатию кнопки у микросхемы нет. Более того, нажатия кнопок не сохраняются в регистрах после отпускания. Следовательно для того, чтобы понять, было нажатие или нет, необходимо постоянно вычитывать регистры клавиатуры. Лично на мой взгляд это не очень удобно, т.к. без толку загружает МК.
В остальном же микросхема работает отлично. Ничего не греется. Максимальный ток, отдаваемый на каждый сегмент индикатора - 20мА, на общий вывод индикатора - 200мА.
Исходники прошивки можно скачать в конце статьи. Библиотека для TM1638 обильно прокомментирована и трудностей возникнуть не должно. Так же выкладываю программу, которую писал для себя. В ней можно быстро получить коды символов семисегментного индикатора. Функционал приложенной прошивки демонстрирует небольшое видео:
Прикрепленные файлы:
- TM1638.rar (100 Кб)
- 7SEG Code Generator.rar (1083 Кб)
Комментарии (15) | Я собрал (0) | Подписаться
Для добавления Вашей сборки необходима регистрация
И станет понятно, что не так делает автор данной статьи. А именно, ожидает опустошения буфера передатчика на передаче каждого байта (то есть получается не использует буфер и прерывает передачу данных до загрузки следующего байта), вместо того чтобы заполнить буфер данными и уже тогда ждать его опустошения.
[Автор]
Вот отчего ваша схема: каскадируемый двухцветный модуль https://www.aliexpress.com/af/tm1638-color.html
Хочу попробовать делать на ней модуль управления ГРИ SEG1-SEG10 использовать как выходы десятичного дешифратора (через ключи естественно)
[Автор]
https://2150692.ru/files/tm1638_v1.3_en.pdf
Попробую сделать подобное "но с перламутровыми пуговицами" (с) то есть на ГРИ
[Автор]
Можно схему эл. подключений увидеть между контроллером и платой с индикатором?
[Автор]