首页 > 代码库 > OLED裸屏学习(2016.8.31)
OLED裸屏学习(2016.8.31)
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了一个未定义的数,导致函数在运行的过程中随意输入命令,导致配置出现异常。
具体细节就不再深挖了,虽然到此还未能真正解决问题,但楚仑大神说他要发一篇文章,所以我的好奇心止于此了。
OLED裸屏学习(2016.8.31)