您当前的位置:首页 > 电子 > 光电显示与成像

OLED使用 SSD1306 IIC

时间:08-09来源:作者:点击数:

OLED的使用

1.使用IIC通讯协议进行数据通信

IIC通讯协议
两根总线 SDA数据总线    SCL时钟总线(主机提供)
IIC的起始信号SCL为高电平  SDA由高电平变成低电平  SCL变成低电平
结束信号    SCL为高电平   SDA由低电平变成高电平  
响应信号ACK   系统传输完成一个字节8bit之后 会把SDA总线的控制权给从机
SCL为高电平   SDA为高电平 表示非应答信号
             SDA为低电平  表示应答信号
 SCL为高电平的时候 进行SDA线数据的读取  
 SCL为低电平的时候 进行SDA线数据的转换
  1. 软件模拟IIC的起始信号
void IIC_Start(void)
{
  //起使SCL SDA都是高电平
	OLED_SCL_HIGH();
	OLED_SDA_HIGH();
	i2c_Delay();
	OLED_SDA_LOW();//此时SDA产生开始信号
	i2c_Delay();
	OLED_SCL_LOW();//SCL线也变成了低电平
	i2c_Delay();
}
  1. 软件模拟IIC的结束信号
void IIC_Stop(void)
{
  OLED_SCL_HIGH();
  //	OLED_SCLK_Clr();
	OLED_SDA_LOW();
	i2c_Delay();
	OLED_SDA_HIGH();//产生结束信号	
}
  1. 应答信号
void i2c_Ack(void)
{
	//产生应答信号   SDA线为低电平
	OLED_SDA_LOW();	/* CPU驱动SDA = 0 */
	i2c_Delay();
	OLED_SCL_HIGH();	/* CPU产生1个时钟 */
	i2c_Delay();
	OLED_SCL_LOW();
	i2c_Delay();
	//设置完成应答信号  CPU释放
	OLED_SDA_HIGH();	/* CPU释放SDA总线 */
}

2.OLED函数

  1. 写函数
    使用该函数 进行命令和数据的区分
/*
#define OLED_CMD  0	//写命令
#define OLED_DATA 1	//写数据
*/
void OLED_WR_Byte(unsigned dat,unsigned cmd)
{
	if(cmd){
   Write_IIC_Data(dat);   
	}else {
   Write_IIC_Command(dat);//写命令	
	}
}
  1. 数据区分
    // IIC Write Command 写命令
    IIC设备在数据传输之前都必须识别从机地址。SSD1306的从机地址有 0111100b 和 0111101b 两种,
    0x78 0x79
    将SA0(D/C#)脚下拉到低电平可以设置从机地址第七位为 0
    0为写模式
    通过SA0(D/C#)脚的上拉和下拉来设置从机地址,从而令总线上可以存在最多2个SSD1306驱动器。

CO 和 D/C# 位后面再加上六个0组成的。(控制字节组成如下图所示)Co D/C# 00 0000

如果Co为0,后面传输的信息就只包含数据字节。

D/C# 位决定了下个数据字节是作为命令还是数据。

D/C# 为0时,下一个数据被视为命令;

DC# 为1时,下一个数据被视为显示数据,存储到GDDRAM中。

在这里插入图片描述

根据时序图可知

发送数据或者指令的时候,首先发送地址0x78(写模式最后一位为0),然后发送判断是数据函数命令 发送指令的时候为0x00 发送数据的时候为0x40

void Write_IIC_Command(unsigned char IIC_Command)
{
   IIC_Start();
   Write_IIC_Byte(0x78);            //Slave address,SA0=0
   i2c_Ack();
   Write_IIC_Byte(0x00);			//write command D/C#为 0 因此是0x00
   i2c_Ack();
   Write_IIC_Byte(IIC_Command); 
   i2c_Ack();
   IIC_Stop();
}
/**********************************************
// IIC Write Data
**********************************************/
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();
}
  1. 写字节函数
    写字节函数通过移位一位一位的写入
    当读取到的是1 拉高SDA
    读取到的是0 拉低SDA
void Write_IIC_Byte(unsigned char IIC_Byte)
{
	unsigned char i;
	unsigned char m,da;
	da=IIC_Byte;
	OLED_SCL_LOW();//低电平进行数据的切换
	for(i=0;i<8;i++)		
	{
			m=da;
		m=m&0x80;
		if(m==0x80){//等于1000 0000 表示该位的数据是1
		  OLED_SDA_HIGH();//将SDA拉高
		}else{
			OLED_SDA_LOW();//将SDA拉低
		}
		da=da<<1;//0100 0001 << 1000 0010 通过左移进行数据的读取
		OLED_SCL_HIGH();//高电平读取信息
		OLED_SCL_LOW();//转换成低电平
		}

}
  1. 设置坐标函数
在这里插入图片描述
/*128*64 128列 64行
*坐标设置 y表示的是页数 从第几页开始显示 一页有8行 一共8页 组成64行
*                       一共8页  因此最多显示 4行 8*16 16行表示的是2页
*                                   最多显示 8行 6*8                                  
*          x表示的是列数 从第几列开始显示 
*     x&1111 0000 >>4 |0x0001 0000      
*/
void OLED_Set_Pos(unsigned char x, unsigned char y) 
{ 	
	OLED_WR_Byte(0xb0+y,OLED_CMD);
	OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
	OLED_WR_Byte((x&0x0f),OLED_CMD); 
}
  1. 清屏函数
    设置页的起使列地址,和页的结束列地址
    0x00 0x10 一共16列
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!	 不太明白
//RAM有也是128*64个字节  RAM划分成为8页 把数据通过RAM传递到OLED上面
void OLED_Clear(void)  
{  
	u8 i,n;		    
	for(i=0;i<8;i++)  //因为有8页  因此要循环8次
	{  
		OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)1011 0000 第五位规定为0 后三位用来设置页地址
                                       //1011 0001		
		OLED_WR_Byte (0x00,OLED_CMD);      //页寻址模式 设置起使列地址低位 0x00·0x0F     0000 0000   0000 1111   
		OLED_WR_Byte (0x10,OLED_CMD);      //页寻址模式 设置起使列地址高位 0x10 ~ 0x1F    0001 0000   0001 1111
		for(n=0;n<128;n++){
		  OLED_WR_Byte(0,OLED_DATA);//向每一列的每个元素写入0 显示黑色
		}			
	} //更新显示
}
  1. 字符显示函数
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示				 
//size:选择字体 16/12 
//生成的方法是列行式 因此需要先对上面的值进行处理  8*16相当于上面一行是8 下面一行也是8  8列16行
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
{      	
	unsigned char c=0,i=0;	
		c=chr-' ';//得到偏移后的值	通过ASCII码计算出和第一个差多少	 
	            //假设是写0 那么他和最开始的相比16-0 等于16 表示要在17行开始	
		if(x>Max_Column-1){//MAX_Column = 128
		  x=0;y=y+2;//加入x输入的大于128 就让x在第一列显示 y在下两行显示
		}
		if(Char_Size ==16){ //字体大小是16
			OLED_Set_Pos(x,y);	
			for(i=0;i<8;i++){
			 OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);//8*16的点阵  表示先显示上面行的8
			} 
      OLED_Set_Pos(x,y+1); //y加1
			for(i=0;i<8;i++){
			 OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA); //显示下面的8列元素
			}
		}else {	
			OLED_Set_Pos(x,y);
			for(i=0;i<6;i++){
				OLED_WR_Byte(F6x8[c][i],OLED_DATA);
			 }
		}
}
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐