STM Урок 22. HAL. I2C. I2C to LCD2004

 

 

 

Урок 22

HAL. I2C. Переходник для LCD 20×4

 

 

Сегодня мы попробуем подключить символьный дисплей LCD 20×4 подключить через переходник по шине I2C. Это позволит нам сэкономить ножки портов, а также обойтись меньшим количеством проводов.

Данный переходник выглядит вот так и его разъём полностью совместим по ножкам с разъёмом дисплея

 

image01

 

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

 

image02_500

 

По схеме мы видим на какие именно ножки разъёма дисплея у нас идут ножки микросхемы.

Проект создаём из MYLCD80, называем его I2CLCD80.

Запускаем Cube. Так как проект был создан в более ранней версии Cube, то в ответ на диалог с тремя кнопками жмём «Migrate», чтобы проект наш адаптировался к новой версии.

Включим I2C1. Ничего нигде больше не трогаем, запоминаем лапки SDA и SCL, генерируем проект, добавляем в него файл lcd.c, настраиваем программатор, собираем код.

Откроем файл lcd.h и исправим там всё в соответствии с требованиями шины I2C.

Убираем включение ножек портов совсем, т.к. они у нас не используются и этим займётся микросхема

 

#include "stm32f4xx_hal.h"

//————————————————

#define d4_set() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_SET)

#define d5_set() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_5, GPIO_PIN_SET)

#define d6_set() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_6, GPIO_PIN_SET)

#define d7_set() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_SET)

#define d4_reset() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_RESET)

#define d5_reset() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_5, GPIO_PIN_RESET)

#define d6_reset() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_6, GPIO_PIN_RESET)

#define d7_reset() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET)

 

Прежде чем раньше менять, нам потребуется функция, которая будет посылать определённые данные в переходник. Для того, чтобы нам её добавить, откроем файл lcd.h и напишем туда функцию

 

//————————————————

void WriteByteI2CLCD(uint8_t bt)

{

        buf[0]=bt;

        HAL_I2C_Master_Transmit(&hi2c1,(uint16_t) 0x4E, buf,1,1000);

}

//————————————————

 

Вернёмся в lcd.h

Всё остальное переделываем вот так на основании вышеупомянутой схемы

 

#define e_set()   WriteByteI2CLCD(portlcd|=0x04) // установка линии E в 1

#define e_reset()   WriteByteI2CLCD(portlcd&=~0x04)  // установка линии E в 0

#define rs_set()    WriteByteI2CLCD(portlcd|=0x01) // установка линии RS в 1

#define rs_reset()   WriteByteI2CLCD(portlcd&=~0x01)  // установка линии RS в 0

#define setled()    WriteByteI2CLCD(portlcd|=0x08) // включение подсветки

#define setwrite()   WriteByteI2CLCD(portlcd&=~0x02)  // установка записи в память дисплея

 

Теперь подправим файл lcd.c

Напишем туда кое-какие дефайны

 

#include "lcd.h"

//—————————————-

extern I2C_HandleTypeDef hi2c1;

uint8_t buf[1]={0};

char str1[100];

uint8_t portlcd = 0; //ячейка для хранения данных порта микросхемы расширения

 

Затем изменим функцию задержки, сделаем её в микросекундах

 

//————————————————

__STATIC_INLINE void DelayMicro(__IO uint32_t micros)

{

           micros *= (SystemCoreClock / 1000000) / 5;

   /* Wait till done */

   while (micros—);

}

//————————————————

 

 

Идём дальше по порядку.

Убираем функцию LCD_WriteData.

Убираем функции LCD_Command и LCD_Data, вместо них добавим другие функции

 

//————————————————

void sendhalfbyte(uint8_t c)

{

        c<<=4;

        e_set(); //включаем линию Е

        DelayMicro(50);

        WriteByteI2CLCD(portlcd|c);

        e_reset(); //выключаем линию Е

        DelayMicro(50);

}

//————————————————

void sendbyte(uint8_t c, uint8_t mode)

{

        if (mode==0) rs_reset();

        else         rs_set();

        uint8_t hc=0;

        hc=c>>4;

        sendhalfbyte(hc); sendhalfbyte(c);

}

//————————————————

 

Далее подправим эту функцию

 

void LCD_Clear(void)

{

        sendbyte(0x01, 0);

        DelayMicro(1500);

}

Эту тоже подправим

void LCD_SendChar(char ch)

{

        sendbyte(ch,1);

}

Данная функция подправится незначительно

void LCD_SetPos(uint8_t x, uint8_t y)

{

        switch(y)

        {

                case 0:

                        sendbyte(x|0x80,0);

                        HAL_Delay(1);

                        break;

                case 1:

                        sendbyte((0x40+x)|0x80,0);

                        HAL_Delay(1);

                        break;

                case 2:

                        sendbyte((0x14+x)|0x80,0);

                        HAL_Delay(1);

                        break;

                case 3:

                        sendbyte((0x54+x)|0x80,0);

                        HAL_Delay(1);

                        break;

        }

}

 

Теперь вот эту

 

void LCD_ini(void)

{

        HAL_Delay(15);

        sendhalfbyte(0x03);

        HAL_Delay(4);

        sendhalfbyte(0x03);

        DelayMicro(100);

        sendhalfbyte(0x03);

        HAL_Delay(1);

        sendhalfbyte(0x02);

        HAL_Delay(1);

        sendbyte(0x28, 0); //4бит-режим (DL=0) и 2 линии (N=1)

        HAL_Delay(1);

        sendbyte(0x0C, 0); //включаем изображение на дисплее (D=1), курсоры никакие не включаем (C=0, B=0)

        HAL_Delay(1);

        sendbyte(0x6, 0); //курсор (хоть он у нас и невидимый) будет двигаться влево

        HAL_Delay(1);

        setled();//подсветка

        setwrite();//запись

}

 

Вот эту незначительно

 

void LCD_String(char* st)

{

        uint8_t  i=0;

        while(st[i]!=0)

        {

                sendbyte(st[i],1);

                i++;

        }

}

 

Прошиваем, смотрим.

 

Предыдущий урок Программирование МК STM32 Следующий урок

 

Исходный код

 

Техническая документация на микросхему PCF8574

 

Отладочную плату, переходник I2C to LCD и дисплей можно приобрести здесь:

STM32F4-DISCOVERY

Переходник I2C to LCD1602 2004

Дисплей LCD 20×4

 

 

Смотреть ВИДЕОУРОК

 

STM32 HAL. I2C. I2C to LCD2004

 

2 комментария на “STM Урок 22. HAL. I2C. I2C to LCD2004
  1. Михаил:

    Добрый день.

    Отличный урок, но надо было особо заострить внимание на то, что для библиотеки HAL адрес внешнего устройства на шине I2C должен быть сдвинут влево на 1 бит. Не у всех переходничек имеет адрес 2F.

    Специально просмотрел внимательно этот урок и первый урок по шине I2C: ни в одном об этом напрямую не говорится. Т.е., пока адрес совпадает с Вашим, все нормально. А мне пришлось покурить интернет, т.к. адрес у меня оказался 3F.

  2. Евгений:

    Чтобы линия E не отключалась одновременно с данными.
    void sendhalfbyte(uint8_t c)
    {
    c<<=4;
    e_set(); //включаем линию Е
    DelayMicro(50);
    WriteByteI2CLCD(portlcd|=c);
    e_reset(); //выключаем линию Е
    DelayMicro(50);
    WriteByteI2CLCD(portlcd&=15);
    }

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*