当前位置:网站首页>基于STC8G1K08的0.96寸IIC液晶屏驱动程序

基于STC8G1K08的0.96寸IIC液晶屏驱动程序

2022-07-07 09:02:00 sunflower-ly

STC8G系列单片机内部集成了一个I2C串行控制器。

STC8G系列的I2C总线提供了两种操作模式:主机模式(SCL为输出口,发送同步时钟信号);从机模式(SCL为输入口,接收同步时钟信号)。

I2C相关寄存器:

I2C主机模式相关寄存器:

I2CCFG:配置寄存器,总线速度控制

符号

描述

地址

B7

B6

B5

B4

B3

B2

B1

B0

I2CCFG

配置寄存器

FE80H

ENI2C

MSSL

MSSPEED[5:0]

ENI2C:I2C功能使能控制位

0:禁止I2C功能

1:允许I2C功能

MSSL:I2C工作模式选择位

0:从机模式

1:主机模式

MSSPEED[5:0]:I2C总线速度控制

I2C总线速度=FOSC/2/(MSSPEEED*2+4)

注意:只有当I2C模块在主机模式时,MSSPEED参数设置的等待参数才有效。此参数主要用于I2C起始信号和中止信号的建立和保持时间的设置。

I2CMSCR:主机控制寄存器

符号

描述

地址

B7

B6

B5

B4

B3

B2

B1

B0

I2CMSCR

主机控制寄存器

FE81H

EMSI

-

-

-

MSCMD[3:0]

EMSI:主机模式中断使能控制位

0:关闭主机模式的中断

1:开启主机模式的中断

MSCMD[3:0]:主机命令

0000:待机,无动作

0001:起始指令,发送起始信号。

0010:发送数据指令

0011:接收ACK命令

0100:接收数据命令

0101:发送ACK命令

0110:停止命令,发送停止信号。

1001:起始命令+发送数据命令+接收ACK命令

1010:发送数据命令+接收ACK命令

1011:接收数据命令发送ACK命令

1100:接收数据命令+发送NAK命令

I2CMSAUX:主机辅助控制寄存器

符号

描述

地址

B7

B6

B5

B4

B3

B2

B1

B0

I2CMSAUX

主机辅助控制寄存器

FE88H

-

-

-

-

-

-

-

WDTA

WDTA:主机模式,I2C数据自动发送允许位。

I2CMSST:主机状态寄存器

符号

描述

地址

B7

B6

B5

B4

B3

B2

B1

B0

I2CMSST

主机状态寄存器

FE82H

MSBUSY

MSIF

-

-

-

-

MSACKI

MSACKO

MSBUSY:主机模式I2C控制状态位

MSIF:主机模式的中断请求位

MSACKI:主机模式时,发送0011命令到I2CMSCR的MSMD位后所接收到的ACK数据。

MSACKO:主机模式时,准备将要发送的的ACK信号。

I2C从机模式相关寄存器:

I2CSLCR:控制寄存器

符号

描述

地址

B7

B6

B5

B4

B3

B2

B1

B0

I2CSLCR

从机控制寄存器

FE83H

-

ESTAI

ERXI

ETXI

ESTOI

-

-

SLRST

ESTAI:从机模式接收START信号中断允许位

ERXI:从机模式时接收到一个字节后中断允许位

ETXI:从机模式时发送一个字节后的中断允许位

ESTOI:从机模式时接收STOP信号的中断允许位

SLRST:复位从机模式

I2CSLST:状态寄存器

符号

描述

地址

B7

B6

B5

B4

B3

B2

B1

B0

I2CSLST

状态寄存器

FE84H

SLBUSY

STAIF

RXIF

TXIF

STOIF

-

SLACKI

SLACKO

SLBUSY:I2C控制器状态位,空闲和忙碌

STAIF:从机模式接收到START信号后的中断请求位

RXIF:从机模式时接收到1字节的数据后的中断请求位。

TXIF:从机模式时发送完成一个字节的数据后的中断请求位。

STOIF:从机模式接收到STOP信号后的中断请求位。

SLACKI:从机模式时,接收到的ACK数据。

SLACKO:从机模式时,准备将要发送的ACK信号。

I2CSLADR:地址寄存器

符号

描述

地址

B7

B6

B5

B4

B3

B2

B1

B0

I2CSLADR

从机地址寄存器

FE85H

IACSLADR[7:1]

MA

IACSLADR[7:1]:从机设备地址

MA:从机设备地址比较控制

0:设备地址必须与I2CSLADR[7:1]相同

1:忽略I2CSLADR[7:1]中的设置,接收所有的设备地址

I2C数据寄存器

I2CTXD:发送数据寄存器

符号

描述

地址

B7

B6

B5

B4

B3

B2

B1

B0

I2CTXD

发送数据寄存器

FE86H

I2CRXD:接收数据寄存器

符号

描述

地址

B7

B6

B5

B4

B3

B2

B1

B0

I2CRXD

接收数据寄存器

FE87H

分步例程:

液晶屏为:0.96寸的IIC屏幕

//硬件IIC初始化

void iicInit()
{
    P_SW2 = 0xc0;   // SCL(3.2) SDA(3.3)
    I2CCFG = 0xff;  //开启iic 主机模式 最高速度
    I2CMSST = 0x00; //关中断 待机模式
}

//延时函数,单片机的晶振为30M

void delay_ms(unsigned int ms)
{                        
        while(ms)
        {
          unsigned char i=39, j=243;
          do
          {while (--j);}
          while (--i);
                ms--;
          }
         return;
}

//等待空闲

void Wait() 
{
    while (!(I2CMSST & 0x40));
    I2CMSST &= ~0x40;
}

//起始信号

void IIC_Start()
{
    I2CMSCR = 0x01;     //发送START命令
    Wait();
}

//结束信号

void IIC_Stop()
{
    I2CMSCR = 0x06;     //发送STOP命令
    Wait();
}

//等待并发送ACK

void IIC_Wait_Ack()
{
    I2CMSCR = 0x00;                             //设置ACK信号
    I2CMSCR = 0x05;                             //发送ACK命令
    Wait();
}

//写字节

void Write_IIC_Byte(unsigned char dat)
{
    I2CTXD = dat;         //写数据到数据缓冲区
    I2CMSCR = 0x02;       //发送SEND命令
    Wait();
}

//写指令

void Write_IIC_Command(unsigned char IIC_Command)
{
       IIC_Start();
       Write_IIC_Byte(0x78);            //Slave address,SA0=0
       IIC_Wait_Ack();       
       Write_IIC_Byte(0x00);           //write command
       IIC_Wait_Ack();       
       Write_IIC_Byte(IIC_Command);
       IIC_Wait_Ack();       
       IIC_Stop();
}

//写数据

void Write_IIC_Data(unsigned char IIC_Data)
{
        IIC_Start();
        Write_IIC_Byte(0x78);                        //D/C#=0; R/W#=0
        IIC_Wait_Ack();       
        Write_IIC_Byte(0x40);                        //write data
        IIC_Wait_Ack();       
        Write_IIC_Byte(IIC_Data);
        IIC_Wait_Ack();       
        IIC_Stop();
}

//写入OLED的字节

void OLED_WR_Byte(unsigned dat,unsigned cmd)
{
      if(cmd)
      {
           Write_IIC_Data(dat);
      }
      else
      {
                                               
           Write_IIC_Command(dat);                                                         
      }
}

//写入指定字模

void fill_picture(unsigned char dat)
{
         unsigned char m,n;
         for(m=0;m<8;m++)
         {
                   OLED_WR_Byte(0xb0+m,0);                //page0-page1
                   OLED_WR_Byte(0x00,0);                //low column start address
                   OLED_WR_Byte(0x10,0); 
                   for(n=0;n<128;n++)
                   {
                       OLED_WR_Byte(dat,1);
                   }
         }
}

//清除OLED屏幕

void OLED_Clear(void) 
{ 
        u8 i,n;                    
        for(i=0;i<8;i++) 
        { 
                OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
                OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
                OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址  
                for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA);
        } //更新显示

}

//初始化SSD1306                                           

void OLED_Init(void)
{      
         //关闭显示
        OLED_WR_Byte(0xAE,OLED_CMD);//--display off

         //设置时钟分频和RC振荡器频率
         OLED_WR_Byte(0xD5,OLED_CMD);//set osc division
         OLED_WR_Byte(0x80,OLED_CMD);//

         //设置多路传输比率
         OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
         OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty    

         //设置显示偏移,不偏移设置0
         OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset
         OLED_WR_Byte(0x00,OLED_CMD);//
   
         //设置显示开始行
         OLED_WR_Byte(0x40,OLED_CMD);//--set start line address 
      
         //启用电荷泵(0x10禁用电荷泵)
         OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable
         OLED_WR_Byte(0x14,OLED_CMD);//
        
         //左右方向显示,正常显示0x01(0xA0左右反置)
         OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap
        
         //上下方向显示,正常显示0xc8(0xc0上下反置)
         OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction
      
         //设置列引脚的硬件配置
         OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion
         OLED_WR_Byte(0x12,OLED_CMD);//
        
         //设置对比度【第二个最大对比度】
         OLED_WR_Byte(0x81,OLED_CMD); // contract control
         OLED_WR_Byte(0xFF,OLED_CMD);//--128

         //设置预充电器件的持续时间
         OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period
         OLED_WR_Byte(0xF1,OLED_CMD);//
        
         //调整Vcomif调节器的输出
         OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh
         OLED_WR_Byte(0x30,OLED_CMD);//
               
         OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
         OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
       
         //设置页地址
         OLED_WR_Byte(0xB0,OLED_CMD);//--set page address       
         OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode off
         OLED_WR_Byte(0x05,OLED_CMD);//
         OLED_WR_Byte(0xA4,OLED_CMD);//
        
         //设置为正常显示,1:显示,0:不显示
         OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverse
       
         //打开OLED
         OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
         OLED_Clear();
} 

主函数:

int main(void)
{
   iicInit();
   OLED_Init();
   while(1)
   {
        fill_picture(0xff);
        delay_ms(1000);
        fill_picture(0x00);
        delay_ms(200);
    }

}

 在编译过程中发现,液晶屏不显示,最终结果是引脚未初始化。

    P5M0=0xff;
    P5M1=0x00;

加入单片机引脚初始化测试成功。

原网站

版权声明
本文为[sunflower-ly]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_39727831/article/details/125616581