天天看點

單片機—HLK-W801并口驅動ST7789

大家好,又見面了,我是你們的朋友全棧君。

目的

買了這塊并口的螢幕,是為了做一個nes模拟器的遊戲機,之前用的SPI的螢幕,顯示遊戲畫面還是比較耗時,畢竟是串行資料,是以準備試一下并行接口的螢幕,順便了解一下并口8080的驅動方式。

并口協定

8080 時序也叫因特爾總線,一般mcu(mpu)模式的lcd上。

Inter總線控制線有四根:

  • RD:寫使能
  • WR:讀使能
  • DC(RS): – 資料/指令
  • CS:片選

    然後就是若幹根資料線,例如8或者16根。

    寫時序圖

單片機—HLK-W801并口驅動ST7789

讀時序圖

單片機—HLK-W801并口驅動ST7789

這裡值得注意的就是,資料的讀寫,都是在RD或者WR的上升沿有效,這個很重要。是以我們可以先寫資料,再制造一個上升沿,或者先拉低,寫入資料後再拉高都是可以的。但是從圖上來看,推薦前者。

ST7789 引腳定義

ST7789的用法有好幾種,今天隻說一下16bit的并口驅動。

硬體連接配接

#define P_LEDA_PORT GPIOA
#define P_LEDA_PIN GPIO_PIN_5 //背光
#define P_RD_PORT GPIOA
#define P_RD_PIN GPIO_PIN_9 //RD
#define P_WR_PORT GPIOA
#define P_WR_PIN GPIO_PIN_10 //WR
#define P_CD_PORT GPIOA
#define P_CD_PIN GPIO_PIN_11 //RS 0是指令 1:資料

#define P_CS_PORT GPIOA
#define P_CS_PIN GPIO_PIN_12 //cs 0是選中

#define P_RESET_PORT GPIOA
#define P_RESET_PIN GPIO_PIN_14 //REST

#define P_DATA_PORT GPIOB
#define P_DATA_PIN 0xFFFF           

複制

其中,

背光,有的螢幕叫BLK,我們可以直接接高電平。

CS,我們可以直接接低電平,預設選中。

RD,我們可以直接拉高電平,不用讀取功能。

CD,有的螢幕叫RS。

資料線,我們用的是GPIOB 0~15。這裡要細心一點,接錯了就會花屏

然後定義如下的控制宏

#define P_CD_LOW P_CD_PORT->DATA &= ~P_CD_PIN
#define P_CD_HIGH P_CD_PORT->DATA |= P_CD_PIN

#define P_RESET_LOW P_RESET_PORT->DATA &= ~P_RESET_PIN
#define P_RESET_HIGH P_RESET_PORT->DATA |= P_RESET_PIN

#define P_WR_LOW P_WR_PORT->DATA &= ~P_WR_PIN
#define P_WR_HIGH P_WR_PORT->DATA |= P_WR_PIN           

複制

這裡是w801的寫法,引腳的高低置位。

ST7789核心函數

LCD顯示屏最基礎的兩個控制 函數,就是寫寄存器和寫資料,

void P_WriteReg(uint16_t reg)
{ 
   
	P_CD_LOW;
	WRITE_REG(P_DATA_PORT->DATA,reg);
	P_WR_LOW;
	P_WR_HIGH;
	P_CD_HIGH;
}

void P_WriteData(uint16_t data)
{ 
   
	WRITE_REG(P_DATA_PORT->DATA,data);
	P_WR_LOW;
	P_WR_HIGH;
}           

複制

這裡我們将控制線的修改,完全放在寫寄存器上,因為寫寄存器用的少,這樣寫資料的時候,就效率高了一些。

然後就是初始化函數

void LCD_Init(void)
{ 
   
	LCD_Reset_On();
	HAL_Delay(120);
	LCD_Reset_Off();

	HAL_Delay(120);
	LCD_WriteReg(0x3A); 	   //65k mode
	LCD_WriteData8(0x05);
	LCD_WriteReg(0xC5); //VCOM
	LCD_WriteData8(0x1A);
	
	LCD_WriteReg(0x36); 				// 螢幕顯示方向設定
	LCD_WriteData8(0x00);
	//-------------ST7789V Frame rate setting-----------//
	LCD_WriteReg(0xb2);
	LCD_WriteData8(0x05);
	LCD_WriteData8(0x05);
	LCD_WriteData8(0x00);
	LCD_WriteData8(0x33);
	LCD_WriteData8(0x33);

	LCD_WriteReg(0xb7);
	LCD_WriteData8(0x35);
	//--------------ST7789V Power setting---------------//
	LCD_WriteReg(0xBB);//VCOM
	LCD_WriteData8(0x3F);

	LCD_WriteReg(0xC0); //Power control
	LCD_WriteData8(0x2c);

	LCD_WriteReg(0xC2);
	LCD_WriteData8(0x01);

	LCD_WriteReg(0xC3);
	LCD_WriteData8(0x0F);//0D gvdd

	LCD_WriteReg(0xC4);
	LCD_WriteData8(0x20);

	LCD_WriteReg(0xC6);
	LCD_WriteData8(0X11);//0x0F

	LCD_WriteReg(0xd0);
	LCD_WriteData8(0xa4);
	LCD_WriteData8(0xa1);

	LCD_WriteReg(0xE8);
	LCD_WriteData8(0x03);

	LCD_WriteReg(0xE9);
	LCD_WriteData8(0x09);
	LCD_WriteData8(0x09);
	LCD_WriteData8(0x08);
	//---------------ST7789V gamma setting-------------//
	LCD_WriteReg(0xE0); //Set Gamma
	LCD_WriteData8(0xD0);
	LCD_WriteData8(0x05);
	LCD_WriteData8(0x09);
	LCD_WriteData8(0x09);
	LCD_WriteData8(0x08);
	LCD_WriteData8(0x14);
	LCD_WriteData8(0x28);
	LCD_WriteData8(0x33);
	LCD_WriteData8(0x3F);
	LCD_WriteData8(0x07);
	LCD_WriteData8(0x13);
	LCD_WriteData8(0x14);
	LCD_WriteData8(0x28);
	LCD_WriteData8(0x30);

	LCD_WriteReg(0XE1); //Set Gamma
	LCD_WriteData8(0xD0);
	LCD_WriteData8(0x05);
	LCD_WriteData8(0x09);
	LCD_WriteData8(0x09);
	LCD_WriteData8(0x08);
	LCD_WriteData8(0x03);
	LCD_WriteData8(0x24);
	LCD_WriteData8(0x32);
	LCD_WriteData8(0x32);
	LCD_WriteData8(0x3B);
	LCD_WriteData8(0x14);
	LCD_WriteData8(0x13);
	LCD_WriteData8(0x28);
	LCD_WriteData8(0x2F);

	LCD_WriteReg(0x11);
	HAL_Delay(120);
	LCD_Clear(0x0000);			 /*先手動清屏再顯示,防止花屏顯示*/
	LCD_WriteReg(0x29); 		//開啟顯示 

}           

複制

其中螢幕方向是可以修改的

LCD_WriteReg(0x36); // 螢幕顯示方向設定

LCD_WriteData8(0x00);

0x00 就是正常的豎屏

0xA0 是向左橫屏

還有兩種0x60, 0xC0 估計是倒置和向右橫屏,有興趣的可以試一下。

易出錯點

16bit驅動最容易出錯的地方就是坐标設定,我以為坐标是16bit的,那麼我就直接寫四個坐标不就行了,恰恰錯了,這裡需要相容8bit的,要把每個16bit分兩次寫入。否則就會出現花屏問題。

這個bug我搞了一天。

void LCD_Address_Set(uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye)
{ 
   
	LCD_WriteReg(0x2a);
	LCD_WriteData(xs>>8);
	LCD_WriteData(xs&0xff);
	LCD_WriteData(xe>>8);
	LCD_WriteData(xe&0xff);
	LCD_WriteReg(0x2b);
	LCD_WriteData(ys>>8);
	LCD_WriteData(ys&0xff);
	LCD_WriteData(ye>>8);
	LCD_WriteData(ye&0xff);
	LCD_WriteReg(0x2c);

}           

複制

代碼提供

《完整代碼下載下傳》

其實是建議大家按照前面的方法自己寫出來,基本的重要地方都已經提供了,是以還是要自己嘗試一下,印象才更深刻。

結束語

誰支援我們偉大複興,誰就是朋友,誰阻攔,那就是敵人。

釋出者:全棧程式員棧長,轉載請注明出處:https://javaforall.cn/128985.html原文連結:https://javaforall.cn