8(495) 662-59-14

Главная / Форум
  • РУС / ENG
(495) 662-59-14 Многоканальный телефон Не дозвонились?
RE: MT-16S2H

a13428711
Пользователи

Сообщений: 7
Регистрация: 21.07.2020

Добрый день!
Приобрели у Вас дисплеи MT-16S2H-8 с I2C, но возникла проблема с обменом по шине - при передаче команды или данных первые полбайта берутся из предыдущей посылки, а вторая половина из текущей, от чего дисплей отрабатывает не то, что от него требовалось.
Имеется ли у вас рабочий платформоориентированный код (в идеале для Ардуино или STM32) для проверки работоспособности дисплеев и сверки кода?
Сейчас код выглядит так:

Код:
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00

#define En 0x04 // Enable bit
#define Rw 0x02 // Read/Write bit
#define Rs 0x01 // Register select bit

void MTxxSx_WriteCmd(char cmd)
{
char data_u, data_l;
uint8_t data_t[4];

data_u = (cmd&0xf0);
data_l = ((cmd<<4)&0xf0);

data_t[0] = data_u | LCD_BACKLIGHT | En;
data_t[1] = data_u | LCD_BACKLIGHT;
data_t[2] = data_l | LCD_BACKLIGHT | En;
data_t[3] = data_l | LCD_BACKLIGHT;
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD,(uint8_t *) data_t, 4, 100);
}

void MTxxSx_WriteData (char data)
{
char data_u, data_l;
uint8_t data_t[4];

data_u = (data&0xf0);
data_l = ((data<<4)&0xf0);

data_t[0] = data_u | En | Rs;
data_t[1] = data_u | Rs;
data_t[2] = data_l | En | Rs;
data_t[3] = data_l | Rs;
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD,(uint8_t *) data_t, 4, 100);
}

void MTxxSx_init(void)
{
HAL_GPIO_WritePin(LCD_POWER_GPIO_Port, LCD_POWER_Pin, GPIO_PIN_SET);
HAL_Delay(1500);
HAL_GPIO_WritePin(LCD_POWER_GPIO_Port, LCD_POWER_Pin, GPIO_PIN_RESET);
HAL_Delay(100);

HAL_Delay(100); // wait for >40ms
MTxxSx_WriteCmd (0x30);
HAL_Delay(50);
MTxxSx_WriteCmd (0x30);
HAL_Delay(50);
MTxxSx_WriteCmd (0x30);
HAL_Delay(50);

MTxxSx_WriteCmd (0x28);
HAL_Delay(50);
MTxxSx_WriteCmd (0x08); //Display on/off control --> D=0,C=0, B=0 ---> display off
HAL_Delay(50);
MTxxSx_WriteCmd (0x01); // clear display
HAL_Delay(50);
MTxxSx_WriteCmd (0x06); //Entry mode set --> I/D = 1 (increment cursor) & S = 0 (no shift)
HAL_Delay(50);

MTxxSx_WriteCmd (0x0F);
HAL_Delay(50);
MTxxSx_WriteCmd (0x01);
HAL_Delay(50);
}


После строки MTxxSx_WriteCmd (0x0F); должен появиться мигающий курсор, а после MTxxSx_WriteCmd (0x01); дисплей должен очиститься и курсор должен оказаться в нулевой позиции, но на дисплее ничего не появляется. Если отправить большое количество данных, то на экране появляются спонтанные символы, а если отправлять несколько команд, то отрабатываются спонтанные команды.
По шине I2C проблем нет, так как младшие 4 бита передаются правильно (LCD_BACKLIGHT как и должно быть управляет подсветкой дисплея, En и Rs отрабатываются как надо).

Имя Для добавления сообщений Вы должны зарегистрироваться или авторизоваться Цитировать Получить ссылку на сообщение

Петухов_Дмитрий
Пользователи

Сообщений: 1329
Регистрация: 25.11.2009

У Вас неправильная процедура инициализации, первые 3 команды 0x30 надо подавать в 8-ми битном режиме, с одним импульсом Е и паузой не менее 40мкс между ними. А потом ещё так же подать команду 0x20, которой у вас вообще нет. И только после этого можно переходить к подаче команд настройки в обычном 4-х битном режиме (с команды 0x28).
Скорее всего у вас индикатор остаётся в 8-ми битном режиме и потому принимает вместо нормальных кодов всякую чушь (вместо байта 0xAB принимает два байта 0xAF и 0xBF).
Правильная инициализация примерно такая (до команд настройки в обычном режиме начиная с 0x28):

Код:

uint8_t data_t[2];

data_t[0] = 0x00 | LCD_BACKLIGHT;
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 1, 100);//установка управляющих битов индикатора в 0

HAL_GPIO_WritePin(LCD_POWER_GPIO_Port, LCD_POWER_Pin, GPIO_PIN_SET);
HAL_Delay(1500);
HAL_GPIO_WritePin(LCD_POWER_GPIO_Port, LCD_POWER_Pin, GPIO_PIN_RESET);

HAL_Delay(100); // wait for >40ms
data_t[0] = 0x30 | LCD_BACKLIGHT | En;
data_t[1] = 0x30 | LCD_BACKLIGHT;
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(2); // wait for >40mcs
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(2); // wait for >40mcs
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(2); // wait for >40mcs
data_t[0] = 0x20 | LCD_BACKLIGHT | En;
data_t[1] = 0x20 | LCD_BACKLIGHT;
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(2); // wait for >40mcs

И ещё не забудьте что после команды 0x01 нужна задержка не менее 2мс, а после всех остальных команд и данных не менее 40мкс (и её проще добавить сразу в процедуры MTxxSx_WriteXXXX() если I2C протокол сам не гарантирует её наличие).
Подавать подряд команды 0x08 и 0x0F смысла мало, достаточно лишь второй (первая будет работать лишь до получения второй, а это доли секунды).

И ещё. Лучше бы сделать массив из 5-ти байтов, и в нулевой байт класть данные/команду с правильными битами RS и RW и с нулевым E так как иначе может не выдерживаться минимальное время tAS (предустановки этих битов перед фронтом E).

Имя Для добавления сообщений Вы должны зарегистрироваться или авторизоваться Цитировать Получить ссылку на сообщение

Петухов_Дмитрий
Пользователи

Сообщений: 1329
Регистрация: 25.11.2009

a13428711
Пользователи

Сообщений: 7
Регистрация: 21.07.2020

Благодарю за ответ. Обязательно проверю.
Когда не получилось по I2C, то решил попробовать поработать с восьмибитной шиной напрямую, чтоб исключить все промежуточные звенья. Тоже ничего не вышло. Прикладываю скрин с лог анализатора (каналы отмеченные как NONE подключены к D0-D3 соответственно, оставляли исключительно для проверки синхронности двух Логов, поэтому на них можете не обращать внимание). Оба лога записаны сразу после подачи питания на дисплей. Питание отключается на 1500мс через реле, так что утечек быть не может.
После всего этого дисплей по прежнему пустой.

Имя Для добавления сообщений Вы должны зарегистрироваться или авторизоваться Цитировать Получить ссылку на сообщение

a13428711
Пользователи

Сообщений: 7
Регистрация: 21.07.2020

Петухов_Дмитрий
Пользователи

Сообщений: 1329
Регистрация: 25.11.2009

ОК, я так понимаю Вы дважды записали по 8 каналов чтобы увидеть все 8 бит шины данных и сигналы RS и RW? Хорошо, давайте посмотрим что за команды Вы выдали индикатору: 0x30, 0x30, 0x30, 0x38, 0x08, 0x01, 0x06, 0x01, дальше пошли какие-то данные, команд больше нет. И что тут видим: инициализация 8-ми битного режима правильная, потом индикатор и курсор вЫключаются (командой 0x08), потом команда очистки памяти. Ну и что Вы хотите увидеть на выключенном индикаторе?! Выключенный индикатор не отображает содержимое памяти на ЖК стекле.
Замените команду 0x08 на 0x0F (включение индикатора и курсора) и уберите одну из 0x01 (она очевидно лишняя, хотя ничему и не мешает), всё должно заработать.

Потом можете перейти в 4-х битный режим, для него инициализация должна быть следующей: 0x30, 0x30, 0x30, 0x20, эти все команды передавать как 8-ми битные как и раньше, одним импульсом E с паузой между ними не менее 40мкс, младшие 4 бита могут быть любыми. Дальше все команды и данные передавать двумя полубайтами: 0x28, 0x0F, 0x06, 0x01 (эту подавать при желании очистить индикатор, после неё пауза на менее 2мс), дальше можно слать символы.

Имя Для добавления сообщений Вы должны зарегистрироваться или авторизоваться Цитировать Получить ссылку на сообщение

a13428711
Пользователи

Сообщений: 7
Регистрация: 21.07.2020

Добрый день! На данный момент ситуация следующая.
Из 10-ти заказанных дисплеев 7 работают нормально (отображаются сиволы, работает управление подсветкой, курсором и т.п.), а 3 не инициализируются (подсветка горит, но при любых действиях дисплей чист). Тестировали 3-мя несвязанными библиотеками: одну писал я, вторую другой программист, третья LiquidCryistal для платформы ардуино (взята с Гитхаба без внесения изменения, за исключением указания адреса шины I2C).
Мой код инициализации:

Код:

void MTxxSx_WriteCmd(char cmd)
{

char data_u, data_l;
uint8_t data_t[4];

data_u = (cmd&0xf0);
data_l = ((cmd<<4)&0xf0);

data_t[0] = data_u | LCD_BACKLIGHT | En; //|0x0C; //en=1, rs=0
data_t[1] = data_u | LCD_BACKLIGHT; //|0x08; //en=0, rs=0
data_t[2] = data_l | LCD_BACKLIGHT | En; //|0x0C; //en=1, rs=0
data_t[3] = data_l | LCD_BACKLIGHT; //|0x08; //en=0, rs=0
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD,(uint8_t *) data_t, 4, 100);
}

void MTxxSx_start_init(void)
{
uint8_t data_t[2];

data_t[0] = 0x00 | LCD_BACKLIGHT;
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 1, 100);//установка управляющих битов индикатора в 0

//HAL_GPIO_WritePin(LCD_POWER_GPIO_Port, LCD_POWER_Pin, GPIO_PIN_SET);
//HAL_Delay(1500);
//HAL_GPIO_WritePin(LCD_POWER_GPIO_Port, LCD_POWER_Pin, GPIO_PIN_RESET);

HAL_Delay(5); // wait for >40ms
data_t[0] = 0x30 | LCD_BACKLIGHT | En;
data_t[1] = 0x30 | LCD_BACKLIGHT;
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(1); // wait for >40mcs
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(1); // wait for >40mcs
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(1); // wait for >40mcs
data_t[0] = 0x20 | LCD_BACKLIGHT | En;
data_t[1] = 0x20 | LCD_BACKLIGHT;
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(1); // wait for >40mcs

MTxxSx_WriteCmd ( LCD_FUNCTIONSET | LCD_4BITMODE | LCD_2LINE | LCD_5x10DOTS | LCD_PAGE2);
HAL_Delay(1);
MTxxSx_WriteCmd (0x08); //Display on/off control --> D=0,C=0, B=0 ---> display off
HAL_Delay(1);
MTxxSx_WriteCmd (0x01); // clear display
HAL_Delay(2);
MTxxSx_WriteCmd (0x06); //Entry mode set --> I/D = 1 (increment cursor) & S = 0 (no shift)
HAL_Delay(1);

MTxxSx_WriteCmd ( LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSORON | LCD_BLINKON);
HAL_Delay(1);
MTxxSx_WriteCmd (0x01);
HAL_Delay(2);
}


void MTxxSx_WriteData (char data)
{
char data_u, data_l;
uint8_t data_t[4];
data_u = (data&0xf0);
data_l = ((data<<4)&0xf0);

data_t[0] = data_u | LCD_BACKLIGHT | En | Rs; //|0x0D;// | 0x08; //en=1, rs=0
data_t[1] = data_u | LCD_BACKLIGHT | Rs; //|0x09;// | 0x08; //en=0, rs=0
data_t[2] = data_l | LCD_BACKLIGHT | En | Rs; //|0x0D;// | 0x08; //en=1, rs=0
data_t[3] = data_l | LCD_BACKLIGHT | Rs; //|0x09;// | 0x08; //en=0, rs=0
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD,(uint8_t *) data_t, 4, 100);
}


В чем может быть проблема?

Имя Для добавления сообщений Вы должны зарегистрироваться или авторизоваться Цитировать Получить ссылку на сообщение

a13428711
Пользователи

Сообщений: 7
Регистрация: 21.07.2020

Код:

#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80

// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00

// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00

// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00

// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00
#define LCD_PAGE1 0x00
#define LCD_PAGE2 0x02

// flags for backlight control
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00

#define En 0x04 // Enable bit
#define Rw 0x02 // Read/Write bit
#define Rs 0x01 // Register select bit

Имя Для добавления сообщений Вы должны зарегистрироваться или авторизоваться Цитировать Получить ссылку на сообщение

Петухов_Дмитрий
Пользователи

Сообщений: 1329
Регистрация: 25.11.2009

В этом коде выше в инициализации ошибочно устанавливается флаг LCD_5x10DOTS вместо LCD_5x8DOTS.

Кроме того, я уже говорил, сигнал RS (и RW) надо выставлять ДО фронта E=1, минимально допустимое время tAS заметно больше нуля, Вы же выставляете одновременно (а реально они могут появиться и в обратном порядке из-за разброса параметров входов-выходов и паразитных ёмкостей). Пока он не меняется всё будет работать (как в инициализации), но при переходе от команд к данным и обратно могут быть глюки. Даже как полечить предлагал: увеличить массив до 5 байтов и первым передавать значение (data_u | LCD_BACKLIGHT | Rs) для данных или (data_u | LCD_BACKLIGHT) для команд.
Именно это и может вызывать глюки, в том числе и "плавающие", в 3 из 10 случаев.

В остальном ошибок не вижу. Дважды подаваемая команда 0x01 не ошибка, просто излишество. Как и сначала выключение индикатора командой 0x08, а потом почти сразу его включение (достаточно лишь второй).

PS. Правильность времён в HAL_Delay() не проверял, это под Вашу ответственность.

Имя Для добавления сообщений Вы должны зарегистрироваться или авторизоваться Цитировать Получить ссылку на сообщение

a13428711
Пользователи

Сообщений: 7
Регистрация: 21.07.2020

LCD_5x10DOTS ошибочно попала (тестировал возможности дисплея).
Не уверен, что правильно понял финт с массивом. Реализовал как в приложенном коде. Результат тот же - 3 из 7 не работают.
HAL_Delay() - это функция официальной библиотеки STM. Используем регулярно, дефектов не замечено.

Код:

#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80

// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00

// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00

// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00

// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00
#define LCD_PAGE1 0x00
#define LCD_PAGE2 0x02

// flags for backlight control
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00

#define En 0x04 // Enable bit
#define Rw 0x02 // Read/Write bit
#define Rs 0x01 // Register select bit


void MTxxSx_WriteCmd(char cmd)
{
char data_u, data_l;
uint8_t data_t[5];

data_u = (cmd&0xf0);
data_l = ((cmd<<4)&0xf0);

data_t[0] = data_u | LCD_BACKLIGHT; //|0x08; //en=0, rs=0
data_t[1] = data_u | LCD_BACKLIGHT | En; //|0x0C; //en=1, rs=0
data_t[2] = data_u | LCD_BACKLIGHT; //|0x08; //en=0, rs=0
data_t[3] = data_l | LCD_BACKLIGHT | En; //|0x0C; //en=1, rs=0
data_t[4] = data_l | LCD_BACKLIGHT; //|0x08; //en=0, rs=0
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD,(uint8_t *) data_t, 5, 100);
HAL_Delay(2);
}

void MTxxSx_start_init(void)
{
uint8_t data_t[2];

data_t[0] = 0x00 | LCD_BACKLIGHT;
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 1, 100);
HAL_Delay(5); // wait for >40ms
data_t[0] = 0x30 | LCD_BACKLIGHT | En;
data_t[1] = 0x30 | LCD_BACKLIGHT;
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(1); // wait for >40mcs
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(1); // wait for >40mcs
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(1); // wait for >40mcs
data_t[0] = 0x20 | LCD_BACKLIGHT | En;
data_t[1] = 0x20 | LCD_BACKLIGHT;
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(1); // wait for >40mcs

MTxxSx_WriteCmd ( LCD_FUNCTIONSET | LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS | LCD_PAGE2);
HAL_Delay(1);
MTxxSx_WriteCmd (0x01); // clear display
HAL_Delay(2);
MTxxSx_WriteCmd (0x06); //Entry mode set --> I/D = 1 (increment cursor) & S = 0 (no shift)
HAL_Delay(1);

MTxxSx_WriteCmd ( LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSORON | LCD_BLINKON);
HAL_Delay(2);
}


void MTxxSx_WriteData (char data)
{
char data_u, data_l;
uint8_t data_t[5];
data_u = (data&0xf0);
data_l = ((data<<4)&0xf0);

data_t[0] = data_u | LCD_BACKLIGHT | Rs; //|0x09;// | 0x08; //en=0, rs=0
data_t[1] = data_u | LCD_BACKLIGHT | En | Rs; //|0x0D;// | 0x08; //en=1, rs=0
data_t[2] = data_u | LCD_BACKLIGHT | Rs; //|0x09;// | 0x08; //en=0, rs=0
data_t[3] = data_l | LCD_BACKLIGHT | En | Rs; //|0x0D;// | 0x08; //en=1, rs=0
data_t[4] = data_l | LCD_BACKLIGHT | Rs; //|0x09;// | 0x08; //en=0, rs=0
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD,(uint8_t *) data_t, 5, 100);
HAL_Delay(2);
}


void MTxxSx_init(void)
{
HAL_Delay(100);

MTxxSx_start_init();

MTxxSx_WriteData('K');
HAL_Delay(1);
MTxxSx_WriteData('i');
HAL_Delay(1);
MTxxSx_WriteData('l');
HAL_Delay(1);
MTxxSx_WriteData('l');
HAL_Delay(1);
MTxxSx_WriteData(' ');
HAL_Delay(1);
MTxxSx_WriteData('m');
HAL_Delay(1);
MTxxSx_WriteData('e');
HAL_Delay(1);
MTxxSx_WriteData('!');
HAL_Delay(1);

MTxxSx_WriteCmd (0xC0);
HAL_Delay(1);

MTxxSx_WriteData('У');
HAL_Delay(1);
MTxxSx_WriteData('б');
HAL_Delay(1);
MTxxSx_WriteData('е');
HAL_Delay(1);
MTxxSx_WriteData('й');
HAL_Delay(1);
MTxxSx_WriteData('т');
HAL_Delay(1);
MTxxSx_WriteData('е');
HAL_Delay(1);
MTxxSx_WriteData(' ');
HAL_Delay(1);
MTxxSx_WriteData('м');
HAL_Delay(1);
MTxxSx_WriteData('е');
HAL_Delay(1);
MTxxSx_WriteData('н');
HAL_Delay(1);
MTxxSx_WriteData('я');
HAL_Delay(1);
MTxxSx_WriteData('!');
HAL_Delay(1);
}

Имя Для добавления сообщений Вы должны зарегистрироваться или авторизоваться Цитировать Получить ссылку на сообщение

Петухов_Дмитрий
Пользователи

Сообщений: 1329
Регистрация: 25.11.2009

С массивом поняли правильно.
В MTxxSx_init() задержки не нужны, они есть в MTxxSx_WriteCmd() и MTxxSx_WriteData().
Больше я не вижу ошибок. Единственным местом в программе где возможны ошибки осталось выдержка времён HAL_Delay(). Ну и выбор скорости I2C конечно.
И кстати, даже на форуме ST пишут что HAL_Delay(1) может выдать любую задержку от 0мс до 1мс, так что такой вызов вовсе не гарантирует задержки в 1мс. Вызов HAL_Delay(2) гарантирует задержку от 1мс до 2мс. И так далее. Так что ваши времена HAL_Delay(1) везде неправильные! А уж вызов HAL_Delay(5) для задержки в 40мс вообще извините бред. Замените везде HAL_Delay(1) на HAL_Delay(2), HAL_Delay(2) после команды 0x01 на HAL_Delay(3) (гарантированно не менее 2мс), а HAL_Delay(5) на HAL_Delay(50) (с запасом), раз уж нет задержки на 40мкс.
Хотя по идее HAL_Delay(1) (задержка на 40мкс) вообще не нужна, 40мкс это передача 4 битов по I2C, т.е. передача второго (и четвёртого) байта из массива гарантированно сделает задержку не менее 80мкс между импульсами E. Если не увеличивать скорость I2C.

Имя Для добавления сообщений Вы должны зарегистрироваться или авторизоваться Цитировать Получить ссылку на сообщение

a13428711
Пользователи

Сообщений: 7
Регистрация: 21.07.2020

Исправил задержки. Результат прежний.
Скорость пробовал и 100кГц и 1кГц - изменений кроме скорости прорисовки на рабочих дисплеях нет.

Код:
void MTxxSx_WriteCmd(char cmd)
{

char data_u, data_l;
uint8_t data_t[5];

data_u = (cmd&0xf0);
data_l = ((cmd<<4)&0xf0);

data_t[0] = data_u | LCD_BACKLIGHT; //|0x08; //en=0, rs=0
data_t[1] = data_u | LCD_BACKLIGHT | En; //|0x0C; //en=1, rs=0
data_t[2] = data_u | LCD_BACKLIGHT; //|0x08; //en=0, rs=0
data_t[3] = data_l | LCD_BACKLIGHT | En; //|0x0C; //en=1, rs=0
data_t[4] = data_l | LCD_BACKLIGHT; //|0x08; //en=0, rs=0
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD,(uint8_t *) data_t, 5, 100);
HAL_Delay(2);
}

void MTxxSx_start_init(void)
{
uint8_t data_t[2];

data_t[0] = 0x00 | LCD_BACKLIGHT;
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 1, 100);//установка управляющих битов индикатора в 0

HAL_Delay(50); // wait for >40ms
data_t[0] = 0x30 | LCD_BACKLIGHT | En;
data_t[1] = 0x30 | LCD_BACKLIGHT;
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(2); // wait for >40mcs
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(2); // wait for >40mcs
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(2); // wait for >40mcs
data_t[0] = 0x20 | LCD_BACKLIGHT | En;
data_t[1] = 0x20 | LCD_BACKLIGHT;
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) data_t, 2, 100);
HAL_Delay(2); // wait for >40mcs

MTxxSx_WriteCmd ( LCD_FUNCTIONSET | LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS | LCD_PAGE2);
HAL_Delay(2);
MTxxSx_WriteCmd (0x01); // clear display
HAL_Delay(5);
MTxxSx_WriteCmd (0x06); //Entry mode set --> I/D = 1 (increment cursor) & S = 0 (no shift)
HAL_Delay(2);

MTxxSx_WriteCmd ( LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSORON | LCD_BLINKON);
HAL_Delay(5);
}


void MTxxSx_WriteData (char data)
{
char data_u, data_l;
uint8_t data_t[5];
data_u = (data&0xf0);
data_l = ((data<<4)&0xf0);

data_t[0] = data_u | LCD_BACKLIGHT | Rs; //|0x09;// | 0x08; //en=0, rs=0
data_t[1] = data_u | LCD_BACKLIGHT | En | Rs; //|0x0D;// | 0x08; //en=1, rs=0
data_t[2] = data_u | LCD_BACKLIGHT | Rs; //|0x09;// | 0x08; //en=0, rs=0
data_t[3] = data_l | LCD_BACKLIGHT | En | Rs; //|0x0D;// | 0x08; //en=1, rs=0
data_t[4] = data_l | LCD_BACKLIGHT | Rs; //|0x09;// | 0x08; //en=0, rs=0
HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD,(uint8_t *) data_t, 5, 100);
HAL_Delay(2);
}


void MTxxSx_init(void)
{
HAL_Delay(100);

MTxxSx_start_init();
MTxxSx_WriteData('K');
MTxxSx_WriteData('i');
MTxxSx_WriteData('l');
MTxxSx_WriteData('l');
MTxxSx_WriteData(' ');
MTxxSx_WriteData('m');
MTxxSx_WriteData('e');
MTxxSx_WriteData('!');

MTxxSx_WriteCmd (0xC0);

MTxxSx_WriteData('У');
MTxxSx_WriteData('б');
MTxxSx_WriteData('е');
MTxxSx_WriteData('й');
MTxxSx_WriteData('т');
MTxxSx_WriteData('е');
MTxxSx_WriteData(' ');
MTxxSx_WriteData('м');
MTxxSx_WriteData('е');
MTxxSx_WriteData('н');
MTxxSx_WriteData('я');
MTxxSx_WriteData('!');
}

Имя Для добавления сообщений Вы должны зарегистрироваться или авторизоваться Цитировать Получить ссылку на сообщение

Петухов_Дмитрий
Пользователи

Сообщений: 1329
Регистрация: 25.11.2009

Тогда я не знаю в чём дело.
Или взгляд замылился или ошибок в программе больше нет.
Неплохо бы в конце MTxxSx_start_init() или сразу после её вызова из MTxxSx_init() выдать команду 0x80 чтобы последующие байты данных пошли в DDRAM, но на надпись во второй строке это не повлияет, там команда 0xC0 есть.
Думаю проблемы в аппаратной части. Включая и возможность неисправных индикаторов (несмотря на 100% ОТК на заводе).

Можно попробовать подключить неисправный индикатор к исправному по параллельной шине, оставив I2C первого неподключенной. Тогда управляя исправным будете одновременно управлять и неисправным и они должны вести себя одинаково. Насколько помню I2C преобразователь без команд записи нулей держит выводы в слабой подтяжке к питанию и фактически не мешает параллельному обмену (ноль одного преобразователя легко перетянет подтяжку к питанию другого). Если два индикатора, соединённые параллельно (выводами DBx, E, RS, RW), будут работать по разному, значит один (или оба) неисправны. Переключив шину I2C на другой индикатор можно проверить и работу обоих I2C преобразователей.
Только при переключениях не забывайте выключать питание, сброса процессора недостаточно!

Имя Для добавления сообщений Вы должны зарегистрироваться или авторизоваться Цитировать Получить ссылку на сообщение
Сейчас на форуме (гостей: 18, пользователей: 0 , из них : 0 )