Type:LQ12864
單點長寬:0.154mm
焊盤:22
電源類型:
VCC:C=circuit 表示電路的意思, 即接入電路的電壓
VDD:D=device 表示器件的意思, 即器件內部的工作電壓;
VSS:S=series 表示公共連接的意思,通常指電路公共接地端電壓
液晶裸片大同小異,本以為沒什么好研究的,但之前周楚侖大神發現了一個底層BUG,導致所有像素點均反向且不可逆,這讓我很疑惑,於是今天靜下心來看了下底層。
關於兩個基本函數;
void OLED_Write_Command(unsigned char Cmd);
void OLED_Write_Data(unsigned char Data);
基本上所有液晶底層函數均基於這兩個函數,所以先從這兩個函數入手看看代碼。
- 首先先看一下四個管腳定義
OLED_SCL 或者 ODO 或者 CLK //時鍾
OLED_SDA 或者 OD1 或者 MOSI //數據
OLED_RST 或者 ORST_2 或者 CS //復位
OLED_DC 或者 ODC_2 或者 DC //數據/命令控制 (使能位)
- 然后看數據寫入函數
void OLED_Write_Data(unsigned char Data)
{
unsigned char Temp_i=8;
OLED_DC=1;;
OLED_SCL=0;
while(Temp_i--)
{
if(Data&0x80){OLED_SDA=1;}
else{OLED_SDA=0;}
OLED_SCL=1;
asm("nop");;
asm("nop");;
asm("nop");;
OLED_SCL=0;;
Data<<=1;
}
大概是這樣,發現asm("nop");這個延時語句沒什么特別大的作用,刪掉。另外while語句由於我天生C語言缺陷看不懂,我只好改回for循環的格式。稍微改動如下(並不改動邏輯):
void OLED_Write_Data(unsigned char Data)
{
unsigned char i;
OLED_DC=1;
for(i=0;i<8;i++)
{
if((Data << i) & 0x80)
{OLED_SDA = 1;}
else
{OLED_SDA = 0;}
OLED_SCL = 0;
OLED_SCL = 1;
}
若改動SCL時鍾的語句,則產生花屏或者無法再寫入,改動DC使能語句,同樣花屏,但是略有不同。至於語句就很簡單了,自己看,乖。
- 然后是命令寫入函數
同樣對該函數進行改寫
void OLED_Write_Command(unsigned char Cmd)
{
unsigned char i;
OLED_DC=0;
for(i=0;i<8;i++)
{
if((Cmd << i) & 0x80)
{OLED_SDA = 1;}
else
{OLED_SDA = 0;}
OLED_SCL = 0;
OLED_SCL = 1;
}
}
看起來除了DC=0以外和數據寫入函數沒有不同。
由此看來兩個最底層的函數都只是寫入一個數,但前者是用來點亮液晶,后者是用來配置寄存器(我猜的)。
- 再來是初始化函數
void OLED_Init(void)
{
unsigned int Temp_Count;
gpio_init(PTC12,GPO,0); //OLED用IO口初始化為輸出
gpio_init(PTC14,GPO,0);
gpio_init(PTC17,GPO,0);
gpio_init(PTD0,GPO,0);
OLED_SCL=1;
OLED_RST=0;
for(Temp_Count=0;Temp_Count<50000;Temp_Count++);
OLED_RST=1;
//從上電到下面開始初始化要有足夠的時間,即等待RC復位完畢
OLED_Write_Command(0xAE|0x00); // Display Off (0x00/0x01)
OLED_Write_Command(0xD5);OLED_Write_Command(0x80); // Set Clock as 100 Frames/Sec
OLED_Write_Command(0xA8);OLED_Write_Command(0x3F); // 1/64 Duty (0x0F~0x3F)
OLED_Write_Command(0xD3);OLED_Write_Command(0x00); // Shift Mapping RAM Counter (0x00~0x3F)
OLED_Write_Command(0x40|0x00); // Set Mapping RAM Display Start Line (0x00~0x3F)
OLED_Write_Command(0x8D);OLED_Write_Command(0x10|0x04); // Enable Embedded DC/DC Converter (0x00/0x04)
OLED_Write_Command(0x20);OLED_Write_Command(0x02); // Set Page Addressing Mode (0x00/0x01/0x02)
OLED_Write_Command(0xA0|0x01); // Set SEG/Column Mapping 0x00左右反置 0x01正常
OLED_Write_Command(0xC0|0x08); // Set COM/Row Scan Direction 0x00上下反置 0x08正常
OLED_Write_Command(0xDA);OLED_Write_Command(0x02|0x10); // Set Sequential Configuration (0x00/0x10)
OLED_Write_Command(0x81);OLED_Write_Command(0xCF); // Set SEG Output Current
OLED_Write_Command(0xD9);OLED_Write_Command(0xF1); // Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
OLED_Write_Command(0xDB);OLED_Write_Command(0x40); // Set VCOM Deselect Level
OLED_Write_Command(0xA4|0x00); // Disable Entire Display On (0x00/0x01)
OLED_Write_Command(0xA6|0x00); // Disable Inverse Display On (0x00/0x01)
OLED_Write_Command(0xAE|0x01); // Display On (0x00/0x01)
OLED_Clear(); // 初始清屏
OLED_Set_Pos(0,0);
}
然后發現
OLED_Write_Command(0xA6|0x00); // Disable Inverse Display On (0x00/0x01)這一項
修改0x00為0x01后圖像顏色反向。
- 再看周楚侖大神排出BUG的函數
void OLED_Set_Pos(unsigned char x,unsigned char y)
{
OLED_Write_Command(0xb0+y);
OLED_Write_Command(((x&0xf0)>>4)|0x10);
OLED_Write_Command(x&0x0f);
}
由於楚侖大神,Set了一個未定義的數,導致函數在運行的過程中隨意輸入命令,導致配置出現異常。
具體細節就不再深挖了,雖然到此還未能真正解決問題,但楚侖大神說他要發一篇文章,所以我的好奇心止於此了。
(本文章由瘋狂的小空出品,轉載請注明出處。
文章鏈接:http://www.cnblogs.com/sillykog/p/5827784.html
作者:陳默含)