了解I2C
飞利浦(NXP)于1980提出I2C
串行总线,使用多主从架构,为同步半双工通信方式 .
常见速率:100kbps、300kbps、3.4Mbps .
端口设置
采用外部上拉(强上拉)时,端口配置为开漏输出,配合上拉电阻(1K左右)以输出高电平 .
I2C的数据有效性
在传输期间,SCL
为高电平时数据有效,数据的切换只能在SCL
为低电平时进行 .
I2C的START和STOP信号
void IIC_Start(void)
{
SDA_HIGH;
SCL_HIGH;
SDA_LOW;
SCL_LOW;
}
void IIC_Stop(void)
{
SDA_LOW;
SCL_HIGH;
SDA_HIGH;
}
I2C的ACK应答信号
START
之后,在接下来的8个CLK中,SDA
进行一次8bit的数据传输,若接收到数据,则在第9个CLK对SDA
拉低,将其视作一次ACK
应答信号 .
发送ACK的方式参考
void IIC_SendAck(u8 ACK_Byte)
{
if(ACK_Byte == 1)
SDA_HIGH;
else
SDA_LOW;
SCL_HIGH;
SCL_LOW;
}
接受ACK方式参考
u8 IIC_ReceiveAck(void)
{
u8 ACK_Byte;
SDA_HIGH;//主机释放,从机接管
SCL_HIGH;
ACK_Byte = READ_SDA;
SCL_LOW;
return ACK_Byte;
}
I2C读写1Byte数据
写数据的方式参考
void IIC_WriteByte(u8 IIC_Byte)
{
u8 i;
u8 data = IIC_Byte;
SCL_LOW;
for(i=0;i<8;i++)
{
if((data&0x80) == 0x80)
SDA_HIGH;
else
SDA_LOW;
data = data<<1;
SCL_HIGH;
SCL_LOW;
}
}
读数据的方式参考
u8 IIC_ReadByte(void)
{
u8 i,IIC_Byte = 0x00;
SDA_HIGH;//主机释放,从机接管 --这里的SDA,SCL都是推挽输出
for(i=0;i<8;i++)
{
SCL_HIGH;
if(READ_SDA == 1)
IIC_Byte |= (0x80>>i);
SCL_LOW;
}
return IIC_Byte;
}
了解SSD1306
SSD1306使用I2C的数据格式
首字节
由从机地址0x3C
和R/W#
组成 .
IIC_WriteByte(0x78);//W
IIC_WriteByte(0x79);//R
控制字节
由Co
和D/C#
及000000
组成,Co
低电平意指后续的Byte都是数据,可用于连续输出 CMD 和 DATA .
IIC_WriteByte(0x00);//后面的字节是命令
IIC_WriteByte(0x40);//后面的字节是数据,并存入GDDRAM
IIC_WriteByte(0x80);//后一位字节是命令
IIC_WriteByte(0xC0);//后一位字节是数据,并存入GDDRAM
写一次命令
void OLED_CMD(u8 CMD)
{
IIC_Start();
IIC_WriteByte(0x78);
IIC_ReceiveAck();
IIC_WriteByte(0x80);
IIC_ReceiveAck();
IIC_WriteByte(CMD);
IIC_ReceiveAck();
IIC_Stop();
}
验证
尝试发送 0xAF
开启屏幕的显示
OLED_CMD(0xAF);
接上逻辑分析仪查看时序
观察屏幕,情况如下:
屏幕被成功点亮,并将GDDRAM中的初始数据输出 .
快速刷屏
void OLED_ClearScreen(void)
{
OLED_DATA_128_64(0x00);
}
void OLED_FillScreen(void)
{
OLED_DATA_128_64(0xFF);
}
void OLED_DATA_128_64(u8 DATA_128_64)
{
u16 i;
IIC_Start();
IIC_WriteByte(0x78);//从机地址0111100和R/W#
IIC_ReceiveAck();
IIC_WriteByte(0x40);
IIC_ReceiveAck();
for(i=0;i<128*8;i++)
{
IIC_WriteByte(DATA_128_64);
IIC_ReceiveAck();
}
IIC_Stop();
}
SSD1306的GDDRAM
GDDRAM结构
从上至下,将GDDRAM分为8个PAGE,8 * 128 Byte
从左至右,将PAGE分为128个SEG,128 * 1 Byte
写入GDDRAM的Byte,最低位D0在顶行,最高位D7在底行 .
GDDRAM的寻址模式
20h+A[1:0]
设置内存寻址模式
A[1:0]=10b
页面寻址 用于局部刷新
仅在PAGE中寻址 .向GDDRAM写入1Byte后,列指针自增1,直至寻址结束,页指针不变 .A[1:0]=00b
水平寻址A[1:0]=01b
竖直寻址A[1:0]=11b
无效寻址
填充全屏
OLED_FILL()
{
OLED_CMD(0x20); // 设置寻址模式
OLED_CMD(0x00); // 水平寻址模式
OLED_CMD(0X21); // 设置列起始和结束地址
OLED_CMD(0X00); // 列起始地址 0
OLED_CMD(0X7F); // 列终止地址 127
OLED_CMD(0X22); // 设置页起始和结束地址
OLED_CMD(0X00); // 页起始地址 0
OLED_CMD(0X07); // 页终止地址 7
u8 r,c;
for(r=0;r<8;r++)
for(c=0;c<128;c++)
OLED_DATA(0xFF);
}