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
(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.
(https://i.postimg.cc/LsLsndH3/Ekran-Al-nt-s.jpg)
(https://i.postimg.cc/KYSGX9nk/Ekran-Al-nt-s-2.jpg)
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ı?