SSD1306 8080 Paralel Haberleşme

Başlatan Mucit23, 20 Kasım 2018, 17:55:06

Mucit23

Selamlar

SSD1306 128x64 OLED LCD lerden satın aldım. Elimde 10 adet kadar var.  https://www.buydisplay.com/default/128x64-oled-i2c-0-96-display-white-color-connector-fpc-ssd1306


SSD1306 ile 8080 formatında paralel olarak haberleşmeye çalışıyorum. Bununla ilgili bir tasarım yaptım. Mikroişlemci olarak STM32F042C6 kullanıyorum.

Bağlantılarım aşağıdaki gibi.



Hemen basitçe bir init rutini hazırladım. Komut yazma ve Data yazma alt programlarını yazdım.
void SSD1306_Reset(void)
{
  GPIO_SetBits(LCD_CS_PORT,LCD_CS_PIN);  //CS=1
	
	GPIO_ResetBits(LCD_RES_PORT,LCD_RES_PIN);  //RES=0
	Delay(10);
	GPIO_SetBits(LCD_RES_PORT,LCD_RES_PIN);    //RES=1
}

void SSD1306_WriteData(uint8_t wr_data)
{
	GPIO_SetBits(LCD_DC_PORT,LCD_DC_PIN);   //DC=1
  GPIO_ResetBits(LCD_CS_PORT,LCD_CS_PIN); //CS=0
  GPIO_ResetBits(LCD_WR_PORT,LCD_WR_PIN); //WR=0
	Delay(1);
	GPIOB->ODR =  (GPIOB->IDR & 0xFF00) | wr_data;
	GPIO_SetBits(LCD_WR_PORT,LCD_WR_PIN);   //WR=1
	Delay(1);	
  GPIO_SetBits(LCD_CS_PORT,LCD_CS_PIN);   //CS=1
}

void SSD1306_WriteCommand(uint8_t wr_command)
{
	GPIO_ResetBits(LCD_DC_PORT,LCD_DC_PIN);    //DC=0
  GPIO_ResetBits(LCD_CS_PORT,LCD_CS_PIN);  //CS=0
	
  GPIO_ResetBits(LCD_WR_PORT,LCD_WR_PIN);  //WR=0
	Delay(1);
	GPIOB->ODR =  (GPIOB->IDR & 0xFF00) | wr_command;
	GPIO_SetBits(LCD_WR_PORT,LCD_WR_PIN);  //WR=1
	Delay(1);	
  GPIO_SetBits(LCD_CS_PORT,LCD_CS_PIN);  //CS=1
}

void SSD1306_Init(void)
{
  GPIO_InitTypeDef        GPIO_InitStructure;
  /* GPIO	Periph clock enable */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
	
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
	
  GPIO_InitStructure.GPIO_Pin = LCD_RD_PIN | LCD_WR_PIN | LCD_DC_PIN | LCD_CS_PIN | LCD_RES_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);	
	
	Delay(100);
	SSD1306_Reset();
	
	Delay(100);
	
    // Init OLED
    SSD1306_WriteCommand(0xAE); //display off

    SSD1306_WriteCommand(0x20); //Set Memory Addressing Mode   
    SSD1306_WriteCommand(0x10); // 00,Horizontal Addressing Mode; 01,Vertical Addressing Mode;
                                // 10,Page Addressing Mode (RESET); 11,Invalid

    SSD1306_WriteCommand(0xB0); //Set Page Start Address for Page Addressing Mode,0-7

#ifdef SSD1306_MIRROR_VERT
    SSD1306_WriteCommand(0xC0); // Mirror vertically
#else
    SSD1306_WriteCommand(0xC8); //Set COM Output Scan Direction
#endif

    SSD1306_WriteCommand(0x00); //---set low column address
    SSD1306_WriteCommand(0x10); //---set high column address

    SSD1306_WriteCommand(0x40); //--set start line address - CHECK

    SSD1306_WriteCommand(0x81); //--set contrast control register - CHECK
    SSD1306_WriteCommand(0xFF);

#ifdef SSD1306_MIRROR_HORIZ
    SSD1306_WriteCommand(0xA0); // Mirror horizontally
#else
    SSD1306_WriteCommand(0xA1); //--set segment re-map 0 to 127 - CHECK
#endif

#ifdef SSD1306_INVERSE_COLOR
    SSD1306_WriteCommand(0xA7); //--set inverse color
#else
    SSD1306_WriteCommand(0xA6); //--set normal color
#endif

    SSD1306_WriteCommand(0xA8); //--set multiplex ratio(1 to 64) - CHECK
    SSD1306_WriteCommand(0x3F); //

    SSD1306_WriteCommand(0xA4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content

    SSD1306_WriteCommand(0xD3); //-set display offset - CHECK
    SSD1306_WriteCommand(0x00); //-not offset

    SSD1306_WriteCommand(0xD5); //--set display clock divide ratio/oscillator frequency
    SSD1306_WriteCommand(0xF0); //--set divide ratio

    SSD1306_WriteCommand(0xD9); //--set pre-charge period
    SSD1306_WriteCommand(0x22); //

    SSD1306_WriteCommand(0xDA); //--set com pins hardware configuration - CHECK
    SSD1306_WriteCommand(0x12);

    SSD1306_WriteCommand(0xDB); //--set vcomh
    SSD1306_WriteCommand(0x20); //0x20,0.77xVcc

    SSD1306_WriteCommand(0x8D); //--set DC-DC enable
    SSD1306_WriteCommand(0x14); //
    SSD1306_WriteCommand(0xAF); //--turn on SSD1306 panel
}

void SSD1306_Clear(uint8_t color)
{
    uint8_t i=0,x=0;
    for(i = 0; i < 8; i++) {
        SSD1306_WriteCommand(0xB0 + i);
        SSD1306_WriteCommand(0x00);
        SSD1306_WriteCommand(0x10);
			  for(x=0;x<128;x++)
			     if(color) SSD1306_WriteData(0xFF); else SSD1306_WriteData(0x00);
			  
    }

}

LCD bir türlü açılmadı. LCD'init ettikten sonra ekranı tamamen 1 ile dolduruyorum. Çalışması KS0108'e çok benziyor. Hız ile ilgili bir sorun olmasa gerek.
Yazdığım init rutinleri bu şekilde

void SSD1306_Reset(void)
{
  GPIO_SetBits(LCD_CS_PORT,LCD_CS_PIN);  //CS=1
	
	GPIO_ResetBits(LCD_RES_PORT,LCD_RES_PIN);  //RES=0
	Delay(10);
	GPIO_SetBits(LCD_RES_PORT,LCD_RES_PIN);    //RES=1
}

void SSD1306_WriteData(uint8_t wr_data)
{
	GPIO_SetBits(LCD_DC_PORT,LCD_DC_PIN);   //DC=1
  GPIO_ResetBits(LCD_CS_PORT,LCD_CS_PIN); //CS=0
  GPIO_ResetBits(LCD_WR_PORT,LCD_WR_PIN); //WR=0
	Delay(1);
	GPIOB->ODR =  (GPIOB->IDR & 0xFF00) | wr_data;
	GPIO_SetBits(LCD_WR_PORT,LCD_WR_PIN);   //WR=1
	Delay(1);	
  GPIO_SetBits(LCD_CS_PORT,LCD_CS_PIN);   //CS=1
}

void SSD1306_WriteCommand(uint8_t wr_command)
{
	GPIO_ResetBits(LCD_DC_PORT,LCD_DC_PIN);    //DC=0
  GPIO_ResetBits(LCD_CS_PORT,LCD_CS_PIN);  //CS=0
	
  GPIO_ResetBits(LCD_WR_PORT,LCD_WR_PIN);  //WR=0
	Delay(1);
	GPIOB->ODR =  (GPIOB->IDR & 0xFF00) | wr_command;
	GPIO_SetBits(LCD_WR_PORT,LCD_WR_PIN);  //WR=1
	Delay(1);	
  GPIO_SetBits(LCD_CS_PORT,LCD_CS_PIN);  //CS=1
}

void SSD1306_Init(void)
{
  GPIO_InitTypeDef        GPIO_InitStructure;
  /* GPIO	Periph clock enable */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
	
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
	
  GPIO_InitStructure.GPIO_Pin = LCD_RD_PIN | LCD_WR_PIN | LCD_DC_PIN | LCD_CS_PIN | LCD_RES_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);	
	
	Delay(100);
	SSD1306_Reset();
	
	Delay(100);
	
    // Init OLED
    SSD1306_WriteCommand(0xAE); //display off

    SSD1306_WriteCommand(0x20); //Set Memory Addressing Mode   
    SSD1306_WriteCommand(0x10); // 00,Horizontal Addressing Mode; 01,Vertical Addressing Mode;
                                // 10,Page Addressing Mode (RESET); 11,Invalid

    SSD1306_WriteCommand(0xB0); //Set Page Start Address for Page Addressing Mode,0-7

#ifdef SSD1306_MIRROR_VERT
    SSD1306_WriteCommand(0xC0); // Mirror vertically
#else
    SSD1306_WriteCommand(0xC8); //Set COM Output Scan Direction
#endif

    SSD1306_WriteCommand(0x00); //---set low column address
    SSD1306_WriteCommand(0x10); //---set high column address

    SSD1306_WriteCommand(0x40); //--set start line address - CHECK

    SSD1306_WriteCommand(0x81); //--set contrast control register - CHECK
    SSD1306_WriteCommand(0xFF);

#ifdef SSD1306_MIRROR_HORIZ
    SSD1306_WriteCommand(0xA0); // Mirror horizontally
#else
    SSD1306_WriteCommand(0xA1); //--set segment re-map 0 to 127 - CHECK
#endif

#ifdef SSD1306_INVERSE_COLOR
    SSD1306_WriteCommand(0xA7); //--set inverse color
#else
    SSD1306_WriteCommand(0xA6); //--set normal color
#endif

    SSD1306_WriteCommand(0xA8); //--set multiplex ratio(1 to 64) - CHECK
    SSD1306_WriteCommand(0x3F); //

    SSD1306_WriteCommand(0xA4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content

    SSD1306_WriteCommand(0xD3); //-set display offset - CHECK
    SSD1306_WriteCommand(0x00); //-not offset

    SSD1306_WriteCommand(0xD5); //--set display clock divide ratio/oscillator frequency
    SSD1306_WriteCommand(0xF0); //--set divide ratio

    SSD1306_WriteCommand(0xD9); //--set pre-charge period
    SSD1306_WriteCommand(0x22); //

    SSD1306_WriteCommand(0xDA); //--set com pins hardware configuration - CHECK
    SSD1306_WriteCommand(0x12);

    SSD1306_WriteCommand(0xDB); //--set vcomh
    SSD1306_WriteCommand(0x20); //0x20,0.77xVcc

    SSD1306_WriteCommand(0x8D); //--set DC-DC enable
    SSD1306_WriteCommand(0x14); //
    SSD1306_WriteCommand(0xAF); //--turn on SSD1306 panel
}

void SSD1306_Clear(uint8_t color)
{
    uint8_t i=0,x=0;
    for(i = 0; i < 8; i++) {
        SSD1306_WriteCommand(0xB0 + i);
        SSD1306_WriteCommand(0x00);
        SSD1306_WriteCommand(0x10);
			  for(x=0;x<128;x++)
			     if(color) SSD1306_WriteData(0xFF); else SSD1306_WriteData(0x00);			  
    }
}

Bağlantıları birkaç defa kontrol ettim hata yok gibi. Datasheet'de 8080 haberleşmesi için BS0=0, BS1=1, BS2=1 olması gerektiği gibi yazıyor. Emin değilim belkide LCD bozuldu, Çünkü sabahtan beri baya uğraştım. Son zamanlarda LCD'ye data gönderirken LCD data portundan çok fazla akım çekmeye başladı. Yani kartın normalde çektiği akım 20ma civarı iken Data gönderirken 120ma civarına çıkıyor. LCD'yi söktüm, Başka bir LCD ile deneyeceğim. Bu sefer SPI ile haberleşmeyi deneyeceğim. Bağlantıları bakır tellerle el ile yaptığım için hata yapma oranım az olur diye düşünüyorum.

Datasheette C1, C2 kapasiteleri 1uF denilmiş ama uygulamalarıun çoğunda 2.2uF takıldığını gördüm. Bende 2.2uF taktım. Kapasitelerin hepsi Tantal IREF direnci ise 390K

Acaba daha önce bu lcd ile paralel haberleşen oldumu? Püf noktası dikkat etmem gereken birşey varmı?