Čtení konfigurace z LCD displeje

Ahoj chtěl bych se zeptat zda si někdo nehraje s grafickými displeji a neřeší z nich i čtení. Já laboruji s KD018QQTBN009-RT na MCU STM32. Napsal a odladil jsem si vlastní knihovnu na inicializaci displeje a daří se mi z něj i čtení (používám k tomu SPIčko). Bohužel jsem po nějaké době zjistil, že občas se mi displej správně neinicializuje. Zkoušel jsem init po náběhu napájení zpozdit, ale žádné časové zpoždění nemělo vliv na spolehlivost inicializace. Řekl jsem si tedy, že pokud do displeje zapíšu nějaké pixely a povede se mi je zpětně přečíst, bude inicializace provedena správně. To jsem udělal a fungovalo to bezvadně. Po nějaké době jsem ale zjistil, že existují displeje, které se mi prostě nedaří přečíst. Nepřečtu z nich vůbec nic ani ID. Pokud čtu pixely, které jsou zapsané v displeji, vrací samá fka a pokud čtu ID vrací mi místo očekávaného 0x7C špatně 0xFE. To mi příjde dost zvláštní, protože displeje jsou všechny jedné šarže, od jednoho dodavatele a to přímo od výrobce. Nenapadá někoho jak z problému vybruslit? Dík.

Datasheet k displeji

Zapojení displeje:
LCD

Zde je ukázka inicializace displeje, ze které je vidět časování:
(dokud se displej neinicializuje, tak se tato funkce volá každých 5ms)

static uint8_t ST7735_Init(void){
  static uint8_t sekv = 0;
  static uint8_t c_delay = TIMER_MS(200, 5);
  
  if(c_delay != 0){ 
    c_delay--;
    return 0x00;
    }
  
  if(sekv == 0){     
    RST_L();
    sekv = 1;
    c_delay = TIMER_MS(10, 5);
    return 0x00;
    }
  
  if(sekv == 1){      
    RST_H();
    CS_H();
    sekv = 2;
    c_delay = TIMER_MS(10, 5);
    return 0x00;
    }
  
  if(sekv == 2){
    CS_L();
    LCD_CMD();
    ST7735_write_byte(REG_SWRESET);                                            
    sekv = 3; 
    c_delay = TIMER_MS(200, 5);
    CS_H();
    return 0x00;
    }
  
  if(sekv == 3){
    #ifdef TEST_LCD
    if((ST7735_SW_read_reg(REG_RDDID) & 0x000000FF) != 0x7C){ 
      //neprecteno ID z displeje, displej zrejme neni pripojen - opakovani inicializace  
      sekv = 0;
      c_delay = TIMER_MS(200, 5);
      return 0x00;
      } 
    else{    
      sekv = 4;
      c_delay = TIMER_MS(10, 5);
      return 0x00;
      }
    #else
    sekv = 4;
    #endif
    }
  
  if(sekv == 4){
    CS_L();
    LCD_CMD();
    ST7735_write_byte(REG_SLPOUT);                                              // Sleep out, booster on
    sekv = 0xFF; 
    c_delay = TIMER_MS(20, 5);
    return 0x00;
    }
  
  //CMD ////////////////////////////////////////////////////////////////////////
  ST7735_write_byte(REG_FRMCTR1);                                               // In normal mode (full colors):  
  LCD_DATA();
  ST7735_write_byte(0x05);                                                      // RTNA set 1-line period: RTNA2, RTNA0
  ST7735_write_byte(0x3C);                                                      // Front porch: FPA5,FPA4,FPA3,FPA2
  ST7735_write_byte(0x3C);                                                      // Back porch: BPA5,BPA4,BPA3,BPA2
  //////////////////////////////////////////////////////////////////////////////  
  LCD_CMD();
  ST7735_write_byte(REG_INVCTR);                                                // Display dot inversion control:  
  LCD_DATA();
  ST7735_write_byte(0x03);                                                      // NLB,NLC
  //////////////////////////////////////////////////////////////////////////////  
  LCD_CMD();
  ST7735_write_byte(REG_COLMOD);                                                // Interface pixel format  
  LCD_DATA();
  ST7735_write_byte(0x05);                                                      // 16-bit/pixel RGB 5-6-5 (65k colors)
  //////////////////////////////////////////////////////////////////////////////  
  LCD_CMD();
  ST7735_write_byte(REG_INVOFF);                                                // Display inversion off  
  //CMD ////////////////////////////////////////////////////////////////////////
  ST7735_write_byte(REG_NORON);                                                 // Normal Display Mode On   
  //CMD ////////////////////////////////////////////////////////////////////////
  ST7735_write_byte(REG_GAMSET);                                                // Gamma curve set:  
  LCD_DATA();
  ST7735_write_byte(0x01);                                                      // Gamma curve 1 (G2.2) or (G1.0)
  //////////////////////////////////////////////////////////////////////////////  
  LCD_CMD();
  ST7735_write_byte(REG_DISPON);                                                // Display on  
  //CMD ////////////////////////////////////////////////////////////////////////
  ST7735_write_byte(REG_MADCTL);                                                // Orientation  
  #if(ORIENTATION == ORIENTATION_CW)
  LCD_DATA();
  ST7735_write_byte(0xA8);                                                      // X-Y Exchange,Y-Mirror
  #elif(ORIENTATION == ORIENTATION_MORMAL_180)
  LCD_DATA();
  ST7735_write_byte(0xC8);                                                      // X-Y Exchange,X-Mirror
  #elif(ORIENTATION == ORIENTATION_CW_180)
  LCD_DATA();
  ST7735_write_byte(0x68);                                                      // X-Y Exchange,X-Mirror
  #else
  LCD_DATA();
  ST7735_write_byte(0x08);                                                      // Normal: Top to Bottom; Left to Right
  #endif
  //////////////////////////////////////////////////////////////////////////////  
  CS_H();

  sekv = 0;
  return 0xFF;  
  }
1 Like

Moc jsem se na kód nedíval, ale co se děje na sběrnici jsi se díval? Logický analyzátor nebo i osciloskop. Že bity/bajty sedí dle DS?

Nedávno jsem pracoval s I2C převodníkem na 1wire a ten mi dal zabrat. Pokud jsem s ním nekomunikoval přesně jak bylo v DS, ale používal jsem obvyklou komunikaci, která mi funguje na desítkách různých zařízení, tak on jediný měl velké problémy. Jednou jel, jednou ne a byl to opruz to dát celé do funkčního stavu.

Takže spíš koukni na tu SPI sběrnici (hrany, bity, bajty, read, write). Pak bych šel do kódu.

Ahoj, tak problém je vyřešen, díky Jirkovi za tip. Problém byl způsoben jako obvykle naprosto pitomou chybou, kterou jsem trvale přehlížel.

Místo toho abych používal:

GPIOB->CRL |= (GPIO_CRL_CNF5_1);    //enable input function 

jsem používal:

GPIOB->CRL |= (GPIO_CRL_MODE5_1);    //enable input function 

Toto nastavení registru nebylo správnou volbou. Díky tomu se dělo to, že z displeje nemohla jít úroveň při logické nule úplně do nuly, ale do hodnoty kolem 1V až 2V podle toho jaký tam byl displej. Tím se vysvětlilo i proč to u některých LCD šlo a u některých ne.

Logický analyzátor, který jsem na ladění podle nápadu Jirky použil toto neodhalil, protože ten to vyhodnotil jako logickou nulu. Zdálo se tedy, že je vše v pořádku. Použitím osciloskopu došlo k odhalení problému a tedy i k jeho vyřešení.