OLED使用 SSD1306 IIC

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);
			 }
		}
}
  • 3
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值