首页 > 代码库 > 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)