Инициализация знакосинтезирующего дисплея 1602 от фирмы МЭЛТ по SPI (SSP) с помощью микроконтроллера Миландр К1986ВЕ92хх
Часть 1
Описание работы дисплея МЭЛТ МТ-16S2S.
Согласно технической документации на дисплей (режим доступа https://www.melt.com.ru/docs/MT-16S2S.pdf?ysclid=m708djocbj209679056) данная серия жидкокристаллических индикаторов обладает встроенным контроллеровм управления ST7070, содержит два вида памяти, память кодов отображаемых символов и пользовательского знакогенератора. Особенностью памяти кодов отображаемых символов является то, что она двухстраничная, и символы латинского и кириллического алфавита разнесены в разные страницы, что конечно может создать ряд неудобств при программировании мультиязычного режима на дисплее.
Дисплей, согласно документации имеется возможность инициализации как по параллельной 4-х/8-ми разрядной шине данных, так и по последовательному однонаправленному синхронному интерфейсу SPI.
Статья как подключить данный дисплей к микроконтроллеру имеется на ресурсе habr.com (режим доступа https://habr.com/ru/articles/397977/), все желающие могут с ней ознакомится. Однако, в настоящей статье мы разберем детали, которые не были освящены в вышеупомянутых информационных ресурсах.
Схема подключения ЖК-индикатора МЭЛТ МТ-16S2S по SPI приведена на рисунке 1.

Рисунок 1. - Схема подключения ЖК-индикатора
Опишем последовательность инциализации:
- XRES устанавливаем в Н уровень.
- Ждем не менее 40 мс.
- Устанавливаем в Н уровень CS
- Производим инциализацию SPI на стороне микроконтроллера.
- Готовим к инициализации дисплей по SPI. (CS (H), приемник выключен CS (L) приемник готов)
- Передаем команду 0х38 // функция установки 0b00111000 согласно рисунку 10 официальной документации на дисплей, раздел "Последовательный интерфейс".
- Производим очистку дисплея передав данные 0х01
- Перемещаем курсор в начало командой 0х02
- Производим включение дисплея
- Завершаем настройки командой 0х38
Далее формируем блок передачи символов.
Часть 2
Программный код на языке Си для настройки функции инициализации дисплея по SPI
Рассмотрим код для формирования команды передачи данных на дисплей с микроконтроллера К1986ВЕ92FI, основная отладочная плата микроконтроллера будет использована MDR32 MILUINO для К1986ВЕ92FI ДФТВ.434519.003 в качестве платы дисплея используем MILUINO SHIELD LCD_16x2_MELT ДФТВ.467988.004.
Код инициализации SSP интерфейса на языке С:
#include "MDR32Fx.h" // Device header
#include "MDR32F9Qx_rst_clk.h" // Keil::Drivers:RST_CLK
#include "MDR32F9Qx_port.h" // Keil::Drivers:PORT
#include "MDR32F9Qx_ssp.h" // Keil::Drivers:SSP
#define CS_Port MDR_PORTF
#define CS_Bit PORT_Pin_2
#define SPI1_SCK_Pin PORT_Pin_1
#define SPI1_MISO_Pin PORT_Pin_3
#define SPI1_MOSI_Pin PORT_Pin_0
#define SPI1_HFSS_Pin PORT_Pin_2
void SSP1_Init(void)
{
RST_CLK_PCLKcmd((RST_CLK_PCLK_RST_CLK | RST_CLK_PCLK_SSP1 | RST_CLK_PCLK_PORTF), ENABLE);
SSP_InitTypeDef sSSP;
PORT_InitTypeDef PORT_InitStructure;
/* Конфигурируем пины SSP1: FSS, CLK, RXD, TXD */
PORT_InitStructure.PORT_Pin = SPI1_MISO_Pin;
PORT_InitStructure.PORT_OE = PORT_OE_IN;
PORT_InitStructure.PORT_FUNC = PORT_FUNC_ALTER;
PORT_InitStructure.PORT_MODE = PORT_MODE_DIGITAL;
PORT_InitStructure.PORT_SPEED = PORT_SPEED_FAST;
PORT_Init(MDR_PORTF, &PORT_InitStructure);
PORT_InitStructure.PORT_Pin = (SPI1_MOSI_Pin | SPI1_SCK_Pin); // FSS - SOFT
PORT_InitStructure.PORT_OE = PORT_OE_OUT;
PORT_Init(MDR_PORTF, &PORT_InitStructure);
SSP_DeInit(MDR_SSP1);
SSP_BRGInit(MDR_SSP1, SSP_HCLKdiv16);
/* Конфигурация SSP1 в режиме MASTER 8-битный режим */
SSP_StructInit (&sSSP);
sSSP.SSP_SCR = 0x10;
sSSP.SSP_CPSDVSR = 8;
sSSP.SSP_Mode = SSP_ModeMaster;
sSSP.SSP_WordLength = SSP_WordLength8b;
sSSP.SSP_SPH = SSP_SPH_2Edge;
sSSP.SSP_SPO = SSP_SPO_High;
sSSP.SSP_FRF = SSP_FRF_SPI_Motorola;
sSSP.SSP_HardwareFlowControl = SSP_HardwareFlowControl_SSE;
SSP_Init (MDR_SSP1, &sSSP);
/* Запускаем SSP1 */
SSP_Cmd(MDR_SSP1, ENABLE);
}Функции передачи и приема данных выглядит так:
uint16_t ReceiveTransmitSPI(uint8_t data)
{
while (SSP_GetFlagStatus(MDR_SSP1, SSP_FLAG_TFE) == RESET) {}
/* Передача данных по SPI1 */
SSP_SendData(MDR_SSP1, data);
/* Ждем пока SPI1 примет данные */
while (SSP_GetFlagStatus(MDR_SSP1, SSP_FLAG_RNE) == RESET) {}
/* Считываем принятые данные по SPI1 */
return SSP_ReceiveData(MDR_SSP1);
}Функция инициализации ЖКИ МЭЛТ МТ-16S2S
#define LCD_cmd_CUR_OFF 0x8000
#define LCD_cmd_CUR_ON 0x4000
#define LCD_cmd_DISP_OFF 0x2000
#define LCD_cmd_DISP_ON 0x1000
#define LCD_cmd_SetPage_0 0x0800
#define LCD_cmd_SetPage_1 0x0400
#define LCD_cmd_CUR_SHIFT 0x0200
#define LCD_cmd_DISP_SHIFT 0x0100
#define LCD_cmd_SHIFT_LEFT 0x0080
#define LCD_cmd_SHIFT_RIGHT 0x0040
#define LCD_cmd_Home 0x0002
#define LCD_cmd_ClrScr 0x0001
#define FIRST_LINE 0x0000
#define SECOND_LINE 0x0001
void LCD_Cmd(uint16_t cmd)
{
uint8_t toSend ;
toSend = 0x08;
CS_RESET;
DELAY_US(90);
ReceiveTransmitSPI(0x38);
DELAY_US(90);
//Очистка дисплея
if ((cmd & LCD_cmd_ClrScr) > 0)
{
ReceiveTransmitSPI(0x01);
DELAY_US(90);
}
//Курсор в начало
if ((cmd&LCD_cmd_Home) > 0)
{
ReceiveTransmitSPI(0x02);
DELAY_US(90);
}
// Включение
if (cmd > 0x3ff)
{
toSend = toSend+((cmd & LCD_cmd_CUR_ON) >> 13) + // курсор
((cmd & LCD_cmd_DISP_ON) >> 10) + // дисплей
((cmd & LCD_cmd_SetPage_1) >> 10); // кодовая страница 1
ReceiveTransmitSPI(toSend);
DELAY_US(90);
}
cmd = cmd & 0x3ff;
toSend = 0x10;
// Сдвиг
if (cmd > 0x3f)
{
toSend += ((cmd & LCD_cmd_DISP_SHIFT) >> 5)+ // Сдвиг дисплея
((cmd & LCD_cmd_SHIFT_RIGHT) >> 4); // вправо
ReceiveTransmitSPI(toSend);
DELAY_US(90);
};
ReceiveTransmitSPI(0x38);
DELAY_US(90);
CS_SET;
}Функция вывода текста на экран
void LCD_print_text(uint8_t line, char* text, uint8_t cell)
{
uint8_t nBytes;
if (!text) return;
nBytes = strlen(text);
if (nBytes>80) return;
CS_RESET;
DELAY_US(90);
if(line == FIRST_LINE)
{
ReceiveTransmitSPI(0x80 + cell);
}
else if (line == SECOND_LINE)
{
ReceiveTransmitSPI(0xC0 + cell);
}
DELAY_US(90);
ReceiveTransmitSPI(0x3c);
DELAY_US(90);
ReceiveTransmitSPI(0x80 + nBytes - 1);
DELAY_US(90);
for(uint8_t j=0; j < nBytes; j++)
{
ReceiveTransmitSPI(text[j]);
DELAY_US(90);
};
ReceiveTransmitSPI(0x38);
DELAY_US(90);
CS_SET;
}Таким образом мы настроили все функции передачи текстовых данных на латинице на знакосинтезирующий дисплей МЭЛТ от микроконтроллера фирмы Миландр
