LCD 1602 и STM32

29-05-2020, 15:49 1 комментариев
Сборка STM32 и LCD1602 часто используется электронщиками в современных проектах. В принципе, это не удивительно, ведь текстовые ЖК-дисплеи с I2C-адаптером довольно просты в наладке и дальнейшей эксплуатации. Они бюджетны по стоимости (если приобретать на AliExpress), при этом могут быть эффективно задействованы в проектировании 3Д-принтеров, бытовых электроприборов и всяческих машин.

Почему именно плата STM32 и шина I2C? Во-первых, так мы экономим свободные порты и уменьшаем применение проводов. Во-вторых, у платы есть преимущества перед теми же Ардуино Нано или Мега: рабочая частота 72 МГц, оперативная память 20 кБ, Flash-память 64 / 128 кБ, АЦП 12 бит и т.д.
Чтобы правильно использовать возможности программирования конкретно в нашем случае, в среду разработки Arduino IDE следует добавить плату STM32. Переходим в Файл > Настройки > Дополнительные ссылки для менеджера плат.

А далее следуем подсказкам скриншотов:
В разделе Upload method выбираем пункт Serial:
Готово!
Распиновка самой платы показана ниже:
Теперь вернемся к главному – теме нашей информационной статьи. В целом подключение дисплея LCD 1602 к STM32 по I2C шине мало чем отличается от подключения к микроконтроллеру Nano, разве что во второй отладочной плате используются иные выводы - B6 (SCL) B7 (SDA). При ее подключении к USB порту LCD-дисплея применяется питание 5V. При наличии внешнего источника питания (5В), это напряжение подается на VCC и на вход 5V той же платы STM32.

Заливаем программный скетч:
#include <Wire.h> 
#include <LiquidCrystal_I2C.h> // liquidcrystali2c.zip
LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей
void setup()
{
  lcd.init();                     
  lcd.backlight();// Включаем подсветку дисплея
  lcd.print("  rcl-radio.ru  ");
  lcd.setCursor(0, 1);
  lcd.print("    LCD 1602    ");
  delay(5000);
  lcd.noBacklight();// Выключаем подсветку дисплея
  delay(5000);
  lcd.backlight();// Включаем подсветку дисплея
}
void loop(){}
Если необходимо определить I2C-адрес LCD-экрана, проделываем такие шаги:
#include <string.h>

void I2C_Scan() {
    char info[] = "Scanning I2C bus...\r\n";
    HAL_UART_Transmit(&huart2, (uint8_t*)info, strlen(info),
                      HAL_MAX_DELAY);

    HAL_StatusTypeDef res;
    for(uint16_t i = 0; i < 128; i++) {
        res = HAL_I2C_IsDeviceReady(&hi2c1, i << 1, 1, 10);
        if(res == HAL_OK) {
            char msg[64];
            snprintf(msg, sizeof(msg), "0x%02X", i);
            HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg),
                              HAL_MAX_DELAY);
        } else {
            HAL_UART_Transmit(&huart2, (uint8_t*)".", 1,
                              HAL_MAX_DELAY);
        }
    }  

    HAL_UART_Transmit(&huart2, (uint8_t*)"\r\n", 2, HAL_MAX_DELAY);
}
Выводим на дисплей небольшой проверочный текст:

#define PIN_RS    (1 << 0)
#define PIN_EN    (1 << 2)
#define BACKLIGHT (1 << 3)

#define LCD_DELAY_MS 5

HAL_StatusTypeDef LCD_SendInternal(uint8_t lcd_addr, uint8_t data,
                                   uint8_t flags) {
    HAL_StatusTypeDef res;
    for(;;) {
        res = HAL_I2C_IsDeviceReady(&hi2c1, lcd_addr, 1,
                                    HAL_MAX_DELAY);
        if(res == HAL_OK)
            break;
    }

    uint8_t up = data & 0xF0;
    uint8_t lo = (data << 4) & 0xF0;

    uint8_t data_arr[4];
    data_arr[0] = up|flags|BACKLIGHT|PIN_EN;
    data_arr[1] = up|flags|BACKLIGHT;
    data_arr[2] = lo|flags|BACKLIGHT|PIN_EN;
    data_arr[3] = lo|flags|BACKLIGHT;

    res = HAL_I2C_Master_Transmit(&hi2c1, lcd_addr, data_arr,
                                  sizeof(data_arr), HAL_MAX_DELAY);
    HAL_Delay(LCD_DELAY_MS);
    return res;
}

void LCD_SendCommand(uint8_t lcd_addr, uint8_t cmd) {
    LCD_SendInternal(lcd_addr, cmd, 0);
}

void LCD_SendData(uint8_t lcd_addr, uint8_t data) {
    LCD_SendInternal(lcd_addr, data, PIN_RS);
}

void LCD_Init(uint8_t lcd_addr) {
    // 4-bit mode, 2 lines, 5x7 format
    LCD_SendCommand(lcd_addr, 0b00110000);
    // display & cursor home (keep this!)
    LCD_SendCommand(lcd_addr, 0b00000010);
    // display on, right shift, underline off, blink off
    LCD_SendCommand(lcd_addr, 0b00001100);
    // clear display (optional here)
    LCD_SendCommand(lcd_addr, 0b00000001);
}

void LCD_SendString(uint8_t lcd_addr, char *str) {
    while(*str) {
        LCD_SendData(lcd_addr, (uint8_t)(*str));
        str++;
    }
}

void init() {
    LCD_Init(LCD_ADDR);

    // set address to 0x00
    LCD_SendCommand(LCD_ADDR, 0b10000000);
    LCD_SendString(LCD_ADDR, " Using 1602 LCD");

    // set address to 0x40
    LCD_SendCommand(LCD_ADDR, 0b11000000);
    LCD_SendString(LCD_ADDR, "  over I2C bus");
}

void loop() {
    HAL_Delay(100);
}
Изучайте Arduino, собирайте интересные проекты и развивайтесь! До скорой встречи!
Поделись в социальных сетях:
О авторе
Калугин Антон

Программист микроконтроллеров с 8-ми летним стажем, работал в таких компаниях как IBM, ASUS, Microsoft.

В комментариях с радостью отвечу на ваши вопросы.

Все статьи автора
Похожие новости

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

Как подключить LCD 1602 к Ардуино в домашних условиях и пользоваться всеми преимуществами этого цифрового устройства – рассказываем сегодня в новой статье....

Сегодня рассмотрим подключение экрана LCD 2004A к Ардуино. Данный модуль интересен для использования (и обзора) по многим причинам. Он достаточно прост в...

Предлагаем на обзор подключение LCD дисплея на базе HD44780 к Ардуино. Модуль выбран как всегда не случайно, т.к. имеет определенные преимущества, о которых...

В этой статье мы рассмотрим подключение ADS1115 к Ардуино. Речь идет о 16-битном аналого-цифровом преобразователе, оснащенном 4 входами непосредственно для...

1 комментария
  1. Di
    29 июня 2021 22:21 Di

    Зачётная статейка, надеюсь это ИИ её лепил? Вы б хоть код проверяли на ошибки в IDE, не говоря уже о его работоспособности.

    replyОтветить
Оставить комментарий