這個是三星的主控S6D1121彩屏(240*320*18bit,262Kcr)的彩屏的驅動程序.
采用的是80System+16bit接口
不知道是什么原因, 這個主控網上很少有資料,我也是看了好久的DS才明白了一些(全英文, 基本沒中文資料, 反正是不好找到)
這是我接觸的第一塊彩屏哦~~
如果有用這個芯片的, 可能會有些方便, 也方便交流下使用經驗.
這里總共分4個文件:
common.c,common.h:一些公共的包含與定義,函數
s6d1121.c,s6d1121.h:主控芯片驅動程序
這里只是驅動,關於圖形接口將在下一篇文章中貼出代碼
(圖形接口已經寫好了,見這里:http://www.cnblogs.com/nbsofer/archive/2012/12/09/2809401.html)
該代碼僅供51單片機測試使用, 需要大量的優化, 我已經把優化后的代碼移植到MSP430上去了.
由於51刷屏太慢,加上沒時間,所以沒有更新51版本的源代碼,見諒~
//common.h - 一些公用的定義,函數等 #ifndef __COMMON_H__ #define __COMMON_H__ #include <reg52.h> #include <intrins.h> typedef unsigned int uint; typedef unsigned char uchar; void delay_us(uint us); void delay_ms(uint ms); #endif// !__COMMON_H__
//common.c #include "common.h" void delay_ms(uint ms) { uchar k; while(ms--){ for(k=125; k>0; k--){ _nop_(); } } } void delay_us(uint us) { while(us--){ _nop_(); } }
//s6d1121.h //S6D1121.h //S6D1121驅動程序 //應用層請不要調用 //應調用GDI接口 // //女孩不哭 QQ:191035066 //2012-11-05 #ifndef __S6D1121_H__ #define __S6D1121_H__ #include "common.h" void LCD_SetAddress(uint x, uint y, uint width, uint height); void LCD_WriteBus(uint dat); void LCD_WriteCmdWithData(uchar cmd, uint value); void LCD_WriteData(uint dat); void LCD_WriteCmd(uchar cmd); uint LCD_ReadBus(void); uint LCD_ReadData(void); void LCD_Init(void); #endif// !__S6D1121_H__
//s6d1121.c /* 文件:S6D1121.c * 功能:三星S6D1121主控彩屏驅動程序 * 版本:1.0 * 作者:女孩不哭 * Q--Q:191035066 * 時間:2012-11-05 * 說明:這里是底層驅動程序,用戶不應該隨便調用 * 請調用編寫的圖形接口程序 * 參考:http://www.elecfreaks.com/wiki/index.php?title=2.4%22_TFT_LCD:_TFT01-2.4 */ #include "common.h" #include "s6d1121.h" //I/O口定義,除*_RST外,均Active Low sbit LCD_RST= P2^0; //復位 sbit LCD_CS = P2^1; //片選 sbit LCD_RD = P2^2; //讀取 sbit LCD_WR = P2^3; //寫入 sbit LCD_RS = P2^4; //寄存器/數據選擇 //數據總線端口定義 //如果使用16位總線,需要宏定義:BUS_16 //當使用8位總線時,僅*_HI有效 #define LCD_DATA_PORT_HI P0 #define LCD_DATA_PORT_LOW P1 //初始化,初始化之前 //MCU應該延時一段時間 //以使電源穩定 void LCD_Init(void) { LCD_RST = 1; delay_ms(5); LCD_RST = 0; delay_ms(5); LCD_RST = 1; LCD_CS = 1; LCD_RD = 1; LCD_WR = 1; delay_ms(5); LCD_CS = 0;//片選使能 //詳細的說明見一開始的網址 LCD_WriteCmdWithData(0x11,0x2004); LCD_WriteCmdWithData(0x13,0xcc00); LCD_WriteCmdWithData(0x15,0x2600); LCD_WriteCmdWithData(0x14,0x252a); LCD_WriteCmdWithData(0x12,0x0033); LCD_WriteCmdWithData(0x13,0xcc04); delay_ms(1); LCD_WriteCmdWithData(0x13,0xcc06); delay_ms(1); LCD_WriteCmdWithData(0x13,0xcc4f); delay_ms(1); LCD_WriteCmdWithData(0x13,0x674f); LCD_WriteCmdWithData(0x11,0x2003); delay_ms(1); LCD_WriteCmdWithData(0x30,0x2609); LCD_WriteCmdWithData(0x31,0x242c); LCD_WriteCmdWithData(0x32,0x1F23); LCD_WriteCmdWithData(0x33,0x2425); LCD_WriteCmdWithData(0x34,0x2226); LCD_WriteCmdWithData(0x35,0x2523); LCD_WriteCmdWithData(0x36,0x1C1A); LCD_WriteCmdWithData(0x37,0x131D); LCD_WriteCmdWithData(0x38,0x0B11); LCD_WriteCmdWithData(0x39,0x1210); LCD_WriteCmdWithData(0x3A,0x1315); LCD_WriteCmdWithData(0x3B,0x3619); LCD_WriteCmdWithData(0x3C,0x0D00); LCD_WriteCmdWithData(0x3D,0x000D); LCD_WriteCmdWithData(0x16,0x0007); LCD_WriteCmdWithData(0x02,0x0013); LCD_WriteCmdWithData(0x03,0x0003); LCD_WriteCmdWithData(0x01,0x0127); delay_ms(1); LCD_WriteCmdWithData(0x08,0x0303); LCD_WriteCmdWithData(0x0A,0x000B); LCD_WriteCmdWithData(0x0B,0x0003); LCD_WriteCmdWithData(0x0C,0x0000); LCD_WriteCmdWithData(0x41,0x0000); LCD_WriteCmdWithData(0x50,0x0000); LCD_WriteCmdWithData(0x60,0x0005); LCD_WriteCmdWithData(0x70,0x000B); LCD_WriteCmdWithData(0x71,0x0000); LCD_WriteCmdWithData(0x78,0x0000); LCD_WriteCmdWithData(0x7A,0x0000); LCD_WriteCmdWithData(0x79,0x0007); LCD_WriteCmdWithData(0x07,0x0053); LCD_WriteCmdWithData(0x79,0x0000); LCD_WriteCmd(0x22); LCD_CS = 1;//關閉片選 delay_ms(50); LCD_CS = 0; } /* 函數:寫命令 * 參數:uchar cmd:寄存器地址 * 返回:(無) * 說明:RS為低為寫寄存器 */ void LCD_WriteCmd(uchar cmd) { LCD_RS = 0;//寫命令模 LCD_WriteBus((uint)cmd); } /* 函數:寫數據值 * 參數:uint dat:16位的數據 * 返回:(無) * 說明:RS應為高 */ void LCD_WriteData(uint dat) { LCD_RS = 1;//寫數據 LCD_WriteBus(dat); } /*uint LCD_ReadData(void) { LCD_RS = 1; return LCD_ReadBus(); } uint LCD_ReadBus(void) { uint ret=0; #ifdef BUS_16 LCD_RD = 0; LCD_RD = 1; ret = LCD_DATA_PORT_HI; ret <<= 8; ret |= LCD_DATA_PORT_LOW; #else LCD_RD = 0; LCD_RD = 1; ret = LCD_DATA_PORT_HI; ret <<= 8; LCD_RD = 0; LCD_RD = 1; ret |= LCD_DATA_PORT_HI; #endif return ret; }*/ /* 函數:寫寄存器 * 參數: * uchar cmd:寄存器地址(8位) * uint value:寫給寄存器的值(16位) * 返回:(無) */ void LCD_WriteCmdWithData(uchar cmd, uint value) { LCD_WriteCmd((uchar)cmd); //寫寄存器地址 LCD_WriteData(value); //寫寄存器值 } //把命令/數據向總線寫入 void LCD_WriteBus(uint dat) { #ifdef BUS_16 //16位總線模式 LCD_DATA_PORT_HI = (uchar)(dat>>8); LCD_DATA_PORT_LOW = (uchar)dat; LCD_WR = 0; LCD_WR = 1; //S6D1121在每次的WR的上升沿讀取數據 #else //此時僅高字節有效 //先寫高字節,再寫低字節 LCD_DATA_PORT_HI = (uchar)(dat>>8); LCD_WR = 0; LCD_WR = 1; LCD_DATA_PORT_HI = (uchar)dat; LCD_WR = 0; LCD_WR = 1; #endif } /* * 函數:設定寫入數據的區域 * 參數: * int x:X坐標(范圍:0~239) * int y:Y坐標(范圍:0~319) * uint width:寬 * uint height:高 * 返回:(無) * 說明:(x1,y1; x2,y2)兩點構成一個矩形 * 設定好區域后,在下一個指令前應該寫緩沖區 */ void LCD_SetAddress(uint x, uint y, uint width, uint height) { LCD_WriteCmdWithData(0x46, (x+width-1)<<8|x); //一次性設定x1,x2(高) LCD_WriteCmdWithData(0x47, y+height-1); //y2 LCD_WriteCmdWithData(0x48, y); //y1 LCD_WriteCmdWithData(0x20, x); //設定RAM開始寫的地址 LCD_WriteCmdWithData(0x21, y); LCD_WriteCmd(0x22); //設定好寫寄存器,開始寫 }
女孩不哭(QQ:191035066)@2012-11-26 16:16:55 http://www.cnblogs.com/nbsofer