IIC
一、IIC、起始信号,终止信号
**起始条件:**当SCL为高电平的时候,SDA线上由高到低的跳变被定义为起始条件。
**结束条件:**当SCL为高电平的时候,SDA线上由低到高的跳变被定义为停止条件。
void IIC_Start(){
sda = 1;
scl = 1;
delay(); // 5us _nop_()
sda = 0;
delay();
}
void IIC_Stop(){
sda = 0;
scl = 1;
delay();
sda = 1;
delay();
}
二、应答信号
发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。
应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;
应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
每当主机向从机发送完一个字节的数据,主机总是需要等待从机给出一个应答信号,以确认从机是否成功接收到了数据,从机应答主机所需要的时钟仍是主机提供的,应答出现在每一次主机完成8个数据位传输后紧跟着的时钟周期,低电平0表示应答,1表示非应答。
char IIC_ACK(){
char flag;
sda = 1;
delay(); //5us
scl = 1;
delay();
flag = sda;
delay();
scl = 0;
delay();
return flag;
}
三、数据发送的时序
void IIC_SendByte(char data){
for(int i=0;i<8;i++){
scl = 0; //准备让sda做好数据准备
sda = data & 0x80; //1000 0000获得最高位
delay();
scl = 1; //开始传输
delay();
scl = 0;
delay();
data = data << 1;
}
}
OLED
一、OLED写命令
I2C 总线接口允许将数据和命令写入设备。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w90zwjvd-1652514981169)(d:\Users\silly_zeng\Desktop\OLED.bmp)]
- 主设备通过启动条件启动数据通信。开始的定义条件如图 8-8 所示。
启动条件是通过将 SDA 从 HIGH 拉到低,而 SCL 保持高。
- 从机地址遵循识别使用的起始条件。从地址为“b0111100(r/w) ”或“b0111101(r/w) ”。
通过将 R/W# 位设置为逻辑“0”来建立写模式。
- 接收到一个字节的数据后会产生一个确认信号,包括从机地址和R/W#位。
请参阅图 8-9 以了解确认信号的图形表示。确认位定义为在确认相关时钟脉冲的高电平期间 SDA 线被拉低。
- 从机地址发送后,控制字节或数据字节都可以通过 SDA 发送。一个控制字节主要由 Co 和 D/C# 位组成,后跟六个“0”。
如果 Co 位设置为逻辑“0”,则以下信息的传输将仅包含数据字节。D/C# 位决定下一个数据字节是作为命令还是数据。
cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
- 当应用停止条件时,写入模式将结束。 停止条件也被定义在图 8-8 中。
通过将“SDA in”从低拉到高来建立停止条件,同时“SCL”保持在高位
void OLED_Write_Cmd(char dataCmd){
/* start */
IIC_Start();
/* 写入从机地址 b0111 1000 */
IIC_SendByte(0x78);
/* ack */
IIC_ACK();
/* cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据 */
IIC_SendByte(0x00);
/* ack */
IIC_ACK();
/* 写指令 */
IIC_SendByte(dataCmd);
/* ack */
IIC_ACK();
/* stop */
IIC_Stop();
}
void OLED_Write_Data(char data){
/* start */
IIC_Start();
/* 写入从机地址 b0111 1000 */
IIC_SendByte(0x78);
/* ack */
IIC_ACK();
/* cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据 */
IIC_SendByte(0x00);
/* ack */
IIC_ACK();
/* 写指令 */
IIC_SendByte(data);
/* ack */
IIC_ACK();
/* stop */
IIC_Stop();
}
二、OLED的寻址模式
页地址模式,水平地址模式和垂直地址模式,可以通过以下表格进行配置
页地址模式:
1.发送cmd:0x20;
2.发送cmd:0x02;默认页模式
水平地址模式
垂直地址模式
void Oled_Init(void){
Oled_Write_Cmd(0xAE);//--display off
Oled_Write_Cmd(0x00);//---set low column address
Oled_Write_Cmd(0x10);//---set high column address
Oled_Write_Cmd(0x40);//--set start line address
Oled_Write_Cmd(0xB0);//--set page address
Oled_Write_Cmd(0x81); // contract control
Oled_Write_Cmd(0xFF);//--128
Oled_Write_Cmd(0xA1);//set segment remap
Oled_Write_Cmd(0xA6);//--normal / reverse
Oled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
Oled_Write_Cmd(0x3F);//--1/32 duty
Oled_Write_Cmd(0xC8);//Com scan direction
Oled_Write_Cmd(0xD3);//-set display offset
Oled_Write_Cmd(0x00);//
Oled_Write_Cmd(0xD5);//set osc division
Oled_Write_Cmd(0x80);//
Oled_Write_Cmd(0xD8);//set area color mode off
Oled_Write_Cmd(0x05);//
Oled_Write_Cmd(0xD9);//Set Pre-Charge Period
Oled_Write_Cmd(0xF1);//
Oled_Write_Cmd(0xDA);//set com pin configuartion
Oled_Write_Cmd(0x12);//
Oled_Write_Cmd(0xDB);//set Vcomh
Oled_Write_Cmd(0x30);//
Oled_Write_Cmd(0x8D);//set charge pump enable
Oled_Write_Cmd(0x14);//
Oled_Write_Cmd(0xAF);//--turn on oled panel
}
void Oled_Clear()
{
unsigned char i,j; //-128 --- 127
for(i=0;i<8;i++){
Oled_Write_Cmd(0xB0 + i);//page0--page7
//每个page从0列
Oled_Write_Cmd(0x00);
Oled_Write_Cmd(0x10);
//0到127列,依次写入0,每写入数据,列地址自动偏移
for(j = 0;j<128;j++){
Oled_Write_Data(0);
}
}
}
void main()
{
unsigned char i;
//1. OLED初始化
Oled_Init();
//2. 选择一个位置
//2.1 确认页寻址模式
Oled_Write_Cmd(0x20);
Oled_Write_Cmd(0x02);
Oled_Clear();
//2.2 选择PAGE0 1011 0000
// 0xB0
Oled_Write_Cmd(0xB0);
Oled_Write_Cmd(0x00);
Oled_Write_Cmd(0x10);
for(i=0;i<16;i++){
Oled_Write_Data();
}
for(i=0;i<16;i++){
Oled_Write_Data();
}
for(i=0;i<16;i++){
Oled_Write_Data();
}
for(i=0;i<16;i++){
Oled_Write_Data();
}
for(i=0;i<16;i++){
Oled_Write_Data();
}
while(1)
;
}
);
}
for(i=0;i<16;i++){
Oled_Write_Data();
}
for(i=0;i<16;i++){
Oled_Write_Data();
}
for(i=0;i<16;i++){
Oled_Write_Data();
}
for(i=0;i<16;i++){
Oled_Write_Data();
}
while(1)
;
}