Вы тоже любите дисплеи?

от автора

Началось всё с того, что покупая что-то на барахолке увидел у продавца разные симпатичные дисплейчики от мобильных телефонов и не только за небольшую цену. Решил взять за компанию в количестве трёх штук — «куда-нибудь пригодится». Шло время, делались разные проекты, а дисплеи мирно ждали своего часа где-то на полке. Но вот настал день, когда я добрался до них и решил всё-таки их оживить. Однако вот задача, о данной модели экрана почти ничего неизвестно… Вот и обратная разработка на подходе. Интересно? Тогда поехали.

Для подключения, наверное, любого дисплея нужно знать 3 вещи: где какой вывод, модель контроллера и последовательность включения (power on sequence или init). Итак, что мы знаем о дисплее? Пока только модель телефона — заботливый продавец указал её при продаже. Эти экраны применяются в телефонах ZTE A36, ZTE A136, ZTE A136G. Первая мысль — посмотреть характеристики дисплея в описании телефона — так, чтобы знать с кем имеем дело. Это цветной CSTN экран разрешением 128×128 точек, диагональ 1.5″, глубина цвета 16 бит (65536 цветов). Не густо, но хоть что-то. В сети множество статей, где ребята подключают дисплеи от мобильных к микроконтроллерам и прочему. Может кто-то уже подключал такие? Поиск довольно быстро опроверг это предположение и надежда без особого труда подключить сие чудо не оправдалась. Плохо искал.

Придётся копать дальше. Вы тоже подумали про схему мобильного телефона или сервис мануал? При первом же запросе были найдены сайты — какие-то форумы ремонтников — где была схема в том числе и на наш телефон. Отлично! Сейчас скачаем. Регистрируемся и… не скачиваем — нет репутации, баллов, сообщений и т д. Ладно. Идём на другой сайт, потом ещё на один, потом ещё… Такое чувство, будто ходишь у витрины магазина, видишь то, что тебе нужно, а достать никак. Жаль, конечно, но что поделать, раз без регистрации и смс никак. Значит распиновку придётся найти как-то иначе.

Смотрим на матрицу — торчит симпатичный шлейф с дорожками и детальками, словно она показывает нам язык, мол не сдамся.

Поиск по надписи TSF8H0062FPC-B1-E на шлейфе никакой полезной информации не дал. Зато по шлейфу видно, как и куда идут дорожки. Проще всего определить землю — она на полигонах и звонится между собой, а также подсветку — обычно идёт отдельным шлейфом. Здесь даже подписаны анод и катоды. Катоды, видимо, соединены параллельно. Тем лучше: проще питать подсветку (не понадобится dc-dc преобразователь). На полигонах у нас 1й, 15й, 20й выводы (счёт слева направо). Они звонятся и между собой. С ними также звонится и 16й вывод, но дорожка от него идёт к резисторам R4 и R3.

Резистор R4 имеет нулевое сопротивление и подключён между выводом 16 и землёй, а резистор R3 вообще не впаян и подключён между выводом 16 и 17. Видимо 17й вывод это + питания, а 16й — это, скорее всего, вывод LCD_ID, по которому телефон определяет модель дисплея. Такое встречается и у других экранов от мобильных.

Видим, что общее кол-во выводов 20. Это позволяет прикинуть, какой используется интерфейс: для spi многовато, значит интерфейс параллельный, вероятнее всего 8-битный. Для 16 бит уже не хватает выводов — три вывода земли, 2 вывода подсветки, остаётся 15. А ведь ещё нужно найти питание, которое у дисплеев часто имеет 2 отдельные линии. Интерфейс обычно используется 8080. В даташитах на контроллеры дисплея встречается ещё 6800, но применяется он, видимо, довольно редко. По крайней мере, в статьях про другие дисплеи я такого не встречал, мне тоже он не попадался. Давайте отметим, что уже есть. Это очень удобно делать в экселе. Пишем название вывода в каждую новую строку первого столбца. А во втором и других столбцах можно делать некоторые комментарии. Также удобно помечать выводы цветом и оперативно менять его при необходимости. Но для наглядности и чтобы никуда не потерялось я это сделаю на картинке:

Очевидно, что выводы со второго по 14й — это линии D0…D7, WR, RD, RS (DC), Reset и СS. То есть обычные для интерефейса 8080 линии. Так ведь? Так, да не так. Помните отметку на фото выше около конденсатора и вывода 14, про которые я пока ничего не сказал? А что линий питания (+) часто две? Подумалось мне, что 14й вывод — это вторая линия питания. Правда, тогда не хватает как раз одного вывода для линий управления. Хотя можно чип селект посадить на активный уровень, возможно так и сделано. В принципе, этой информации уже достаточно, чтобы попытаться найти в интернете похожие распиновки и выбрать из них одну подходящую. Запрос я вводил примерно как «tft lcd 20 pin», «tft lcd 1.5 inch» и в таком виде в разных вариантах. Далее поиск по картинкам. Обычно при таком запросе в итоге попадаешь на алиэкспрес, где довольно часто продавец приводит распиновку для экрана. Бывает пишет и модель контроллера. В итоге нашёл вот такую распиновку:

Да это наш дисплей и есть, всё как у нас! Отлич…

Но что делать с выводом 16? На распиновке указано Vdd, то есть + питания, а у нас он звонится с минусом. Что-то не так. Зато тут указана модель контроллера S6B3301. Качаем даташит, может пригодится. О том, что контроллер стоит или такой, или из этого семейства, я стал подозревать после того, как случайно нашёл у того же продавца с барахолки ещё один дисплей для ZTE A36, но чуть-чуть другой:

А вот тут уже есть интересная надпись «S6B33B6«. Очевидно это модель контролера. Правда шлейф чуть другой и у нашего дисплея может быть другой контроллер. Даташит на S6B33B6 я так и не нашёл. Зато нашёл на похожие s6b33b2, s6b33b0a, s6b33b3a, s6b33bl.

Подведём некоторый итог: точная модель контроллера неизвестна, точная распиновка тоже, инита пока тоже нет. Покопавшись в даташите на s6b3301, я нашёл там PowerON sequence и решил попробовать написать инит. На всякий случай посмотрел интерфейс 8080:

Вас тоже смущает 2 сигнала чип селект? CS2 и CS1B. Зачем их 2, я не знаю. Вспомним здесь ещё и конденсатор с 14го вывода на землю (который, правда, не впаян). В общем я решил, что это скорее всего второе питание. Иначе зачем ставить конденсатор на вывод чип селект? Наверное оба чип селекта наглухо соединены с выводами питания, чтобы дисплей всегда был активен. Но даже если я ошибся, то ничего не сгорит.

Берём stm32 и пробуем писать инит, функции для передачи данных и команд, и вывод тестовой картинки. У меня это будет 3 полоски основных цветов. Stm32 я выбрал из-за логических уровней 3,3 В. Предварительно также полистал ранее скачанные даташиты контроллеров данного семейства и проверил максимальное напряжение питания — у всех оно было больше 3,3 вольт. Значит будем питать подопытного от 3,3 В. За основу я взял распиновку, которую нашёл ранее (на картинке выше), только на вывод 16 я ничего не подавал, а на 14й вывод подал +3,3 В. Пишем программу, прошиваем — дисплей молчит.

Тут я решил, что информации не достаточно, и дисплей пока отправится на полку. Всё равно он маленький, есть экземляры и побольше. На этом всё, расходимся.

О пользе общения или логический анализатор в помощь

Но не тут то было. В тот самый момент, когда я уже упаковал всё в пакетик, наклеил наклейку и написал, что точной информации нет, мне приходит сообщение от моего товарища (товарищ, привет!) — мы иногда делимся друг с другом текущими проектами — где он присылает мне ссылку на похожий, по его мнению, дисплей на алиэкспресе. Ссылка у меня почему-то не открывалась, но свою задачу он выполнил — я решил: «А может ещё поискать?» Но что делать дальше? Даже попробовал отсеять контроллеры по размеру чипа — он тоже приводится в даташите. Тут вспомнилась замечательная статья, которую читал годом ранее. Можно было бы ещё поискать какую-либо информацию в интернете, но это долго, а главное не гарантирует результат. Поэтому я решил не «биться головой об стенку», а найти нужный телефон на барахолке и купить наконец логический анализатор (давно уже хотел).

Мне всё таки удалось найти рабочий телефон. Приехал DSLogic+. Дальше дело техники — подпаиваемся к плате:

Тут я немного промахнулся с проволочками — они оказались настолько тонкими, что клипсы просто невозможно было надёжно закрепить. Под рукой оказались обрезки выводов выводных компонентов — обычно выручают, поэтому я их не выбрасываю. Аккуратно всё расправляем, чтобы не коротнуло, записываем обмен.

Каналы анализатора я подключал по порядку с первого вывода, пропуская земли. Видим, что 0я линия изменяется один раз — это reset. 13я линия подключена к выводу 16 (подключил на всякий случай), 14я — к выводу 17. Видно, что это питание. Сперва дисплей сбрасывается, затем происходят какие-то настройки, потом после паузы на нём появляется картинка велком. Затем питание выключается и все линии падают в ноль. Декодировать это вручную ооочень долго и чревато ошибками и лишней усталостью. Поэтому подключим декодер. DSView (как и Sigrok) содержит множество декодеров, но для протокола 8080 не нашлось. Можно написать свой, я начал это делать и даже появились первые успехи, но потом решил сосредоточиться именно на дисплее. Благо, в списке декодеров я видел «parallel». Решил попробовать его. Предположим, что найденная ранее распиновка, в целом, верная, а также внимательно изучим поведение линий

и сравним его с приведенной в даташите картинкой для интерфейса 8080 (эта картинка уже упоминалась выше). Видим, что запись идёт по фронту сигнала WR, а сигнал CS1B устанавливается в неактивное состояние только после фронта WR. Декодер Parallel требует линии данных и линию синхронизации — выбираем 8 линий данных и линию WR. Всё, теперь можно записать последовательность команд, задержек между ними (особенно нужно учесть большие задержки). Здесь, опять же, очень удобно работать в экселе.

А в DSView очень удобно переключаться по декодированным байтикам. Первая декодированная команда 0x50 (на картинке выше не показана). Это «Display OFF». Непонятно, зачем выключать его, он и так выключен. Главное что получили не бессмысслицу, а именно код команды, которую нашли в даташите. Декодируя команды одну за другой отсеиваем контроллеры, у которых таких команд просто нет или есть несоответствия. Сравнивая команды контроллеров s6b33b2, s6b33b0a, s6b33b3a, s6b33bl, обнаруживаем, что они у всех одни и те же. Где-то немного отличаются биты в параметрах команд. Поэтому точно определять модель контроллера незачем.

Итоги

В итоге получаем такой инит
/* USER CODE BEGIN 2 */ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //S6B33Bx init (poluchen s pomosh'u dslogic+ i datasheetov na S6B33Bx,) LCD_RST0;           // Reset  HAL_Delay(102);  //   wait 102 ms LCD_RST1;           // Release reset  lcd_sendcmd(0x50);//0-Display OFF   HAL_Delay(220);  //   wait 220 ms lcd_sendcmd(0x2C);//1-Standby Mode OFF   HAL_Delay(220);  //   wait 220 ms   lcd_sendcmd(0x02);//2-Oscillation Mode Set  lcd_sendcmd(0x01);//3-parameter OSC = 1: Internal oscillator ON HAL_Delay(110);//wait 110 ms lcd_sendcmd(0x20);//4-DC-DC Select lcd_sendcmd(0x03);//5-parameter DC1 x2 DC2 x1 HAL_Delay(110);//wait 110 ms lcd_sendcmd(0x26);//6-DC-DC and AMP ON/OFF set  lcd_sendcmd(0x01);//7-parameter  Built-in 1’st Booster ON HAL_Delay(110);//wait 110 ms lcd_sendcmd(0x26);//8-DC-DC and AMP ON/OFF set  lcd_sendcmd(0x09);//9-parameter  Built-in OP-AMP ON,  Built-in 1’st Booster ON HAL_Delay(220);  //   wait 220 ms lcd_sendcmd(0x26);//10-DCDC and AMP ON/OFF set   lcd_sendcmd(0x0B);//11-parameter  Built-in OP-AMP ON,  Built-in 1’st Booster ON, Built-in 2’nd Booster ON HAL_Delay(324);  //   wait 324 ms lcd_sendcmd(0x26);//12-DC-DC and AMP ON/OFF set  lcd_sendcmd(0x0F);//13-parameter Built-in OP-AMP ON,  Built-in 1’st Booster ON, Built-in 2’nd Booster ON, Built-in 3’rd Booster ON HAL_Delay(110);//wait 110 ms lcd_sendcmd(0x28);//14-Temperature Compensation Set lcd_sendcmd(0x00);//15-parameter  TCS = 00 : 0.00%/degC  HAL_Delay(54);  //   wait 54 ms lcd_sendcmd(0x45);//16-RAM Skip Area Set  lcd_sendcmd(0x00);//17-parameter RAM Skip function ON/OFF RSK = 00 : No Skip lcd_sendcmd(0x53);//18-Specified Display Pattern Set  lcd_sendcmd(0x00);//19-parameter SDP = 00 : Normal display lcd_sendcmd(0x10);//20-DriverOutputMode set (This instruction sets the display direction.) lcd_sendcmd(0x03);//21-parameter ...  lcd_sendcmd(0x24);//22-DC-DC Clock Division Set   lcd_sendcmd(0x03);//23-parameter ... lcd_sendcmd(0x30);//24-Addressing Mode Set   lcd_sendcmd(0x0D);//25-parameter GSM=00 - 65536 color mode dsg=1 -dummy subgroup is one subgroup  //SGF=1: SG Frame inversion ON SGP=10:  Different phase by 2pixel-unit (Initial status)  //SGM= 1: SG inversion ON lcd_sendcmd(0x32);//26-ROWVectorModeSet  lcd_sendcmd(0x0E);//27-parameter 111 - Every sub-frame (initial status) 0 - - 0: R1->R2->R3->R4 -> R1… (Initial status)    lcd_sendcmd(0x40);//28-Entry Mode Set  lcd_sendcmd(0x80);//29-parameter ... lcd_sendcmd(0x42);//30-X-address Area Set  lcd_sendcmd(0x00);//31-parameter ... lcd_sendcmd(0x7F);//32-0x7F = 127 lcd_sendcmd(0x43);//33-Y-address Area Set lcd_sendcmd(0x00);//34-parameter ... lcd_sendcmd(0x7F);//35-0x7F = 127 HAL_Delay(22);  //   wait 22 ms lcd_sendcmd(0x34);//36-N-lineInversionSet lcd_sendcmd(0x88);//37-parameter ... lcd_sendcmd(0x2A);//38-ContrastControl(1) lcd_sendcmd(0xC6);//39-parameter ...  lcd_sendcmd(0x36);//40-FrameFrequen control  lcd_sendcmd(0x00);//41-parameter ... lcd_sendcmd(0x55);//42-Partial Display Mode Set lcd_sendcmd(0x00);//43-parameter ...  lcd_sendcmd(0x51);//44- Display ON HAL_Delay(54);  //   wait 54 ms

Окончательная распиновка получилась такая:

Вывод LCD_ID оставляем не подключенным, на Vdd подаём 3,3 В. А подсветку подключаем к питанию через небольшой резистор. В качестве контроллера возьмём популярную платку blue pill.

Код целиком
/* Includes ------------------------------------------------------------------*/ #include "main.h" #include "gpio.h"  /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "stm32f1xx_ll_gpio.h" /* USER CODE END Includes */  /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */  /* USER CODE END PTD */  /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ //  LCD_RST #define LCD_RST1  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0,GPIO_PIN_SET); #define LCD_RST0  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0,GPIO_PIN_RESET); //   LCD_DC #define LCD_DC1  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1,GPIO_PIN_SET); #define LCD_DC0  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1,GPIO_PIN_RESET); //   LCD_WR #define LCD_WR1  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2,GPIO_PIN_SET); #define LCD_WR0  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2,GPIO_PIN_RESET); //   LCD_RD #define LCD_RD1  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3,GPIO_PIN_SET); #define LCD_RD0  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3,GPIO_PIN_RESET); //  LCD_CS #define LCD_CS1   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4,GPIO_PIN_SET); #define LCD_CS0   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4,GPIO_PIN_RESET);  //Connect d0...d7  Reset DC WR  RD  CS //     to b3...b10 A0    A1 A2  A3  A4  #define lcd_width 128 #define lcd_heigth 128  /* USER CODE END PD */  /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */  /* USER CODE END PM */  /* Private variables ---------------------------------------------------------*/  /* USER CODE BEGIN PV */  /* USER CODE END PV */  /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */  /* USER CODE END PFP */  /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ void lcd_sendbyte(uint8_t byte)//8080 8 bit parallel protocol { LCD_CS0; LCD_RD1;//write LCD_WR0; //lcd d0 connected to pin b3, d1 to d4, that is why byte shifted by 3 ... LL_GPIO_WriteOutputPort(GPIOB, byte<<3); LCD_WR1;//The display writes D[17:0] lines when there is a rising edge of WRX LCD_CS1; } void lcd_sendcmd(uint8_t cmd) { LCD_DC0;//command lcd_sendbyte(cmd); } void lcd_senddata(uint8_t data) { LCD_DC1;//data lcd_sendbyte(data); } void lcd_draw_pixel(uint8_t x, uint8_t y, uint16_t color) { lcd_sendcmd(0x43);//Row adress set lcd_sendcmd(y);//Y start address  lcd_sendcmd(y+1);//Y end address  lcd_sendcmd(0x42);//Column adress set lcd_sendcmd(x); //X start address  lcd_sendcmd(x+1); //X end address   lcd_senddata((color & 0xFF00)>>8);//higher byte lcd_senddata(color & 0x00FF);//lower byte } /* USER CODE END 0 */  /**   * @brief  The application entry point.   * @retval int   */ int main(void) {   /* USER CODE BEGIN 1 */    /* USER CODE END 1 */    /* MCU Configuration--------------------------------------------------------*/    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */   HAL_Init();    /* USER CODE BEGIN Init */    /* USER CODE END Init */    /* Configure the system clock */   SystemClock_Config();    /* USER CODE BEGIN SysInit */    /* USER CODE END SysInit */    /* Initialize all configured peripherals */   MX_GPIO_Init();   /* USER CODE BEGIN 2 */ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //S6B33Bx init (poluchen s pomosh'u dslogic+ i datasheetov na S6B33Bx,) LCD_RST0;           // Reset  HAL_Delay(102);  //   wait 102 ms LCD_RST1;           // Release reset  lcd_sendcmd(0x50);//0-Display OFF   HAL_Delay(220);  //   wait 220 ms lcd_sendcmd(0x2C);//1-Standby Mode OFF   HAL_Delay(220);  //   wait 220 ms   lcd_sendcmd(0x02);//2-Oscillation Mode Set  lcd_sendcmd(0x01);//3-parameter OSC = 1: Internal oscillator ON HAL_Delay(110);//wait 110 ms lcd_sendcmd(0x20);//4-DC-DC Select lcd_sendcmd(0x03);//5-parameter DC1 x2 DC2 x1 HAL_Delay(110);//wait 110 ms lcd_sendcmd(0x26);//6-DC-DC and AMP ON/OFF set  lcd_sendcmd(0x01);//7-parameter  Built-in 1’st Booster ON HAL_Delay(110);//wait 110 ms lcd_sendcmd(0x26);//8-DC-DC and AMP ON/OFF set  lcd_sendcmd(0x09);//9-parameter  Built-in OP-AMP ON,  Built-in 1’st Booster ON HAL_Delay(220);  //   wait 220 ms lcd_sendcmd(0x26);//10-DCDC and AMP ON/OFF set   lcd_sendcmd(0x0B);//11-parameter  Built-in OP-AMP ON,  Built-in 1’st Booster ON, Built-in 2’nd Booster ON HAL_Delay(324);  //   wait 324 ms lcd_sendcmd(0x26);//12-DC-DC and AMP ON/OFF set  lcd_sendcmd(0x0F);//13-parameter Built-in OP-AMP ON,  Built-in 1’st Booster ON, Built-in 2’nd Booster ON, Built-in 3’rd Booster ON HAL_Delay(110);//wait 110 ms lcd_sendcmd(0x28);//14-Temperature Compensation Set lcd_sendcmd(0x00);//15-parameter  TCS = 00 : 0.00%/degC  HAL_Delay(54);  //   wait 54 ms lcd_sendcmd(0x45);//16-RAM Skip Area Set  lcd_sendcmd(0x00);//17-parameter RAM Skip function ON/OFF RSK = 00 : No Skip lcd_sendcmd(0x53);//18-Specified Display Pattern Set  lcd_sendcmd(0x00);//19-parameter SDP = 00 : Normal display lcd_sendcmd(0x10);//20-DriverOutputMode set (This instruction sets the display direction.) lcd_sendcmd(0x03);//21-parameter ...  lcd_sendcmd(0x24);//22-DC-DC Clock Division Set   lcd_sendcmd(0x03);//23-parameter ... lcd_sendcmd(0x30);//24-Addressing Mode Set   lcd_sendcmd(0x0D);//25-parameter GSM=00 - 65536 color mode dsg=1 -dummy subgroup is one subgroup  //SGF=1: SG Frame inversion ON SGP=10:  Different phase by 2pixel-unit (Initial status)  //SGM= 1: SG inversion ON lcd_sendcmd(0x32);//26-ROWVectorModeSet  lcd_sendcmd(0x0E);//27-parameter 111 - Every sub-frame (initial status) 0 - - 0: R1->R2->R3->R4 -> R1… (Initial status)    lcd_sendcmd(0x40);//28-Entry Mode Set  lcd_sendcmd(0x80);//29-parameter ... lcd_sendcmd(0x42);//30-X-address Area Set  lcd_sendcmd(0x00);//31-parameter ... lcd_sendcmd(0x7F);//32-0x7F = 127 lcd_sendcmd(0x43);//33-Y-address Area Set lcd_sendcmd(0x00);//34-parameter ... lcd_sendcmd(0x7F);//35-0x7F = 127 HAL_Delay(22);  //   wait 22 ms lcd_sendcmd(0x34);//36-N-lineInversionSet lcd_sendcmd(0x88);//37-parameter ... lcd_sendcmd(0x2A);//38-ContrastControl(1) lcd_sendcmd(0xC6);//39-parameter ...  lcd_sendcmd(0x36);//40-FrameFrequen control  lcd_sendcmd(0x00);//41-parameter ... lcd_sendcmd(0x55);//42-Partial Display Mode Set lcd_sendcmd(0x00);//43-parameter ...  lcd_sendcmd(0x51);//44- Display ON HAL_Delay(54);  //   wait 54 ms   /* lcd_sendcmd(0x43);//45-Y-address Area Set  lcd_sendcmd(0x00);//46-y start lcd_sendcmd(0x7F);//47- y end 0x7F = 127 lcd_sendcmd(0x42);//48-X-address Area Set lcd_sendcmd(0x00);//49-x start lcd_sendcmd(0x7F);//50- x end 0x7F = 127   lcd_sendcmd(0x43);//51-Y-address Area Set  lcd_sendcmd(0x00);//52-y start lcd_sendcmd(0x7F);//53- y end 0x7F = 127 lcd_sendcmd(0x42);//54-X-address Area Set lcd_sendcmd(0x04);//55-x start lcd_sendcmd(0x83);//56- x end 0x83 = 131 */  //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  uint16_t color; //GREEN  uint8_t y;   uint8_t x;    for (y=0;y<lcd_heigth;y++) {      for (x=4;x<132;x++)  {                  if (y<40) color=0xF800; //RED         else if (y<80) color=0x07E0; //GREEN else color=0x001F; //BLUE           lcd_draw_pixel(x, y, color);      } } HAL_Delay(3000);  //   wait 3 s  /* //++++++++++++++++++clear LCD++++++++++++ color = 0x00; lcd_sendcmd(0x43);//51-Y-address Area Set  lcd_sendcmd(0x00);//52-y start lcd_sendcmd(0x7F);//53- y end 0x7F = 127 lcd_sendcmd(0x42);//54-X-address Area Set lcd_sendcmd(0x04);//55-x start lcd_sendcmd(0x83);//56- x end 0x83 = 131  for (y=0;y<lcd_heigth;y++) {      for (x=0;x<lcd_width;x++)  {  lcd_senddata((color & 0xFF00)>>8);//higher byte      lcd_senddata(color & 0x00FF);//lower byte  } }  */      /* USER CODE END 2 */    /* Infinite loop */   /* USER CODE BEGIN WHILE */   while (1)   {     /* USER CODE END WHILE */      /* USER CODE BEGIN 3 */   }   /* USER CODE END 3 */ }  /**   * @brief System Clock Configuration   * @retval None   */ void SystemClock_Config(void) {   RCC_OscInitTypeDef RCC_OscInitStruct = {0};   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};    /** Initializes the RCC Oscillators according to the specified parameters   * in the RCC_OscInitTypeDef structure.   */   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;   RCC_OscInitStruct.HSEState = RCC_HSE_ON;   RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;   RCC_OscInitStruct.HSIState = RCC_HSI_ON;   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)   {     Error_Handler();   }   /** Initializes the CPU, AHB and APB buses clocks   */   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)   {     Error_Handler();   } }  /* USER CODE BEGIN 4 */  /* USER CODE END 4 */  /**   * @brief  Period elapsed callback in non blocking mode   * @note   This function is called  when TIM2 interrupt took place, inside   * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment   * a global variable "uwTick" used as application time base.   * @param  htim : TIM handle   * @retval None   */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {   /* USER CODE BEGIN Callback 0 */    /* USER CODE END Callback 0 */   if (htim->Instance == TIM2) {     HAL_IncTick();   }   /* USER CODE BEGIN Callback 1 */    /* USER CODE END Callback 1 */ }  /**   * @brief  This function is executed in case of error occurrence.   * @retval None   */ void Error_Handler(void) {   /* USER CODE BEGIN Error_Handler_Debug */   /* User can add his own implementation to report the HAL error return state */    /* USER CODE END Error_Handler_Debug */ }  #ifdef  USE_FULL_ASSERT /**   * @brief  Reports the name of the source file and the source line number   *         where the assert_param error has occurred.   * @param  file: pointer to the source file name   * @param  line: assert_param error line source number   * @retval None   */ void assert_failed(uint8_t *file, uint32_t line) {   /* USER CODE BEGIN 6 */   /* User can add his own implementation to report the file name and line number,      tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */   /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */  /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Сперва я не совсем правильно понял как посылать адрес дисплею, в итоге получил не ожидаемые три полоски, а цветной снег.

Это тоже хорошо — значит дисплей принимает команды и выполнил «DisplayON». В процессе отладки и пошагового исполнения проверил, дисплей выключен ровно до того момента, как посылается эта команда. Немного исправил функцию рисования пикселя, и, слава Богу, всё заработало («код целиком» — это уже исправленный и рабочий код).

Уже потом нашёл библиотеку на S6B33BG от kbiva и статью про похожий дисплейчик. Эффектную демо я не писал, так как цель была именно провести обратную разработку. При необходимости всё это можно дописать.

С момента приезда анализатора и телефона до момента появления трёх полос на дисплее прошло примерно 2 дня. Информацию я собирал несколько дольше. Как видим, логический анализатор сильно ускоряет процесс. Также, наверное, может помочь анализ прошивки самого телефона. Там можно встретить строчки вида (пример для телефона FLY E160):

LCD_BlockWrite_HX8347D: startx=%d, starty=%d, endx=%d, endy=%d  0   custom\drv\LCD\TINNO35_09A_LCM\lcd_HX8347D.c    IsLcd_HX8347D.. data:%x LCD_BlockWrite_ILI9325: startx=%d, starty=%d, endx=%d, endy=%d  0   custom\drv\LCD\TINNO35_09A_LCM\lcd_ILI9325.c    IsLcd_ILI9325.. data:%x LCD_BlockWrite_ILI9328: startx=%d, starty=%d, endx=%d, endy=%d  0   custom\drv\LCD\TINNO35_09A_LCM\lcd_ILI9328.c    IsLcd_ILI9328.. data:%x LCD_Init_R61580() %d    0   custom\drv\LCD\TINNO35_09A_LCM\lcd_R61580.c IsLcd_R61580 data»

Жирным отметил модель контроллера. Эту информацию привожу для справки, сам пока в прошивках не пробовал искать. Если по прошивке телефона в чём-то ошибся, просьба поправить в комментариях.

В конце хочу выразить благодарность своему товарищу, ведь статья появилась в том числе и благодаря ему. Надеюсь, было интересно и кому-то поможет. Удачных проектов.


ссылка на оригинал статьи https://habr.com/ru/post/685056/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *