Реклама ⓘ
Главная » Микроконтроллеры
Призовой фонд
на апрель 2024 г.
1. 100 руб.
От пользователей

Реклама ⓘ

Подключаем LCD от Siemens C75 и ME75 к STM32

В Siemens C75 и ME75 применялись два типа дисплеев, один с зеленым текстолитом и названием LPH9157-2, а другой с темно-желтым текстолитом. Так вот, у меня дисплей с зеленым текстолитом его и будем использовать.

Итак, фото подключаемого дисплея.

Имя дисплея LPH9157-2

LPH9157-2

Подключать будем к STM32F103C8. На мой взгляд, отличный камень для подобных опытов. В сети есть статья Особенности работы с дисплеем LPH9157-2 автора Igoryosha, эта статья сделана на основе микроконтроллеров AVR, автор написал там библиотеку для работы с дисплеем, но данное решение мне не подходило из-за низкой скорости работы микроконтроллеров AVR. В итоге я решил портировать данную библиотеку на STM32, тем самым повысив скорость работы с дисплеем.  

В чем же заключалось портирование?

Для начала я переписал библиотеку с использованием программного SPI. Потом переделал с использованием аппаратного SPI.

Рассмотрим порт с программным SPI:

Создаем новый проект в среде разработки CoIDE. Можно конечно использовать и другие среды разработки для STM32, но при их использовании могут быть проблемы при компиляции данного кода. Подключаем заголовочные файлы

#include 
#include 
#include
#include
#include "stm32f10x.h"
#include "stm32f10x_conf.h"

 Далее конфигурируем порт, к которому будет подключен дисплей

//#define LCD_CS 		  Выбор чипа
//#define LCD_RESET 	 Сброс
//#define LCD_RS 		  CD - тип передаваемых данных
//#define LCD_CLK 	 Синхронизация
//#define LCD_DATA         Данные

Тут записали в пины порта логический ноль
#define LCD_CS0 		 GPIOB->BRR  =  1<<0;
#define LCD_RESET0               GPIOB->BRR  =  1<<1;
#define LCD_RS0 		 GPIOB->BRR  =  1<<12;
#define LCD_CLK0 	         GPIOB->BRR  =  1<<13;
#define LCD_DATA0                GPIOB->BRR  =  1<<14;

А тут записали в пины порта логическую единицу
#define LCD_CS1 		GPIOB->BSRR  =  1<<0;
#define LCD_RESET1 	        GPIOB->BSRR  =  1<<1;
#define LCD_RS1 		GPIOB->BSRR  =  1<<12;
#define LCD_CLK1 	        GPIOB->BSRR  =  1<<13;
#define LCD_DATA1               GPIOB->BSRR  =  1<<14;

Ножки для подключения дисплея можно использовать с любых портов.

Далее идут константы цветов, данных и команд, все как у автора.

Теперь конфигурируем периферию:

Таймер для задержки

RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
TIM2->PSC     = 8000-1;
TIM2->CR1     = TIM_CR1_OPM; 

Порт для дисплея

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //включить тактирование порта
GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_12| GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP; //выход общего назначения симметричный
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//максимальная частота выходного сигнала
GPIO_Init(GPIOB, &GPIO_InitStructure);//вызов функции инициализации  

Перепишем теперь функции передачи команд/данных и инициализации с учетом выше заданных констант:

Функции передачи команд/данных: 

void Send_to_lcd (unsigned char RS, unsigned char data)
 {
  LCD_CLK0;
  LCD_DATA0;
  if ((RS_old != RS) || (!RS_old && !RS)) //проверяем старое значение RS (если поступают одни команды то дергаем CS)
  {
   LCD_CS1;
   if(RS) LCD_RS1
   else LCD_RS0;
   LCD_CS0;
  }
  LCD_DATA0;
  if ((data & 128) == 128) LCD_DATA1;
  LCD_CLK1;
  LCD_CLK0;
  LCD_DATA0;
  if ((data & 64) == 64)  LCD_DATA1;
  LCD_CLK1;
  LCD_CLK0;
  LCD_DATA0;
  if ((data & 32) == 32)  LCD_DATA1;
  LCD_CLK1;
  LCD_CLK0;
  LCD_DATA0;
  if ((data & 16) ==16)  LCD_DATA1;
  LCD_CLK1;
  LCD_CLK0;
  LCD_DATA0;
  if ((data & 8) == 8)  LCD_DATA1;
  LCD_CLK1;
  LCD_CLK0;
  LCD_DATA0;
  if ((data & 4) == 4)  LCD_DATA1;
  LCD_CLK1;
  LCD_CLK0;
  LCD_DATA0;
  if ((data & 2) == 2)  LCD_DATA1;
  LCD_CLK1;
  LCD_CLK0;
  LCD_DATA0;
  if ((data & 1) == 1)  LCD_DATA1;
  LCD_CLK1;
  LCD_CLK0;
  RS_old=RS;  //запоминаю значение RS
  LCD_DATA0;
 }

Функция инициализации:

void LCD_init(void)
 {
  LCD_RESET0;
  delay_ms(1000);
  LCD_RESET1;
  delay_ms(1000);
  Send_to_lcd(0, 0x01); //Программный сброс
  Send_to_lcd(0, 0x36);    
  Send_to_lcd(1, 0x00);
  Send_to_lcd(0, 0x11); //Выход из спящего режима
  delay_ms(200);
  Send_to_lcd(0, 0x3a); //Установка цветовой палитры
  #ifdef _8_BIT_COLOR
  Send_to_lcd(1, 0x02); //Байт на пиксель 256 цветов
  #else
  Send_to_lcd(1, 0x05); //Два байта на пиксель 65536 цветов
  #endif
  delay_ms(200);
  Send_to_lcd(0, 0x29); //Включение дисплея
 }

В остальные функции для работы с дисплеем тоже были внесены изменения того же типа что и выше, так что здесь их рассматривать нет смысла. В принципе с программным SPI наверно все, так как основная идея порта ясна.

Теперь разберемся с аппаратным SPI.

Для работы с аппаратным SPI нужно его сконфигурировать, но об этом будет речь чуть ниже.

Здесь все также как и выше только при конфигурации порта для дисплея берем 3 ноги с порта и еще 2 с SPI.

Подключаем к проекту  

#include 

, и переходим к настройке пинов порта для дисплея.  Это оставляем как есть:

#define LCD_CS0 		      GPIOB->BRR  =  1<<0;
#define LCD_RESET0                    GPIOB->BRR  =  1<<1;
#define LCD_RS0 		      GPIOB->BRR  =  1<<12;

#define LCD_CS1 		      GPIOB->BSRR  =  1<<0;
#define LCD_RESET1 	              GPIOB->BSRR  =  1<<1;
#define LCD_RS1 		      GPIOB->BSRR  =  1<<12; 

Далее значит, настраиваем пины SPI:

RCC->APB2ENR |=  RCC_APB2ENR_AFIOEN;     //включить тактирование альтернативных функций
RCC->APB2ENR |=  RCC_APB2ENR_IOPAEN;     //включить тактирование порта А
RCC_APB2PeriphClockCmd(  RCC_APB2Periph_SPI1, ENABLE);
//вывод управления SS: выход двухтактный, общего назначения,50MHz                                        
 GPIOA->CRL   |=  GPIO_CRL_MODE4;    //
 GPIOA->CRL   &= ~GPIO_CRL_CNF4;     //
 GPIOA->BSRR   =  GPIO_BSRR_BS4;     //

 //вывод SCK: выход двухтактный, альтернативная функция, 50MHz
 GPIOA->CRL   |=  GPIO_CRL_MODE5;    //
 GPIOA->CRL   &= ~GPIO_CRL_CNF5;     //
 GPIOA->CRL   |=  GPIO_CRL_CNF5_1;   //

 //вывод MISO: вход цифровой с подтягивающим резистором, подтяжка к плюсу
 GPIOA->CRL   &= ~GPIO_CRL_MODE6;    //
 GPIOA->CRL   &= ~GPIO_CRL_CNF6;     //
 GPIOA->CRL   |=  GPIO_CRL_CNF6_1;   //
 GPIOA->BSRR   =  GPIO_BSRR_BS6;     //

 //вывод MOSI: выход двухтактный, альтернативная функция, 50MHz
 GPIOA->CRL   |=  GPIO_CRL_MODE7;    //
 GPIOA->CRL   &= ~GPIO_CRL_CNF7;     //
 GPIOA->CRL   |=  GPIO_CRL_CNF7_1;   //
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

Теперь настраиваем SPI:

     SPI_StructInit(&spi);
     spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
     spi.SPI_Mode = SPI_Mode_Master;
     spi.SPI_DataSize = SPI_DataSize_8b;
     spi.SPI_CPOL = SPI_CPOL_Low;
     spi.SPI_CPHA = SPI_CPHA_2Edge;
     spi.SPI_NSS = SPI_NSS_Soft;
     spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
     spi.SPI_FirstBit = SPI_FirstBit_MSB;
     spi.SPI_CRCPolynomial = 7;
     SPI_Init(SPI1, &spi);

Описание настроек SPI  можно глянуть в интернете, поэтому здесь приводить не буду.

Функция передачи данных по SPI:

uint8_t Send_to_lcd (uint8_t data)
       {
         SPI1->DR = data;
         while (!(SPI1->SR & SPI_SR_RXNE));
         return (SPI1->DR);
       }

Дальше используем эту функцию за место той, что была в программном SPI.

Теперь по поводу схемы:

Дисплей я подключал на прямую к портам микроконтроллера, питание дисплея 2.9вольт. Если не будет работать дисплей, замерьте напряжение после стабилитрона, оно должно быть строго 2.9 вольт. Если оно ниже, как было у меня то нужно поставить конденсатор электролитический на пару сотен мкФ (я ставил 220мкФ). Питание подсветки 12 вольт. Схему приводить нет смысла, так как у меня конкретно своя макетная плата с отладочной платой, так что разумнее  будет исходить из того что у Вас за плата с МК.

Картинка работающего дисплея:

Тестовые проекты в среде программирования CoIDE прикреплены ниже. В них портированы не все функции, которые были изначально на AVR. Если Вам понадобятся остальные функции, то Вы можете их с легкостью портировать, так как, там все просто.

Список радиоэлементов

Обозначение Тип Номинал Количество ПримечаниеМагазинМой блокнот
МК STM32
STM32F103C8
1 Поиск в магазине ОтронВ блокнот
LCD-дисплейSiemens C75, ME751 Поиск в магазине ОтронВ блокнот
Стабилитрон2.9 Вольт1 Поиск в магазине ОтронВ блокнот
Добавить все

Скачать список элементов (PDF)

Прикрепленные файлы:

Теги:

Опубликована: 29.12.2013 0 1
Я собрал 0 2
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 4.2 Проголосовало: 2 чел.

Комментарии (7) | Я собрал (0) | Подписаться

0
50mg #
Классная статья! Есть мнение, что LPH9157-2 аналогичен по способу управления дисплеям на контроллере ILI9163. У меня как раз такой имеется, однако пока не могу его инициализировать, используя этот код. А на CLK же постоянно импульсы должны быть? Что-то он в HI-Z у меня находится. Чувствую туплю где-то.
Ответить
0
50mg #
В общем загвоздка была как обычно в неправильном указании портов для вывода по невнимательности, теперь все работает.
Ответить
0
while(1) #
Дак а вы используете неизмененный код? И еще интересно бы поглядеть на дисплейчик который юзаете. Минус дисплеев от сименса в том, что у них цвета какие-то тусклые, хотя если так подумать, то для того времени норм было
Ответить
0
50mg #
Не, я поменял номера портов, но не во всех местах, как оказалось. Разрешение поменял, функцию вывода изображений чуток поменял (сначала она давала лишнее смещение по х). Пока еще не разобрался почему у меня каналы R и B перепутаны, все хочу сесть с лог.анализатором и нормально во всем разобраться, а то сейчас играюсь с этим кодом, как обезьяна с ноутбуком
Дисплейчик этот: MI0177J2T-1.
Ответить
0
50mg #
Продолжаю разбираться с этой темой, теперь уже с аппаратным spi и что-то не догоняю, а зачем эта строка в обработчике передачи команды "Send_to_lcd((cmd >> 8));" Ведь у нас команды только 8 бит. А так получается лишний пустой байт передается в каждой команде.
Ответить
0
greench #
Send_to_lcd И Это рабочая функция?
Ответить
0
Электронщик #
Тут не правильный бит регистра проверяется
while (!(SPI1->SR & SPI_SR_RXNE));
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется сила тока?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Программатор Pickit3
Программатор Pickit3
Мультиметр DT9205A Модуль радиореле на 4 канала
вверх