Главная » Микроконтроллеры
Призовой фонд
на май 2017 г.
1. Тестер компонентов MG328
Паяльник
2. Осциллограф DSO138
Паяльник
3. Регулируемый паяльник 60 Вт
Паяльник
4. 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 Поиск в FivelВ блокнот
LCD-дисплейSiemens C75, ME751 Поиск в FivelВ блокнот
Стабилитрон2.9 Вольт1 Поиск в FivelВ блокнот
Добавить все

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

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

Теги:

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

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

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

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

Комментарии (6) | Я собрал (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 И Это рабочая функция?
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется сила тока?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

AVR-программатор USB ASP
AVR-программатор USB ASP
Паяльная станция Hakko 936 ELM327 OBD II — адаптер с поддержкой CAN
вверх