Программная реализация интерфейса управления tm1640 на atmega

Программная реализация интерфейса управления TM1640 на ATmega

Микросхема 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):

В тексте основной программы обязательно инициализируем выбранные выводы для работы с шиной и установим на них высокий уровень:

Сформируем состояние Start: осуществим перепад уровня на DIN с высокого на низкий, а следом такой же перепад на SCLK. Временную задержку между командами можно не ставить даже для максимальной частоты тактирования микроконтроллера в 16 МГц. Для корректной работы этой установки на обоих линиях должен быть установлен высокий уровень.

Теперь состояние Stop: в даташите это состояние называется «End», но привычней использовать более правильный антоним. Для корректной работы этой установки на обоих линиях должен быть низкий уровень. Осуществим перепад уровня на DIN с низкого на высокий, затем такой же перепад осуществим на SCLK)

Рассмотрим отправку байта, которая по требованию протокола должна осуществляться с младшего бита: Устанавливаем требуемое значение бита данных и формируем синхроимпульс. Даже для частоты тактирования микроконтроллера в 16МГц, без использования функции задержки, длительность синхроимпульса составит более 125нс (измерено логическим анализатором Saleae Logic). Это превышает требуемое минимальное время установки бита данных на 25нс. Не забываем сбросить DIN в ноль.

В этой функции, в соответствии с таблицей 9 даташита производится отправка адреса индикатора от 0 до 15.

Чтобы с помощью приведенной функции на индикаторах отображались нужные символы, необходимо задать следующий массив и сделать определение для символов 16-битного кода.

Функция установки яркости сделана в соответствии с таблицей 10 даташита. В ней производится отправка команды с требуемой яркостью индикаторов от 0 (погасить индикаторы) до 8 (максимальная яркость).

Иногда удобно полностью затереть все данные, отправленные на индикаторный дисплей. Для этого используем такую функцию:

Здесь приведен пример поочередной отправки символов 16-разрядного кода с последующим постепенным гашением индикаторов.

Ниже представлена фотография макета на основе TM1640, собранного по схеме рис.2 (но с использованием всех выводов GRID), под управлением микроконтроллера Atmega32. Видео работы схемы, исходный код и «даташит» на микросхему имеются в приложении к статье.

Взаимодействие двух микроконтроллеров AVR ATmega8 через UART

В этой статье мы рассмотрим процесс взаимодействия двух микроконтроллеров ATmega8 (семейство AVR) через последовательный порт. Взаимодействие будет осуществляться с помощью универсальных асинхронных приемопередатчиков (UART — Universal Asynchronous Receiver Transmitter), имеющихся в микроконтроллерах. Подобное взаимодействие часто бывает востребовано в различных системах.

Необходимые компоненты

Аппаратное обеспечение

  1. Микроконтроллер ATmega8 (2 шт.) (купить на AliExpress).
  2. Программатор AVR-ISP (купить на AliExpress), USBASP (купить на AliExpress) или другой подобный.
  3. Конденсатор 1000 мкФ (соединенный по питанию) (купить на AliExpress).
  4. Конденсатор 100 нФ (соединенный по питанию) (купить на AliExpress).
  5. Светодиод (купить на AliExpress).
  6. Кнопка.
  7. Резистор 1 кОм (купить на AliExpress).
  8. Источник питания с напряжением 5 Вольт.

Программное обеспечение

  1. Atmel Studio версии 6.1 (или выше).
  2. Progisp или flash magic (необязательно).

Работа схемы

Схема устройства приведена на следующем рисунке.

В данной схеме мы будем рассматривать взаимодействие двух ATmega8 через последовательный порт с интерфейсом RS232 – это один из самых простых видов взаимодействий между микроконтроллерами AVR. Для этой цели у микроконтроллеров на схеме соединены контакты TXD и RXD их последовательных портов.

Прежде чем рассматривать работу схемы остановимся на принципах работы последовательного порта в микроконтроллерах AVR. Для осуществления успешного взаимодействия между ними необходимо установить следующие параметры последовательного порта:

  1. Восемь бит данных.
  2. Два стоповых бита.
  3. Нет бита проверки на четность.
  4. Бодовая скорость 2400 бод/с.
  5. Асинхронный режим связи (часы обоих микроконтроллеров не синхронизированы).

Таким образом, мы должны установить соответствующие значения регистров последовательного порта для двух микроконтроллеров ATmega8 индивидуально, когда один из микроконтроллеров работает как передатчик, а другой как приемник. Эти значения следующие:

  1. Контакт TXD первого микроконтроллера должен быть задействован в качестве передатчика, а контакт RXD второго микроконтроллера должен быть задействован в качестве приемника.
  2. Поскольку связь последовательная, то мы должны знать когда мы примем весь байт целиком. Поэтому мы не должны останавливать прием данных до тех пока не примем весь байт. Остановка приема данных после приема всего байта производится с помощью соответствующего прерывания.
  3. Данные передаются и принимаются в 8 битном режиме. Поэтому два символа должны пересылаться единовременно.
  4. Битов проверки на четность нет, в конце данных передается один стоповый бит.

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

DARK GREY (темно-серый, UDRE): (сторона передатчика) Этот бит не устанавливается в самом начале, но он используется во время работы последовательного порта чтобы проверить готов ли передатчик к передаче или нет. Более подробно использование этого бита рассмотрено в программе, приведенной ниже.

LIGHT GREY (светло-серый, RXC): (сторона приемника) Этот бит не устанавливается в самом начале, но он используется во время работы последовательного порта чтобы проверить готов ли приемник к приему данных или нет. Более подробно использование этого бита рассмотрено в программе.

VOILET (фиолетовый, TXEN): (сторона передатчика) Этот бит устанавливается чтобы разрешить передачу данных по последовательному порту на стороне передатчика.

RED (красный, RXEN): (сторона приемника) Устанавливается чтобы разрешить прием данных на контакте RXD микроконтроллера.

BROWN (коричневый, RXCIE): Этот бит должен быть установлен для того, чтобы после успешного приема данных генерировалось прерывание. При помощи установки этого бита мы будем знать что очередные 8 бит приняты правильно.

PINK (розовый, URSEL): Этот бит должен быть установлен перед тем как устанавливать другие биты в регистре UCSRC. Но после того как мы установим все необходимые биты UCSRC, бит URSEL должен быть сброшен.

YELLOW(желтый, UCSZ0,UCSZ1,UCSZ2): (сторона приемника и сторона передатчика). Эти три бита используются для выбора числа бит, которые мы будем передавать/принимать за одну попытку (передачи).

Как следует из приведенной таблицы для задействования 8 битного режима связи биты UCSZ0 и UCSZ1 необходимо установить в 1, а бит UCSZ2 – в 0. Мы должны сделать этот как на приемной, так и на передающей стороне.

ORANGE (оранжевый, UMSEL): (сторона приемника и сторона передатчика). Используется для выбора режима связи: синхронный или асинхронный.

Поскольку оба микроконтроллера используют свои собственные внутренние часы (таймеры) и никоим образом не синхронизируют их между собой, то мы должны в соответствии с приведенной таблицей установить бит UMSEL в 0 на обоих микроконтроллерах.

GREEN (зеленый, UPM1, UPM0): (сторона приемника и сторона передатчика). Эти два бита устанавливаются в зависимости от того каким образом мы хотим использовать проверку на четность.

Микроконтроллеры ATMEGA программируются таким образом, чтобы не использовать проверку на четность поскольку длительность передачи данных (8 бит) очень мала, поэтому можно предположить что и вероятность искажения данных (вероятность ошибки) будет очень мала. Поэтому мы должны в соответствии с приведенной таблицей установить биты UPM1 и UPM0 в 0 либо не трогать их вообще, потому что по умолчанию при инициализации микроконтроллера они сброшены.

BLUE (синий, USBS): (сторона приемника и сторона передатчика) Этот бит используется для выбора числа стоповых бит в процессе передачи.

Поскольку мы выбрали асинхронный режим связи, то для более точной (надежной) передачи и приема данных необходимо использовать 2 стоповых бита. Поэтому устанавливаем бит USBS в 1 на обоих микроконтроллерах.

Бодовая скорость последовательного порта устанавливается с помощью соответствующего значения в регистре UBRRH. Это значение необходимо определять в зависимости от требуемой бодовой скорости и тактовой частоты микроконтроллера.

Для выбранных нами параметров (скорость 2400 бод/с, тактовая частота 1 МГц) в регистре UBRR необходимо установить значение 25.

На представленной схеме на передающем конце мы видим кнопку. При нажатии этой кнопки 8 бит данных передаются передатчиком и принимаются приемником. Об успешном завершении приема данных свидетельствует включение светодиода на приемной стороне.

Исходный код программы на языке C (Си) с пояснениями

Программа для рассматриваемой схемы представлена следующим фрагментом кода на языке C (Си). Комментарии к коду программу поясняют принцип работы отдельных команд.

Программная реализация интерфейса управления tm1640 на atmega


SPI? Легко!

В одном из предыдущих постов, я рассказывал про подключение термопары к Arduino. Теперь настало время рассмореть подключение к AVR микроконтроллерам на чистом Си, благо, как выяснилось, это совсем не сложно.

Читайте также  Компания laird выпустила новый модуль беспроводного зарядного устройства

Напомню, что термопара подключается через адаптер MAX6675, который в свою очередь подключается к микроконтроллеру через SPI интерфейс.

После I2C, SPI интерфейс скорее всего покажется очень простым. Если расмотреть аппаратную реализацию SPI, то там есть регистр данных SPDR, записью или чтением с которого и осуществляется вся работа c SPI.

Программная реализация, как выяснилось, не намного сложнее, но сначала о том, что такое SPI. Фирменный аппнот к SPI можо найти на сайте Atmel: AVR151: Setup And Use of The SPI

рассмотрим схему подключения взятую оттуда:

  1. К интерфейсу возможно подключение нескольких устройств, но единовременно возможна работа только с одним из них.
  2. Используется концепция master-slave(дирижер оркестр). Мастер генерирует синхроимпульсы и переключает устройства.
  3. В минимальном варианте, имеется две управляющие линии: SCK по которой генерируется синхронизирующие импульсы(она общая для всех), и линия выбора устройства SS(Slave Select). Другое ее обозначение: CS(Chip Select).
  4. Каждое добавленное SPI устройство увеличивает интерфейс на еще одну SS/CS линию.
  5. Интерфейс полнодуплексный, линия MISO (Master In Slave Out) отвечает за прием(относительно мастера), линия MOSI отвечает за предачу.
  6. Имеется четыре режима работы SPI. Фаза SCK изначально имеет низкий уровень в mode 0, и высокий в mode 3. Чтение осуществляется по нарастающему фронту.
  7. В режимах 1 и 3 чтение осуществляется по падающему фронту. Встречаются редко, если верить книге «Практическое программирование микроконтроллеров AVR» Юрия Ревича, глава 11.
  8. Упрощеный вариант SPI состоит из трех линий. В таком случае связь идет только на прием или только на передачу.

Вот именно такой упрощеный режим используется в MAX6675. Документация:MAX6676 datasheet

Предлагаю еще раз взглянуть на формат передачи:

Данные передаются пакетами по два байта. Под температуру отводится 12 бит. 15-й бит, бит знака. LSB — младший значащий бит, MSB — старший значащий бит. Оффициальная легенда:

Значение температуры передается в градусах Цельсия, в диапазоне от 0 до 1024. 1024 — это десять бит, в то время как данные передаются 12-битным форматом. Значит, чтобы получить значение в градусах, нужно будет полученое число разделить на 4. Меня немного смутил второй бит, device ID. В смысле я не очень понимаю как может один бит служить идентификатором. Его скорее можно назвать битом корректности.

Если припомнить, то в случае с Arduino я использовал библиотеку: MAX6675-library

На проверку, там оказался довольно простой код:

Я решил не изобретать велосипед, и переписать код на чистом Си. В качестве шаблона использовал проект из предыдущего поста. Я отбросил файлы относящиеся к TWI, после чего осталось переписать main.c в соответсвии со своими целями:

Результат работы программы:

В данном случае виден результат воздействия горелки на термопару.
Скачать проект вместе со сборочными файлами и прошивкой для ATmega8 можно здесь.
Структура проекта:

Программная реализация интерфейса управления tm1640 на atmega

Arduino TM16xx library for LED & KEY and LED Matrix modules based on TM1638, TM1637, TM1640 and similar chips. Simply use print() on 7-segment displays and use Adafruit GFX on matrix displays.

TM16xx LEDs and Buttons library

This Arduino library facilitates driving LED displays using TM16xx LED driver chips. The TM16xx chip family allows driving 7-segment LED displays or LED matrices. Next to built-in high-frequency LED multiplexing, they offer control of LED brightness. Most TM16xx chips also support reading key-scan data for button presses. Using this library you can simply use print() on a 7-segment display or use Adafruit GFX on a LED matrix. Currently this library supports the TM1620, TM1628, TM1630, TM1637, TM1638, TM1640, TM1650 and TM1668 chips. Note that there are similar chips made by other manufacturers that may be compatible with the Titan Micro chips. For instance: the HBS640 by WINRISE is compatible with the TM1640.

Initial version was based on the TM1638 library by Ricardo Batista. Further inspiration from the TM1637 library by Avishay, the Max72xxPanel library by Mark Ruys and the OneButton library by Matthias Hertel.

Table of contents

  • TM16xx chip features
  • Library structure
  • Basic usage
  • TM16xxDisplay class
  • TM16xxMatrix class
  • TM16xxMatrixGFX class
  • TM16xxButtons class
  • New in this library
  • Features & limitations
  • More information

TM16xx chip features

Type segments x digits buttons interface
TM1620 8 x 6 — 10 x 4 n/a DIN/CLK/STB
TM1628 10 x 7 — 13 x 4 10 x 2 multi DIO/CLK/STB
TM1630 7 x 5 — 8 x 4 7 x 1 multi DIO/CLK/STB
TM1637 8 x 6 (common anode) 8 x 2 single DIO/CLK
TM1638 10 x 8 8 x 3 multi DIO/CLK/STB
TM1640 8 x 16 n/a DIN/CLK
TM1650 8 x 4 7 x 4 single DIO/CLK (SDA/SCL)
TM1668 10 x 7 — 13 x 4 10 x 2 multi DIO/CLK/STB

See the documents folder for datasheets containing more information about these chips and their pinouts.

This library has a layered structure to simplify the support of multiple TM16xx chips. By using a base class that provides a uniform API, your application doesn’t need chip specific code. Likewise, the library can offer common functionality in display specific classes that support multiple chips.

The figure below illustrates that concept:

To use this library you need to include the class that matches the chip on your module and instantiate the object:

In the setup() function you can set the intensity of the display, but that’s not mandatory:

In the loop() function you can use basic display methods provided by the base class:

For the easy to use print() method and more advance display methods you can use the TM16xxDisplay class.

The TM16xx chip makes it easy to see if a button is pressed. To check if a button was pressed you can use the getButtons() method:

Please note that while you don’t need to write any code for debouncing, the button state may be reset when you display something. For advanced detection of button clicks, double clicks and long presses you can use the TM16xxButtons class.

The TM16xxDisplay class adds some bytes to the memory footprint, but it provides the familiar easy to use print() and println() functions. Next to that it also provides some more advanced display methods. To use that class on top of the base class, all you need to do is instantiate it, refering to the chip specific class:

Simple print example using the TM16xxDisplay class:

See TM16xxDisplay.h for the provided methods.

The TM16xxMatrix class provides basic methods for using a single LED-matrix module. For more advanced graphics use the TM16xxMatrixGFX class. To use the TM16xxMatrix class on top of the base class, all you need to do is instantiate it, refering to the chip specific class:

Note that the TM1640 has sufficient outputs to drive two 8×8 matrices.

These methods can be used to set the pixels of the matrix:

See TM16xxMatrix.h for the provided methods.

The TM16xxMatrixGFX class implements the popular Adafruit GFX interface to drive one or more TM16xx based LED-matrix modules. To use the TM16xxMatrixGFX class you first need to include the proper header files:

Then you can instantiate the TM16xxMatrixGFX class, refering to the chip specific class:

Note that the TM1640 has sufficient outputs to drive two 8×8 matrices. The WeMOS D1 Mini Matrix LED Shield also uses the TM1640, but has only one 8×8 matrix.

These methods can be used to draw on the matrix:

In addition all the Adafruit GFX methods can be used, e.g.:

Multiple identical modules can be combined to form a large matrix. The data line can be shared to reduce the number of pins:

See Adafruit GFX documentation and TM16xxMatrixGFX.h for the provided methods. See the library examples for more information.

The TM16xxButtons class enlarges the footprint a bit, but based on the popular OneButton library library, it adds more advanced methods to use buttons. Next to simply polling the state of each button, you can define callback functions that will be called when a button is released, clicked, double-clicked or long pressed. To use this class on top of the base class, all you need to do is include the proper headers and instantiate the buttons object, refering to the chip specific class, for example:

Then you define the functions you want to use to handle the button events:

In setup() you need to attach the callback function:

(BTW. Besides a click function, you can also attach a function to handle release, doubleclick and longpress events).

In loop() you need to call the tick() function that detects all state changes and calls the callback functions as needed:

To implement a shift key, you can use the isPressed() function. See TM16xxButtons.h for the provided methods and the Button clicks example for more information.

New in this library

Added library functionality:

  • Revised library structure to simplify support of other TM16xx chips.
  • Basic functionality in base class for a uniform API.
  • Support for TM1637. Note: TM1637 does not support simultaneous button presses. (Method derived from TM1637 library but using pins in standard output mode when writing).
  • Support for TM1668. Note: TM1668 can be used in 10×7 — 13×4 display modes. Datasheet partly translated.
  • Support for TM1650. Note: TM1650 can be used in 8×4 or 7×4 display mode. Datasheet fully translated.
  • Reduced required RAM memory by using PROGMEM fonts.
  • Support for ATtiny44A and ESP8266 in addition to regular Arduinos.
  • Separate classes for LED matrix and advanced LED display support.
  • Simple display of text and numbers on 7-segment displays using familiar print() and println() methods.
  • Support for the Adafruit GFX graphics library for advanced graphics on a LED matrix.
  • Full support for QYF-TM1638 module (8 digit common anode LED display and 4×4 keypad)
  • Support for TM1638 in Anode Mode (10 digit common anode LED 8 segment display) [TM1638Anode.h]
  • Support for combining multiple modules into one large Adafruit GFX matrix.
  • Support for scanning all possible keys (K1, K2 and K3 lines) on TM1638.
  • Support for release, click, doubleclick and long press button detection using callback functions.
  • Added library examples.
  • Support for TM1620 (thanks @eddwhite)
  • Support for TM1630 (thanks @tokuhira)
  • Support for TM1628. Note: TM1628 can be used in 10×7 — 13×4 display modes.

Functionality in original library by Ricardo Batista:

  • Support for the TM1638 and TM1640, including common anode TM1638 module;
  • Helper methods for displaying numbers in decimal, hexadecimal and binary;
  • Support for multiple chained TM1638 and for TM1638 in inverted position;
  • Support for dimming the display and LEDs and for writing text;
  • Reading simultaneous button presses on TM1638;
  • The current version of this library supports ESP8266/ESP32, Atmel ATmega (e.g. ATmega328 and ATmega168) and Atmel ATtiny MCUs. Due to the required memory, the smallest ATtiny MCU supported is the ATtiny44. Please let me know if you’ve successfully used this library with other MCUs.
  • The TM16xx chips offer no support for daisychaining multiple chips, but when separate Clk or Latch lines are used the Din line can be shared for combined displays.
  • The library doesn’t support combining multiple 7-segment modules into one display, but it is possible to define multiple display objects for multiple different modules. See the TM1638_TM1637ex_two_modules example.
  • The TM16xxMatrixGFX class does support combining multiple LED Matrix module into one large matrix. Please note that the TM1640 supports up to 16 digits or an 8×16 LED matrix.
  • The QYF-TM1638 module (TM138 with common anode display) is fully supported. Please note that while multiple buttons can be pressed, pressing more than two buttons can give faulty results due to the lack of short-out preventing diodes on the module.
  • The popular TM1638 LED & KEY module comes in a number of varieties. My version has some odd button wiring sequence: S1=KS1, S5=KS2, S2=KS3, S6=KS4, S3=KS5, S7=KS6, S4=KS7, S8=KS8
  • The TM1668 class has experimental support for using RGB LEDs on Grids 5-7. Some information about the wiring can be found in the example code. Most likely future versions will have a specific class for using RGB LEDs. The TM1680 has 8×24 outputs which sounds ideal for creating a 8×8 RGB matrix. Unfortunately these chips don’t support individual LED brightness, only intensity of the whole display.
  • The TM1650 datasheet mentions SDA and SCL pins. The used protocol resembles I2C, but lacks addressing. For that reason this library doesn’t use the I2C Wire library, but (slow) bitbanging using digitalWrite.
  • The WeMOS D1 mini Matrix LED Shield and the TM1640 Mini LED Matrix 8×16 by Maxint R&D have R1 on the right-top. Call setMirror(true) to reverse the x-mirrorring.
  • When using TM16xxButtons, the amount of memory used can become too large. To preserve RAM memory on smaller MCUs such as the ATtiny44A, the number of buttons is limited to 8 on the ATtiny MCUs. This can be changed by setting the maximum in the TM16xxButtons.h header file:
  • An alternative RAM preserving implementation using dynamic memory allocation is optional, but not suitable for small MCUs as using malloc/free will increase the required FLASH program space by over 600 bytes. Modify the TM16XX_OPT_BUTTONS_. defines in the header file at your own risk.

See the library examples for more information on how to use this library. See also the original examples by Ricardo Batista. Most will still work or only require minor changes.

  • Manufacturer: Titan Micro Electronics — LED driver datasheets
  • Original TM1638/TM1640 library: https://github.com/rjbatista/tm1638-library
  • TM1637 library used for reference: https://github.com/avishorp/TM1637
  • A TM1637 library optimized for speed and size: https://github.com/Erriez/ErriezTM1637
  • TM1650 library that uses the Wire interface: https://github.com/mozgy/Mozz_TM1650
  • MAX7219 LED Matrix library: https://github.com/markruys/arduino-Max72xxPanel
  • OneButton multi-state buttons: https://github.com/mathertel/OneButton
  • Adafruit GFX library: https://github.com/adafruit/Adafruit-GFX-Library
  • Adafruit GFX documentation: https://learn.adafruit.com/adafruit-gfx-graphics-library
  • Matrix transposition used in TM1638QYF: https://www.chessprogramming.org/Flipping_Mirroring_and_Rotating#Anti-Diagonal
  • All code on this GitHub account, including this library is provided to you on an as-is basis without guarantees and with all liability dismissed. It may be used at your own risk. Unfortunately I have no means to provide support.

About

Arduino TM16xx library for LED & KEY and LED Matrix modules based on TM1638, TM1637, TM1640 and similar chips. Simply use print() on 7-segment and use Adafruit GFX on matrix.

Примеры на Си для микроконтроллеров Atmel AVR

Здесь представлены примеры различных программ на языке Си для микроконтроллеров Atmel AVR. Все примеры написаны под микроконтроллер ATmega16, поэтому при переносе на другие МК семейства AVR это нужно учитывать. Тактовая частота микроконтроллера во всех примерах 8 МГц (используется тактирование от внутреннего генератора). Код примеров разбит на блоки и снабжен комментариями. Проекты написаны в среде Eclipse (инструкция по установке и настройке Eclipse для AVR) и легко могут быть импортированы в Eclipse. Также можно использовать данные проекты и в среде AVR studio (изменится только структура файлов проекта). При обнаружении ошибок просьба сообщить на почту.

Blink – Самый простой пример. К порту C подключены 8 светодиодов. Светодиоды зажигаются логической единицей на линии порта. В цикле светодиоды порта включаются и выключаются. Свеобразный аналог Hello World в мире встраиваемых систем.

IO Ports – В данном примере рассматривается работа с портами ввода-вывода. К порту C подключены 8 светодиодов (линии 0-7). К линии 2 порта D подключена кнопка, с подтяжкой на землю. При нажатии кнопка выдает на линию 0 порта С уровень логической единицы. Цикл программы организован следующим образом: при запуске включается бегущий огонь, сначала загорается светодиод на линии 0 порта C, затем на линии 1 и т.д. По достижении линии 7 направление бегущего огня меняется (от 7 к 0). При нажатии на кнопку бегущий огонь останавливается и загораются одновременно все светодиоды. После повторного нажатия на кнопку бегущий огонь продолжает перемещаться с места остановки.

Dynamic Indication – В данном примере рассматривается работа с 7-сегментным индикатором. В моём случае он имеет 4 разряда (цифры). Поскольку у меня на плате установлены транзисторы для управления разрядами, то управление осуществляется выводом логической единицы и на разряды и на сегменты. Схема подключения следующая: к линиям 0-7 порта C подключены сегменты индикатора, а к линиям 0-3 порта В разряды индикатора. При запуске на индикатор выводятся цифры 1 2 3 4.

UART – В данном примере рассматривается периферийного модуля UART (универсальный асинхронный приёмопередатчик). Модуль UART можно настроить как на работу с прерываниями, так и без них (вручную, путём работы с флагами). Пример работает следующим образом: при получении байта, МК переходит в обработчик прерывания (используется только прерывание по приёму данных) и разбирает численное значение байта (0-255) на цифры, которые и выводятся на 7-сегментный индикатор. Схема подключения аналогична предыдущему примеру. Передача осуществляется по двум линиям UART (порт D линии 0-1), к которым необходимо подключить линии RX и TX преобразователя USB-UART. Для настройкки без прерываний необходимо обнулить бит RXCIE в регистре UCSRB и вручную опрашивать интерфейс в основном цикле программы.

Clock – В данном примере рассматривается реализация простых часов с 7-сегментным индикатором и парой кнопок. Только здесь уже требуется 6 разрядов, хотя секунды можно опустить. Кнопки с подтяжкой на землю. При нажатии кнопка выдает на линию высокий логический уровень. Индикатор подключается как и в предыдущих примерах (сегменты к порту C, разряды к порту B), а кнопки к линиям 2-3 порта D. Кнопка используется PD2 для установки минут, а PD3 для установки часов. По нажатию каждой из кнопок увеличивается значение соответствующего разряда (минуты или часы).

DS18B20 – В данном примере рассматривается работа с цифровым датчиком температуры DS18B20. Показания температуры выводятся на 7-сегментный индикатор. Вывод DQ датчика поключен к ноге (пину) PD5. Линия должна быть подтянута к плюсу питания резистором на 4.7-10 кОм (согласно документации). Датчик опрашивается каждые 5 секунд. Температура выводится на 4-разрядный индикатор: знак, два разряда на целуюю часть и один на вещественную. Документация к датчику здесь.

DHT11 – В данном примере рассматривается работа с датчиком температуры и влажности DHT11. Показания температуры выводятся на 7-сегментный индикатор. Вывод DATA (также SDA) датчика поключен к ноге (пину) PD5. Линия должна быть подтянута к плюсу питания резистором на 4.7-10 кОм (согласно документации). Датчик опрашивается каждые 5 секунд. Измеряются температура и влажность, но на дисплей выводится только влажность (целое двухзначное число). Документация к датчику здесь.

DHT22 – В данном примере рассматривается работа с датчиком температуры и влажности DHT22. По сравнению с DHT11 данный датчик обладает большей точностью и более широким диапазоном измерений. Показания температуры выводятся на 7-сегментный индикатор. Вывод DATA (также SDA) датчика поключен к ноге (пину) PD5. Линия должна быть подтянута к плюсу питания резистором на 4.7-10 кОм (хотя согласно документации это и необязательно). Датчик опрашивается каждые 5 секунд. Измеряются температура и влажность, но на дисплей выводится только влажность (вещественное двухзначное число с одним знаком после запятой). Документация к датчику здесь.

BMP180 – В данном примере рассматривается работа с цифровым датчиком температуры и атмосферного давления BMP180. Показания атмосферного давления выводятся на 7-сегментный индикатор. Датчик подключаетсяпо интерфейсу I2C. Линии SDA и SCL должны быть подтянуты к плюсу питания резисторами на 4.7-10 кОм. Датчик опрашивается каждые 10 секунд. Измеряются температура и давление, но на дисплей выводится только атмосферное давление в мм. ртутного столба (целое число). Документация к датчику здесь.

BH1750 – В данном примере рассматривается работа с цифровым датчиком освещенности BH1750. Показания освещенности выводятся на 7-сегментный индикатор. Датчик подключается по интерфейсу I2C. Линии SDA и SCL должны быть подтянуты к плюсу питания резисторами на 4.7-10 кОм. Датчик опрашивается каждые 5 секунд. Документация к датчику здесь.

ADC Indication – Данный пример аналогичен примеру с UART. Отличие в том, что байт берется с линии 0 порта А (линия 0 АЦП, ADC0). Микроконтроллер по таймеру производит аналого-цифровое преобразование напряжения на линии 0 порта А, (младшие 2 бита отбрасываются как шум). При измерении используется внутренняя опора 5 В. К линии PD2 порта D подключена кнопка, которая определяет режим вывода показаний. При нажатии на кнопку выводится результат измерений в виде числа от 0 до 255. Если кнопка не нажата, то результат измерений переводится в вольты и выводится на индикатор (с точностью до десятых).

Fast PWM – В данном примере показана настройка аппаратного ШИМ (широтно-импульсная модуляция, англ. PWM). К линиям 4 и 5 порта D подключены светодиоды, а к линиям 2-3 и 6-7 порта D – кнопки каналов A и B соответственно. Кнопки с подтяжкой на землю (при нажатии кнопка выдает на линию порта уровень логической единицы) Кнопки на линях 2 и 3 соответственно увеличивают и уменьшают коэффициент заполнения ШИМ (меняется яркость светодиода) канала А. Кнопки на линях 6 и 7 соответственно увеличивают и уменьшают коэффициент заполнения ШИМ канала B. Число сравнения для каждого из каналов меняется в диапазоне от 0 до 255. Для канала А шаг изменения равен 10, для канала В шаг равен 5.

HCSR04 – В данном примере рассматривается работа с ультразвуковым датчиком расстояния HCSR04. К линии PD3 подключен вывод Trigger датчика, а к линии PD2 вывод Echo. Поключение 7-сегментного индикатора аналогично предыдущим примерам. МК периодически опрашивает датчик и определяет расстояние до препятсвия в сантиметрах. После этого число разбивается на цифры и выводится на дисплей. Документация к датчику здесь.

Matrix Keyboard – В данном примере показана работа с матричной клавиатурой. Микроконтроллер динамически опрашивает клавиатуру, а затем определяет номер нажатой клавиатуры. Размер поля 3 на 3 – получаем 9 кнопок. Нажатие первых 8-ми приводит к зажиганию светодиода на соответствующей линии порта А, нажатие 9-ой кнопки зажигает все светодиоды порта А. Матричная клавиатура подключается к линиям 0-5 порта С (три столбца и три строки). В архиве схема и печатная плата матричной клавиатуры (Diptrace).

Shift Register – В данном примере рассматривается работа с модулем SPI на примере сдвигового регистра 74HC595. К регистру подключены светодиоды, в качестве линии CS используется линия 4 порта B (вывод not SS). Линия DS (14 нога) регистра идет к MOSI (PB5), линия SHCP (11 нога) к линии SCK (PB7), линия STCP (12 нога) к линии SS (PB4). Линии MR (10 нога) и OE (13 нога) должны быть подтянуты к высокому и низкому логическим уровням соответственно. По таймеру микроконтроллер меняет состояние светодиодов: поочерёдно горят то чётные светодиоды, то нечётные. Если при этом передать байт по UART’у, то он будет выведен в порт на светодиоды. Чтобы обратно переключиться в режим мигания необходимо послать по UART’у 0x00 (ноль). Документация к микросхеме 74HC595 здесь.

SG-90 Servo – В данном примере рассматривается работа с сервоприводом SG-90. Используется аппаратный ШИМ. Линия ШИМ сервпопривода подключена к каналу А аппаратного ШИМ. Кнопки поворота подключены к линиям PD2 и PD3. Кнопка на линии PD2 увеличивает длительность импульса, кнопка на линии PD3 уменьшает длительность импульса. Длительность импульса меняется от 1 до 2 мс. Описание сервомотора здесь.

RGB Lamp – В данном примере рассматривается работа с трехцветным RGB-светодиодом. Реализовано плавное переливание цветов с использованием программного ШИМ. Линии красного, зеленого и синего цветов подключаются соответственно к линиям 2, 3 и 4 порта D.

TSOP4836 NEC – В данном примере рассматривается работа с фотоприемником TSOP4836 и протоколом передачи NEC, который широко используется в инфракрасных пультах дистанционного управления. При получении команды на дисплей выводится ее код. Поключение 7-сегментного индикатора аналогично предыдущим примерам. Описание фотоприемника здесь.

WS2812 Ring – В данном примере рассматривается работа со светодиодами WS2812 с встроенным ШИМ-контроллером. К контроллеру подключено такое кольцо из 16 светодиодов (количество светодиодов в кольце можно указать в коде). Библиотека для работы с WS2812 не моя (взята на гитхабе и немного допилена, копирайт сохранён). В программе сначала задается массив цветов (красный, зеленый, синий), а затем в цикле реализуется их сдвиг и плавным изменением интенсивности. Линия IN первого светодиода подключается к линии PD2 порта D. Описание светодиодов здесь.

MFRC522 RFID – В данном примере рассматривается работа со считывателем RFID карточек MFRC522. Cчитыватель подключён к контроллеру по стандартной схеме. Библиотека для работы с MFRC522 не моя (взята на гитхабе и немного допилена, копирайт сохранён). При запуске контроллер определяет тип ридера и отправляет данные в UART. Затем идет непрерывная проверка обнаружения RFID устройств. При поднесении карточки или брелка считывается его адрес и отправляется в UART (адрес 32 бита, 4 байта). Описание считывателя здесь.

Работа с микроконтроллерами: прошивка программатором и чистый «Си»

В этой статье я расскажу о том, как программировать микроконтроллеры без использования Arduino. Мы будем использовать программатор AvrISP STK500 для программирования контроллера ATtiny84.

Нам понадобится

Подключаем питание

Arduino мы не используем, поэтому обо всем нам придется думать самостоятельно. И первое, с чем необходимо разобраться — питание. Мы будем использовать преобразователь L7805, обладающей следующими характеристиками:

Теперь нам надо узнать схему подключения этого преобразователя. Ее мы найдем на странице 3 даташита.

Помимо самого преобразователя, мы видим еще 2 конденсатора — входной Сi и выходной Сo. Входной конденсатор необходим для того, чтобы сгладить пульсации на входе в случае удаленности L7805 от источника. В нашем случае длина соединительных проводов не будет превышать 15 см, поэтому входного конденсатора у нас не будет. Зато будет выходной, поскольку мы хотим «кормить» наш контроллер стабильным питанием.

Распиновка

Необходимо знать назначение ножек преобразователя. Это описано на 2-й странице даташита.

Схема

С учетом всего вышеописанного, получается схема для организации питания.

Программатор

В качестве программатора мы использовали AvrISP STK500 от Seeed Studio. Для его работы под Windows и Mac OS необходимы драйверы. Их можно скачать с официального сайта. Пользователям Linux устанавливать ничего не нужно — программатор будет сразу готов к работе.

Подключение к контроллеру

Распиновка разъема программатора такова:

Важно! Это распиновка разъема программатора, если смотреть на него сверху (отверстиями от себя). Не перепутайте!

Разъем программатора необходимо подключить к микроконтроллеру. Можно использовать как 10-пиновый разъём, так и 6-пиновый. Без разницы. Соединим проводами соответствующие пины, т.е:

10-пиновый ICSP ATtiny84
Reset 5 4
MOSI 1 7
MISO 9 8
SCK 7 9

Прошивка

Напишем код прошивки на чистом «C», которая заставит светодиод мигать. Использование ШИМ-сигналов и считывание аналоговых сигналов на чистом «C» не так тривиальна, и может являться темой отдельной статьи, поэтому остановимся пока на простейшем примере.

После скетчей Arduino, код малопонятен, правда? Ничего, сейчас я объясню, что да как. В первых двух строчках мы подключаем необходимые библиотеки, чтобы воспользоваться такими штуками, как DDRA , PORTA , _delay_ms .

Что же такое DDRA ? Это регистр микроконтроллера, управляющий направлением работы порта А. Он содержит в себе 8 бит. Если установить какой-то бит в 1, то пин с соответствующим номером станет выходом.

PORTA — тоже регистр, но он содержит в себе данные порта А. Если мы хотим на вывод номер 2 записать логическую единицу, то мы должны поместить 1 в соответсвующий бит регистра.

А _delay_ms — функция задержки. Исходя из этого можно составить таблицу соответствия:

Arduino C
Направление pinMode(led, OUTPUT); DDRA = 1
Значение digitalWrite(led, HIGH); PORTA = 1
Задержка delay(1000); _delay_ms(50);

Однако, самым важным различием кода является то, что в программе на С нет разделений функций setup и loop . За все это отвечает функция int main(void) . И она выполняется всего 1 раз! А мы хотим, чтобы наш светодиод моргал не один раз, а постоянно. Как раз для этого и используется бесконечный цикл while (1==1) .

Поэтому легко сделать вывод, что этот цикл и есть аналог функции loop() в Arduino. А то, что до него — аналог функции setup() .

Далее начинается самое интересное. Нам нужно скомпилировать и загрузить прошивку. Однако, в зависимости от вашей операционной системы, методика будет различаться.

Mac OS X

Первым делом необходимо скачать и установить CrossPack for AVR Development. Это даст нам все необходимые инструменты. CrossPack состоит из двух частей.

Первая нам нужна для написания кода и создания файла прошивки, а вторая — для заливки прошивки в контроллер.

Проект создается в три шага.

В результате будет создано следующее дерево файлов.

На данном этапе нас интересует содержимое файла Makefile . В нем содержится информация о том, что вообще мы используем: какой контроллер, программатор. Это все описывается в строках с 20 по 24:

Пройдемся по строкам:

Это автосгенерированный make-файл, поэтому нам необходимо вручную его подправить. Править будем строку DEVICE у нас же микроконтроллер attiny84 и строку FUSES . А вот с ней все сложнее. Fuse-биты, или просто «фьюзы» — два (иногда три) особых байта, в которых содержится фундаментальая конфигурация работы контроллера. Очень важно правильно их задать.

Внимание! Задание неверных fuse-битов может привезти к тому, что микроконтроллер перестанет работать и вернуть его к нормальной жизни может быть либо очень сложно либо невозможно! Воспользеумся сайтом AVR Fuse Calcuator.

Сначала из выпадающего списка выберем нужный нам контроллер (ATtiny84).

И затем укажем необходимые опции, которые нам нужны. Сейчас для нас важны 2 вещи: сохранение возможности прошивать контроллер через SPI и сохранение его работоспособности без внешнего резонатора, поэтому выбираем соответствующие пункты, а остальные оставляем по умолчанию.

Видим, как поменялись сгенерированные значения.

Внесем изменения в Makefile.

Прошивка

Она происходит в 2 этапа.

Сначала необходимо перейти в папку firmware и выполнить команду make . Если ошибок нет, то результат выполнения команды будет таким:

Эта команда сделает из нашего исходника main.c файл, пригодный для заливки в контроллер — main.hex .

Второй этап — как раз заливка прошивки. Делается это с помощью команды make flash . Ее нормальный вывод выглядит следующим образом:

Все, прошивка контроллера завершена.

Windows

Здесь все проще.

Первым делом необходимо скачать и уствновить среду разработки для AVR — Atmel AVR Studio 4. А вторым — Atmel AVR Toolchain.

После запуска среды, необходимо создать новый проект.

Затем указать имя, расположение и то, что мы хотим использовать С ( GCC ).

Третий шаг — настройка отладчика.

На этом все, проект готов к использованию. Теперь необходимо написать и сохранить исходник, который мы уже обсудили.

В результате общий вид среды разработки выглядит вот так:

Теперь необходимо подключиться к программатору. Делается это с помощью нажатия на кнопку con .

В качестве Platform выбираем STK500 , а в Port — Auto . Затем нажимаем Connect.

Если все правильно, то в открывшемся окне выбираем вкладку Main и нажимаем в ней на кнопку Read Signature .

Строка Reading signature from device .. 0x1E, 0x93, 0x0C .. OK! говорит о том, что все хорошо и сигнатура успешно прочиталась. Сигнатура — это своего рода позывной микроконтроллера, которым он сообщает собственную модель.

Это окно нельзя закрывать, иначе соединение с программатором будет потеряно. Просто сверните его.

Теперь нажмем Build → Build . Это заставит программу скомпилироваться. Прошьем контроллер с помощью кнопки Write Flash Memory Using Current Settings — это заставит скомпилированную программу загрузиться в память микроконтроллера.

Заключение

Мы собрали простейшее устройство мигалку, но сделали это на низком уровне. С использованием программатора и «продвинутой» среды разработки, а не Arduino.

Разобравшись в премудростях программирования микроконтроллеров на чистом «Си», вы сможете выжимать из них максимум возможности, затрачивая при этом минимум места и денег.