Драйвер I2C для LCD1602 с управлением от модуля PCF8574
Драйвер I2C для LCD1602 с управлением от модуля PCF8574
В статье будет рассмотрен пример реализации драйвера для LCD BC1602A с русской прошивкой и управлением от модуля на микросхеме PCF8574. Плата дисплея LCD дополнена клавиатурой из пяти клавиш, которые управляются вторым модулем PCF8574. Драйвер написан для PIC24 и обеспечивает следующие возможности.
• Запись строк текста, как в латинском алфавите, так и в русском алфавите, либо в смешанном варианте англо-русском.
• Чтение определенного числа символов текста с произвольной позиции.
• Управление курсором с помощью клавиатуры или программой.
• Управление LCD из разных задач.
Драйвер может быть адаптирован и для других типов микроконтроллеров поскольку шина I2C практически стандартизирована и модули I2C микроконтроллеров строятся однотипно. Ниже показана конструкция модуля LCD, модуля PCF8574 и схема соединений.
LCD1

    Модуль PCF8574, приобретен на Алиэкспресс. Он весьма недорог и позволяет обеспечить управление LCD в четырех битном режиме по шине I2C. Поскольку PCF8574 имеет только восемь выходных бит на нем нельзя реализовать восьми битный режим LCD. Для восьми битного режима LCD необходим модуль на основе PCF8575, имеющий шестнадцать выходов, но он существенно дороже. Управление LCD по шине I2C сильно снижает скорость обмена процессора с LCD, но сводит число управляющих линий до двух вместо семи в четырех битном режиме или одиннадцати в восьми битном режиме. Реализация драйвера в четырех битном режиме с управлением от порта микроконтроллера описана в моей статье на странице http://dslev.narod.ru/DriverLCD.html.
LCD2
    Если читателю будет недостаточно материала статьи для самостоятельного написания драйвера, то автор может предоставить полный код драйвера, а также справочные документы, по запросу dslev@yandex.ru.

shema

    Особенности реализации драйвера LCD с управлением по шине I2C

    Драйвер LCD состоит из двух слоев, первый слой должен обеспечить обмен с подчиненным модулем I2C (PCF8574). Второй слой обеспечивает управление LCD в четырех битном режиме от выходных линий модуля PCF8574. В написании функций первого слоя может оказать помощь библиотека компилятора для периферийных устройств PIC24F, PIC24H, PIC30F, PIC33F. Находится библиотека по пути …\XC16_1.35\src\peripheral_24F.zip\peripheral_24F\pmc\i2c. Для остальных типов PIC отдельная папка …\peripheral_30F_24H_33F.zip\... Папка содержит набор файлов, для каждой функции отдельный файл. Без примера разобраться в них не просто, пример и описание можно найти в файле .chm или .htm по пути …\XC16_1.35\docs\periph_libs\. Документация опирается на работу с периферийным модулем соответствующего типа PIC24 и содержит файлы для разных версий модулей I2C. Чтобы не путаться во множестве файлов, нужно ориентироваться на пример из Microchip PIC24F Peripheral Library.chm и скачать техническое описание модуля I2C DS39702, которое описывает периферийный модуль I2C для микроконтроллеров dsPIC33/PIC24.
    В статье описываются общие принципы обмена с подчиненным модулем (master-slave), без деталей, статей на эту тему много как в Интернете, так и документе DS39702. Всего для обеспечения обмена достаточно пяти функций, текст приводится ниже. В отличие от примера из файла Peripheral Library.chm в приводимых функциях используется минимально необходимых управляющих сигналов двух основных регистров периферийного модуля I2C PIC24, I2CxCON и I2CxSTAT. Остальные регистры, упоминаемые в документе DS39702, не используются, либо они не реализованы. Макросы, примененные в функциях, описаны в файле …\XC16_1.35\support\PIC24F\h\p24FJ256DA210.h и в файле .h драйвера. Для других типов PIC24 имеются свои файлы.
    Центральный процессор PIC24 управляет протоколом передачи сообщений в периферийный модуль I2C PIC24. Управление заключается в установке определенных битов в управляющем регистре I2CxCON и в ожидании завершения операции, что отображается в регистре состояния I2CxSTAT. Ожидание завершения операции довольно длительный процесс, передача одного символа выполняется за 112 микросекунд. Можно использовать прерывания, но об этом далее.

    Сеанс обмена "Мастер-подчиненный"
    Рассмотрим сеанс обмена по шине I2C применительно для варианта управления LCD через модуль PCF8574. Это первый слой драйвера.
1. Каждый сеанс обмена начинается с подачи "Мастером" сигнала Start (см. рисунок). Старт это изменение уровня на линии данных SDA с высокого на низкий при наличии высокого уровня на линии тактового сигнала SCL.
2. После выдачи сигнала Start, "Мастер" должен передать на шину адрес подчиненного. Для этого он выдаёт на шину 7-ми битный адрес устройства (PCF8574), плюс дополнительный восьмой бит, который указывает направление передачи данных. Если производится запись в устройство (PCF8574), то этот бит равен нулю, а если чтение, то этот бит равен единице. Первый байт после старта всегда всеми подчиненными устройствами воспринимается как адресация. Передача и прием сопровождаются сигналом подтверждения ACK, который может принимать значение нуль или единица.
3. После выдачи адреса следует передача или прием данных. Прием и передача сопровождаются тактовыми сигналами SCL. Восемь импульсов тактируют данные или адрес, девятый сигнал служит для формирования сигнала прерывания. Микроконтроллер PIC24F формирует прерывание вследующих случаях, после старта, после передачи данных или адреса и после сигнала стоп.
4. Завершается обмен передачей сигнала Stop, который заключается в изменении уровня на линии SDA с низкого на высокий при высоком уровне на линии SCL.
5. Внутри цикла обмена данными с устройством возможно переключение между передачей и приемом без завершения цикла по сигналу Stop. Для этого существует сигнал Restart, который позволяет не начинать новый сеанс обмена, а просто передать адрес устройства с битом записи или чтения. Сигнал Stop передается после завершения всего цикла обмена. Этот режим используется для чтения данных из LCD.
Рисунок ниже отображает три типа обмена данными. Драйвер использует все три типа форматов. Для работы с LCD используется первый и третий формат, второй формат обслуживает клавиатуру. На рисунке форматов обмена показан сигнал подтверждения ACK = 0 или ACK = 1(NACK). На этот сигнал нужно обратить внимание в режиме чтения. В техническом описании модуля PCF8574 сигнал подтверждения всегда показан как ACK, что неправильно.

format   


Исходя из форматов обмена, можно сделать вывод, что для обеспечения обмена по шине I2C нужно написать пять функций.
1. Функция, реализующая старт.
2. Функция, реализующая запись данных.
3. Функция, реализующая чтение данных.
4. Функция, реализующая повторный старт.
5. Функция, реализующая стоп.
Особняком стоит функция инициализации модуля I2C PIC24. В этой функции можно выбрать способ работы, с прерыванием или без оного.

Code1

В тексте функций используются собственные макросы, переопределяющие макросы файла p24FJ256DA210.h например, бит регистра I2C3CONbits.SEN определяется как CON_SEN, бит регистра I2C3STATbits.TRSTAT определяется как STAT_TRSTAT. Имена битов соответствуют обозначениям в техническом описании DS39702 модуля I2C микроконтроллера. Приведенные ниже функции полностью обеспечивают обмен по шине I2C с модулем PCF8574.

Code2

Code3

сщву4

Управление LCD в четырех битном режиме от выходной шины модуля PCF8574

Управлением LCD занимается второй слой драйвера. Он реализует команды LCD в четырех битном режиме. Следует отметить, что работа LCD в четырех битном режиме имеет некоторые нюансы, вызванные отличиями в контроллерах LCD разных производителей. Это касается в основном инициализации LCD, а также соблюдение временных соотношений сигналов управления. Подробно этот вопрос рассмотрен в статье на странице http://dslev.narod.ru/DriverLCD.html. Настоятельно рекомендуется опираться на техническое описание конкретного образца используемого LCD.

Запись данных в LCD
Функция записи байта данных должна реализовать временную диаграмму записи в соответствии с техническим описанием LCD, рисунок ниже.

write
    На этом рисунке показана фиксация данных в контроллере LCD по спаду строба Е. Строб Е, а также сигналы RS, W и данные передаются в LCD семью битами одновременно из модуля PCF8574, то для формирования стробов Е необходимо выполнить четыре передачи данных с разными значениями бита Е. Сигналы RS, W не изменяются. В результате требуется произвести предварительное преобразование строки, записать ее буфер и затем передать по шине I2C в модуль PCF8574. Последовательность записи байта данных выглядит следующим образом.
1. Старт.
2. Установка адреса модуля PCF8574 для записи.
3. Запись в буфер передачи подготовленной команды установка адреса LCD и строки данных.
4. Передача буфера в модуль PCF8574.
5. Стоп.
Реальная картинка процесса установки адреса памяти LCD и запись одного байта данных показана на рисунке ниже.

Set adr byte

Чтение данных
    Чтение данных значительно сложнее записи. Чтение данных необходимо только при работе с клавиатурой, когда оператор переключает режимы работы или делает другие действия. В случае простого отображения информации на экране и отсутствии клавиатуры режим чтения не нужен.
Чтение данных модулем PCF8574 выполняется при установленном высоком уровне строба Е, сбрасывать его нельзя. Последовательность чтения байта данных выглядит следующим образом.
1. Старт.
2. Установка адреса модуля PCF8574 для записи.
3. Запись в буфер передачи подготовленной команды установка адреса памяти LCD. Строб Е в команде не завершается, остается высокий уровень.
4. Переключение модуля PCF8574 в режим чтения.
5. Установка адреса модуля PCF8574 для чтения.
6. Читать старшие биты данных.
7. Переключение модуля PCF8574 в режим записи.
8. Установка адреса модуля PCF8574 для записи.
9. Завершить первый строб, Е=0.
10. Установка второго строба, Е=1.
11. Переключение модуля PCF8574 в режим чтения.
12. Установка адреса модуля PCF8574 для чтения.
13. Читать младшие биты данных, сформировать полный байт данных.
14. Переключение модуля PCF8574 в режим записи.
15. Установка адреса модуля PCF8574 для записи.
16. Завершить второй строб, Е=0.
17. Стоп.

    На картинке ниже показана реальная диаграмма чтения одного символа "Й" (0хА6). Байт 0х7F устанавливает строб Е=1, команду чтение RS=1, RW=1 и подтягивает шину модуля PCF8574 к высокому уровню.

Read byte

Инициализация LCD
    Инициализация LCD должна выполняться строго в соответствии с техническим описанием конкретного образца LCD. Часто можно прочитать в разных источниках, что управление LCD фактически стало стандартом, но это не так. Особенно это касается инициализации, неточная или неправильная последовательность команд вызывает полную или частичную неработоспособность LCD. Даже квалифицированные разработчики выбрасывают LCD в мусор, выполнив неправильную инициализацию. В данной статье описывается именно такой, "мусорный" LCD BC1602ABNHCD и второй BC2402AGPLCH, оба с русской прошивкой фирмы Bolymin. Следует заметить, что LCD с русской прошивкой существенно дороже. Не стоит пытаться изобразить русский алфавит перепрошивкой восьми пустых символов, зря потерянное время. Далее приведена функция инициализации, написанная в соответствии с алгоритмом инициализации BC1602ABNHCD и BC2402AGPLCH.

Code5

Управление клавиатурой и тестирование

    Для управления клавиатурой использован второй модуль PCF8574, подключен к шине I2C параллельно первому модулю. На втором модуле удалены подтягивающие резисторы на входах SDA и SCL. Модуль работает только в режиме чтения. В основном цикле микроконтроллера модуль клавиатуры опрашивается с периодом 300 мсек. Можно опрашивать по прерыванию, если выходы клавиатуры объединить по ИЛИ и завести на вход внешнего прерывания. Я посчитал, что это лишняя работа, модулю I2C назначено пониженное прерывание и на основной цикл нагрузки не будет.
Для опроса клавиатуры используется системный таймер микроконтроллера (TMR1). С периодом 300 мсек устанавливается флаг клавиатуры драйвера, который проверяется в главном цикле микроконтроллера. Если флаг установлен, вызывается функция управления клавиатурой. Флаг клавиатуры сбрасывается.

Code6
Code7
Code8

Прерывания
    В режиме мастер модуль I2C микроконтроллера генерирует прерывние MI2CxIF. Прерывание генерируется по следующим событиям в процессе обмена по шине I2C:
• После старта.
• После остановки.
• После передачи или чтения данных.
• После передачи сигнала подтверждения (ACK).
• После повторного старта.
• При определении события записи данных в передающий регистр до завершения текущей передачи.

    Если прерывания не используются, тогда нужно очищать флаг прерывания в программе после каждого события. При разрешенном прерывании флаг очищается в функции прерывания, события можно не обрабатывать. Обработка событий может потребоваться в каких-то особых случаях, для управленя LCD практической ценности в такой обработке я не увидел. Можно установить приоритет I2C в общей системе прерываниий микроконтроллера и в большинстве случаев этого достаточно. Ниже приведена таблица состояний регистров, которые могут обрабатываться в прерывании.

Table

На рисунке ниже показаны прерывания в режиме записи и чтения.На рисунке ниже показаны прерывания в режиме записи и чтения.

Int
Int_read

Инструменты разработки
1. Среда MPLAB X v4.15
2. Компилятор XC16 v1.35
3. Модуль микроконтроллера PIC24FJ256DA210
4. LCD BC1602ABNHCD и BC2402AGPLCH
Литература
1. DS39702.pdf – техническое описание модуля I2C dsPIC33/PIC24
2. PCF8574.pdf – техническое описание микросхемы
3. BC1602A.pdf - техническое описание LCD