Подключение LCD к микроконтроллеру STM32

Обсуждаем цифровые устройства...
Ответить
isx
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

Сообщение isx »

Приветствую форумчан!
Изображение
Столкнулся с необходимостью подключить LCD с тачскрином к STM32.
Как всегда, попытки завести устройство через сторонние библиотеки ни к чему не привели. Нашел ветку на форуме http://radiokot.ru/forum/viewtopic.php?p=2564754 . Дисплей точно такой же, попробовал библиотеку, которую предложил там Mikele_P, но кроме подсветки ничего так и не увидел. Один только нюанс - я подавал вместо 3.3 вольт 3 вольта, но думаю это не столь существенно.
Интересует следующие вопросы.
1. Снег на экране должен появиться сразу после инициализации?
2. Как происходит эта самая инициализация? Дисплей инициализируется сразу после ногодрыга с RST пином, или потом нужно еще досылать какие-то команды?
3. Если нужны команды, то какие там должны быть и в каком порядке (или хотябы где это посмотреть можно, так как в даташите на контроллер моего дисплея hx8347g я такой инфы не нашел)?
Хочу хоть снег увидеть, а то так и не понятно то ли в коде проблема, то ли дисплей дохлый.... :kill:

Даташит на контроллер LCD hx8347g http://datasheet4u.com/datasheet/H/X/8/ ... x.pdf.html
Реклама
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 29
Зарегистрирован: Сб фев 06, 2016 14:26:07

Сообщение JustRom »

Проинициализировать таймер SysTick не забыли (вместе с переменной SysTimer)? Обратите внимание на функцию delay_ms.
Реклама
isx
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

Сообщение isx »

Я delay_ms сделал через delay_us.

Код: Выделить всё

void delay_ms(uint32_t N)
{
    uint16_t d = 0;
    
    while (d < N)
    {
	delay_us(750);
	d++;
    }

}
Именно с 750 мкс. отладчик показывал задержку чуть больше 1 мс.
isx
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

Сообщение isx »

Как обычно, угробил уйму времени запихиванием сторонних библиотек, но толку никакого нет. Только белый свет в тоннеле :) . Плюнул, решил делать свою библиотеку.
Для начала посмотрел как все устроено в других. Порядок получился такой:
1) Подключение.
2) Ресет.
3) Чтение ID (опционально, но мне надо знать, как мое чудовище определяется).
Собственно здесь все и повисло. Разные модели контроллеров требуют различного подхода как к ресету, так и к чтению ID.
Предполагаю, что мой hx8347G аналог ILI9325 (в ветке, которую я указывал, человек именно с его настройками запустил это чудо). Полазал по даташиту, действительно, регистр чтения ID у них одинаковый - 0x00 (у ILI9341, к примеру, 0xD3).
Вопросы:
Какой должен быть правильный порядок ресета?
Каков порядок получения ID?
Сейчас у меня такое понаписано (ОСТОРОЖНО 18+):

Код: Выделить всё

void hx8347G_Init (void)
{
	hx8347G_PINs_Command_Init();
	hx8347G_PINs_Data_Out();
	hx8347G_Reset();
	LCD_ID = hx8347G_Get_LCD_ID(0x00);
}

void hx8347G_PINs_Command_Init(void)
{
   
    GPIOA->CRH &= ~( GPIO_CRH_MODE8  // rd
                    |GPIO_CRH_MODE9  // wr
                    |GPIO_CRH_MODE10 // rs
                    |GPIO_CRH_MODE11 // cs
                    |GPIO_CRH_MODE12 // rst
                   );

    GPIOA->CRH |=  ( GPIO_CRH_MODE8  // rd
                    |GPIO_CRH_MODE9  // wr
                    |GPIO_CRH_MODE10 // rs
                    |GPIO_CRH_MODE11 // cs
                    |GPIO_CRH_MODE12 // rst
                   );
    
    GPIOA->CRH &= ~( GPIO_CRH_CNF8
                    |GPIO_CRH_CNF9
                    |GPIO_CRH_CNF10
                    |GPIO_CRH_CNF11
                    |GPIO_CRH_CNF12
                   );
}


void hx8347G_PINs_Data_Out(void)
{
    
    GPIOA->CRL &= ~( GPIO_CRL_MODE0 // D0
                    |GPIO_CRL_MODE1 // D1
                    |GPIO_CRL_MODE2 // D2
                    |GPIO_CRL_MODE3 // D3
                    |GPIO_CRL_MODE4 // D4
                    |GPIO_CRL_MODE5 // D5
                    |GPIO_CRL_MODE6 // D6
                    |GPIO_CRL_MODE7 // D7
                   );   

    GPIOA->CRL |=  ( GPIO_CRL_MODE0 // D0
                    |GPIO_CRL_MODE1 // D1
                    |GPIO_CRL_MODE2 // D2
                    |GPIO_CRL_MODE3 // D3
                    |GPIO_CRL_MODE4 // D4
                    |GPIO_CRL_MODE5 // D5
                    |GPIO_CRL_MODE6 // D6
                    |GPIO_CRL_MODE7 // D7
                   );   
    
    GPIOA->CRL &= ~( GPIO_CRL_CNF0  
                    |GPIO_CRL_CNF1
                    |GPIO_CRL_CNF2
                    |GPIO_CRL_CNF3
                    |GPIO_CRL_CNF4
                    |GPIO_CRL_CNF5
                    |GPIO_CRL_CNF6
                    |GPIO_CRL_CNF7
                   );    
                   
    GPIOA->ODR &= 0xFF00;
}



void hx8347G_PINs_Data_In(void)
{

    GPIOA->CRL &= ~( GPIO_CRL_MODE0 // D0
											|GPIO_CRL_MODE1 // D1
											|GPIO_CRL_MODE2 // D2
											|GPIO_CRL_MODE3 // D3
											|GPIO_CRL_MODE4 // D4
											|GPIO_CRL_MODE5 // D5
											|GPIO_CRL_MODE6 // D6
											|GPIO_CRL_MODE7 // D7
										 );   

    GPIOA->CRL &= ~( GPIO_CRL_CNF0  
											|GPIO_CRL_CNF1
											|GPIO_CRL_CNF2
											|GPIO_CRL_CNF3
											|GPIO_CRL_CNF4
											|GPIO_CRL_CNF5
											|GPIO_CRL_CNF6
											|GPIO_CRL_CNF7
										 );    
    
    GPIOA->CRL |= ( GPIO_CRL_CNF0_0
										 |GPIO_CRL_CNF1_0
										 |GPIO_CRL_CNF2_0
										 |GPIO_CRL_CNF3_0
										 |GPIO_CRL_CNF4_0
										 |GPIO_CRL_CNF5_0
										 |GPIO_CRL_CNF6_0
										 |GPIO_CRL_CNF7_0
										);    
      
}



void hx8347G_Reset (void)
{ 
	
	HX8347G_LCD_RESET_DISABLE;
	HX8347G_LCD_CS_DISABLE;
	HX8347G_LCD_CD_DATA;
	HX8347G_LCD_WR_DISABLE;
	HX8347G_LCD_RD_DISABLE;
	hx8347G_Send_Command(0xFF); 
	_hx8347G_Delay_ms(50);

	HX8347G_LCD_RESET_ENABLE;
	_hx8347G_Delay_ms(100);
	HX8347G_LCD_RESET_DISABLE;
	_hx8347G_Delay_ms(1000);
	
}


/////////////////////////////ОСОБО ОПАСНЫЙ КОД!!!/////////////////////////////////////
Здесь полное безобразие, так как я пытался всеми способами получить нужные данные.

uint32_t hx8347G_Get_LCD_ID (uint8_t r)
{ 
	uint32_t ID = 0;
	uint32_t x = 0;
	
	//HX8347G_LCD_CS_ENABLE;
	//HX8347G_LCD_CD_COMMAND;
	//HX8347G_LCD_RD_DISABLE;
	//HX8347G_LCD_WR_ENABLE;
	
	  HX8347G_LCD_CS_ENABLE;
    HX8347G_LCD_CD_COMMAND;
    hx8347G_PINs_Data_Out();
		_hx8347G_Delay_ms(50);
		hx8347G_Send_8bit (0x00);
		_hx8347G_Delay_ms(50);
    HX8347G_LCD_CS_DISABLE;
		
		HX8347G_LCD_CS_ENABLE;
    HX8347G_LCD_CD_DATA;
    hx8347G_PINs_Data_Out();
		_hx8347G_Delay_ms(50);
		hx8347G_Send_8bit (0x01);
		_hx8347G_Delay_ms(50);
    HX8347G_LCD_CS_DISABLE;
		
		HX8347G_LCD_CS_ENABLE;
    HX8347G_LCD_CD_COMMAND;
    hx8347G_PINs_Data_Out();
		_hx8347G_Delay_ms(50);
		hx8347G_Send_8bit (0x00);
		_hx8347G_Delay_ms(50);
    HX8347G_LCD_CS_DISABLE;
		
		
		
/*		
		
		
		hx8347G_PINs_Data_In();
		_hx8347G_Delay_ms(50);
		//1
    HX8347G_LCD_CS_ENABLE;
    HX8347G_LCD_CD_DATA;
    HX8347G_LCD_RD_ENABLE;
_hx8347G_Delay_ms(50);
    ID = HX8347G_READ_DATA;
		ID<<=8;

    HX8347G_LCD_RD_DISABLE;
    HX8347G_LCD_CS_DISABLE;
_hx8347G_Delay_ms(50);		
		//2
		HX8347G_LCD_CS_ENABLE;
    HX8347G_LCD_CD_DATA;
    HX8347G_LCD_RD_ENABLE;
_hx8347G_Delay_ms(50);
    ID += HX8347G_READ_DATA;

    HX8347G_LCD_RD_DISABLE;
    HX8347G_LCD_CS_DISABLE;
_hx8347G_Delay_ms(50);
    hx8347G_PINs_Data_Out();
		
		
*/	
	
	/*
	HX8347G_LCD_CS_ENABLE;
	HX8347G_LCD_CD_COMMAND;
	HX8347G_LCD_RD_DISABLE; 
	hx8347G_PINs_Data_Out();
	HX8347G_WR_STROBE;
	*/
	
	
	/*
	hx8347G_Send_8bit(r);
	_hx8347G_Delay_us(100);	
	hx8347G_Send_8bit(r);
	_hx8347G_Delay_us(100);
	*/
	
	
	
	hx8347G_PINs_Data_In();
	HX8347G_LCD_CD_DATA;
	_hx8347G_Delay_us(50);	
	
	
	HX8347G_LCD_RD_ENABLE;	
	_hx8347G_Delay_us(5);	
	x = HX8347G_READ_DATA;
	HX8347G_LCD_RD_DISABLE;
	ID = x;
	ID<<=8;
	
	HX8347G_LCD_RD_ENABLE;	
	_hx8347G_Delay_us(5);	
	x = HX8347G_READ_DATA;
	HX8347G_LCD_RD_DISABLE;
	ID |= x;
	ID<<=8;
	
	HX8347G_LCD_RD_ENABLE;	
	_hx8347G_Delay_us(5);	
	x = HX8347G_READ_DATA;
	HX8347G_LCD_RD_DISABLE;
	ID |= x;
	ID<<=8;
	
	HX8347G_LCD_RD_ENABLE;	
	_hx8347G_Delay_us(5);	
	x = HX8347G_READ_DATA;
	HX8347G_LCD_RD_DISABLE;
	ID |= x;
	
	if (r == 0xEF)
	{
			ID<<=8;
			HX8347G_LCD_RD_ENABLE;	
			_hx8347G_Delay_us(5);	
			x = HX8347G_READ_DATA;
			HX8347G_LCD_RD_DISABLE;
			ID |= x;
	}

	HX8347G_LCD_CS_DISABLE;
	hx8347G_PINs_Data_Out();
	_hx8347G_Delay_us(150); // Stabilization
	
	return ID;
}


Дефайны:

Код: Выделить всё


#define HX8347G_LCD_RD_ENABLE 							(GPIOA->BSRR |= GPIO_BSRR_BR8)//
#define HX8347G_LCD_RD_DISABLE 							(GPIOA->BSRR |= GPIO_BSRR_BS8) //

#define HX8347G_LCD_WR_ENABLE 							(GPIOA->BSRR |= GPIO_BSRR_BR9) //
#define HX8347G_LCD_WR_DISABLE 							(GPIOA->BSRR |= GPIO_BSRR_BS9) //

#define HX8347G_LCD_CD_COMMAND 							(GPIOA->BSRR |= GPIO_BSRR_BR10) //
#define HX8347G_LCD_CD_DATA		 							(GPIOA->BSRR |= GPIO_BSRR_BS10) //

#define HX8347G_LCD_CS_ENABLE 							(GPIOA->BSRR |= GPIO_BSRR_BR11) //
#define HX8347G_LCD_CS_DISABLE 							(GPIOA->BSRR |= GPIO_BSRR_BS11) //

#define HX8347G_LCD_RESET_ENABLE 						(GPIOA->BSRR |= GPIO_BSRR_BR12) //
#define HX8347G_LCD_RESET_DISABLE 					(GPIOA->BSRR |= GPIO_BSRR_BS12) //


#define HX8347G_SET_DATA				(GPIOA->ODR &= 0xFF00); (GPIOA->BSRR)	
#define HX8347G_READ_DATA				(GPIOA->IDR & 0xFF) 


#define HX8347G_WR_STROBE {HX8347G_LCD_WR_ENABLE; HX8347G_LCD_WR_DISABLE;}

При любом способе получения ID, в ответ мне приходят 0x75757575 либо 0x7D7D7D7D (даже если закомментировать ресет).

Нужна помощь спецов, так как мой мозг уже не тянет такой груз самостоятельно :kill: :kill: :) .

P.S. Даташит читаю, но для меня такая систематизация - это нечто новое. Не могу я там ни порядок инициализации найти, ни порядок запроса, ни вообще порядок общения с какими либо регистрами. Буду очень благодарен за какие-либо наводки в этом направлении... :)
Реклама
Эиком - электронные компоненты и радиодетали
isx
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

Сообщение isx »

Ни у кого нет никаких мыслей по этому поводу? Совсем а то запарился - не движется процесс никак :( .
Реклама
isx
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

Сообщение isx »

Раз никто не хочет участвовать в теме, то продолжу диалог с самим собой :) .
Угробил вчера около 3-х часов на изучение даташита на контроллер. Самые интересные для меня моменты:
1) Изображение
Так, включаем питание. Делаем RST=0, ждем 1мс., подымаем RST в 1, ждем 5мс. Сложно, но мы и не с таким справлялись :)) . Далее настраиваем питание, НО, я то хочу прочитать ID.
В даташите нет ни слова о том, когда мне можно прочитать ID чипа, поэтому делаю как все - читаю сразу после ресета. Едем к списку команд:
Изображение
Вот он родненький, самый первый в списке :) . И в нем мы сразу видим, что в результате чтения с этого регистра мы должны получить 01110101, тобишь 0x75. Что это за однобайтный идентификатор - понятия не имею, так как во всех других дисплеях они двухбайтные. Ну да и черт с ним пока, у нас более важная проблема - как передать 16-бит регистра по 8-ми битной шине? Опят головой в даташит:
Изображение
Это единственное, что можно найти по интересующему нас вопросу. Из этого можно предположить, что каждая кучка данных отправляется и принимается стробом RNW или NRN. И предполагаем, что контроллер вкурсе, что у нас шина на 8 бит, и что все команды и данные более 8-ми бит будут передаваться/приниматься
в несколько заходов. Только вот что он будет делать если мы передаем/принимаем 8 бит - завершать запись/чтение или ждать нулевые биты? Пока загадка. Ладно, черт с ним пока. Едем далее.
А далее пишем код:

Код: Выделить всё

void hx8347G_Reset (void)
{ 

	HX8347G_LCD_RESET_DISABLE;
	_hx8347G_Delay_ms(10);
	HX8347G_LCD_CS_DISABLE;
	HX8347G_LCD_CD_DATA;
	HX8347G_LCD_WR_DISABLE;
	HX8347G_LCD_RD_DISABLE;
	HX8347G_SET_DATA = 0xFF; 
	_hx8347G_Delay_ms(1);

	HX8347G_LCD_RESET_ENABLE;
	_hx8347G_Delay_us(3);
	HX8347G_LCD_RESET_DISABLE;
	_hx8347G_Delay_us(10);
	
		HX8347G_LCD_RESET_ENABLE;
	_hx8347G_Delay_us(10);
	HX8347G_LCD_RESET_DISABLE;
	_hx8347G_Delay_ms(150);
}



uint32_t hx8347G_Read_Reg (uint8_t Reg_Value, uint8_t Number_Of_Bytes_For_Read)
{ 
	uint32_t Readed_Data = 0;
	uint8_t x = 1;

	
	if (Data_PINs_State == 1) {hx8347G_PINs_Data_Out();}

	HX8347G_LCD_CS_DISABLE;
	HX8347G_LCD_RD_DISABLE;
	HX8347G_LCD_WR_DISABLE;
	HX8347G_LCD_CD_DATA;

	HX8347G_LCD_CS_ENABLE;
	HX8347G_LCD_CD_COMMAND;
  HX8347G_SET_DATA = Reg_Value;	
	_hx8347G_Delay_us(1);
	HX8347G_WR_STROBE;
	_hx8347G_Delay_us(1);
	
	HX8347G_LCD_CS_DISABLE;
	HX8347G_LCD_CS_ENABLE;
	
	HX8347G_LCD_CD_DATA;
	hx8347G_PINs_Data_In();
	for (x = 1; x <= Number_Of_Bytes_For_Read; x++)
	{
	_hx8347G_Delay_us(1);
	HX8347G_LCD_RD_ENABLE;
	_hx8347G_Delay_us(1);
	Readed_Data <<= 8;
	Readed_Data |= HX8347G_READ_DATA;
	HX8347G_LCD_RD_DISABLE;
	}
	
	HX8347G_LCD_CS_DISABLE;

	return Readed_Data;
	
}
Внимательный глаз, наверное, заметит строчки HX8347G_LCD_CS_DISABLE; HX8347G_LCD_CS_ENABLE;. Не смотря на то, что на графике NCS не отключается, код работает только в таком виде. Если убрать эти строки, то в ответ придут нули. Почему так сделано - понятия не имею :dont_know: .
Тайминги взяты с последних страниц даташита.
Теперь если в main.c добавить hx8347G_Reset (); test1 = hx8347G_Read_Reg (0x00, 1);, т.е. считать 1 байт из регистра 0x00, то в ответ получим 0x75. Вернемся к даташиту и посмотрим регистр 0x00 подробнее:
Изображение
Вот этот загадочный ID 0x75. Смею предположить, что я уже общаюсь с дисплеем :beer: .

P.S. похоже поторопился с выводами. При чтении любого регистра в ответ летят 0x75 либо 0x7D. Пошел искать причину....
Реклама
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 29
Зарегистрирован: Сб фев 06, 2016 14:26:07

Сообщение JustRom »

Киньте схему подключения, может гляну свежим взглядом. Я бы на Вашем месте попытался сначала запустить хоть с какой-нибудь библиотекой, чтобы убедиться, что он вообще живой. Эту ссылку смотрели?
isx
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

Сообщение isx »

Подключение проще простого (основано на ногодрыге):

Код: Выделить всё

#define HX8347G_LCD_RD_ENABLE                      (GPIOA->BSRR |= GPIO_BSRR_BR8)//
#define HX8347G_LCD_RD_DISABLE                      (GPIOA->BSRR |= GPIO_BSRR_BS8) //

#define HX8347G_LCD_WR_ENABLE                      (GPIOA->BSRR |= GPIO_BSRR_BR9) //
#define HX8347G_LCD_WR_DISABLE                      (GPIOA->BSRR |= GPIO_BSRR_BS9) //

#define HX8347G_LCD_CD_COMMAND                      (GPIOA->BSRR |= GPIO_BSRR_BR10) //
#define HX8347G_LCD_CD_DATA                            (GPIOA->BSRR |= GPIO_BSRR_BS10) //

#define HX8347G_LCD_CS_ENABLE                      (GPIOA->BSRR |= GPIO_BSRR_BR11) //
#define HX8347G_LCD_CS_DISABLE                      (GPIOA->BSRR |= GPIO_BSRR_BS11) //

#define HX8347G_LCD_RESET_ENABLE                   (GPIOA->BSRR |= GPIO_BSRR_BR12) //
#define HX8347G_LCD_RESET_DISABLE                (GPIOA->BSRR |= GPIO_BSRR_BS12) //

/////////////////////////////////////////////////////////////////////////////////////////////////////


    GPIOA->CRL |=  ( GPIO_CRL_MODE0 // D0
                    |GPIO_CRL_MODE1 // D1
                    |GPIO_CRL_MODE2 // D2
                    |GPIO_CRL_MODE3 // D3
                    |GPIO_CRL_MODE4 // D4
                    |GPIO_CRL_MODE5 // D5
                    |GPIO_CRL_MODE6 // D6
                    |GPIO_CRL_MODE7 // D7
                   );   

Проверить то неначем. Все библиотеки для ардуинок, а у меня только платы STM32 в распоряжении. Пробовал портировать, но ничего не вышло, в итоге не знаю, толи портировал неправильно, толи дисплей дохляк... :dont_know: :kill:

Добавлено after 6 minutes 33 seconds:
Последняя надежда на вот эту библиотеку (уже и не помню где скачал). Здесь на FSMC переделано под мой контроллер (HX8347G).
Завтра проверять буду, седня уже от этого дисплея голова кипит :) .
Вложения
ili9320 (For STM32).rar
(5.24 КБ) 211 скачиваний
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 29
Зарегистрирован: Сб фев 06, 2016 14:26:07

Сообщение JustRom »

А чем у Вас enable_bit от disable_bit отличается? Вы и там и там бит устанавливаете.

upd: с телефона не заметил, но я бы вместо BSRR дергал бы через ODR
isx
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

Сообщение isx »

BSRR выполняется за один такт. Это как bit-banding.
Ответить

Вернуться в «Цифровая техника»