IIC时序的实现
I
I
C
IIC
IIC 是一种通信协议,是一种串行通信结构,由一根时钟线
S
C
L
SCL
SCL 以及一根数据线
S
D
A
SDA
SDA 组成,在
I
2
C
I2C
I2C 总线传输过程中,将两种特定的情况定义为开始和停止条件:当
S
C
L
SCL
SCL 保持“高”时,
S
D
A
SDA
SDA 由“高”变为“低”为开始条件;当
S
C
L
SCL
SCL 保持“高”且
S
D
A
SDA
SDA 由“低”变为“高”时为停止条件。
开始和停止条件均由主控制器产生。使用硬件接口可以很容易地检测到开始和停止条件,没有这种接口的微机必须以每时钟周期至少两次对
S
D
A
SDA
SDA 取样,以检测这种变化。
S
D
A
SDA
SDA 线上的数据在时钟“高”期间必须是稳定的,只有当
S
C
L
SCL
SCL 线上的时钟信号为低时,数据线上的“高”或“低”状态才可以改变。输出到
S
D
A
SDA
SDA 线上的每个字节必须是8位,每次传输的字节不受限制,但每个字节必须要有一个应答
A
C
K
ACK
ACK。如果一接收器件在完成其他功能(如一内部中断)前不能接收另一数据的完整字节时,它可以保持时钟线
S
C
L
SCL
SCL为低,以促使发送器进入等待状态;当接收器准备好接受数据的其它字节并释放时钟
S
C
L
SCL
SCL后,数据传输继续进行。
I
2
C
I2C
I2C数据总线传送时序。
数据传送具有应答是必须的。与应答对应的时钟脉冲由主控制器产生,发送器在应答期间必须下拉
S
D
A
SDA
SDA线。当寻址的被控器件不能应答时,数据保持为高并使主控器产生停止条件而终止传输。在传输的过程中,在用到主控接收器的情况下,主控接收器必须发出一数据结束信号给被控发送器,从而使被控发送器释放数据线,以允许主控器产生停止条件。
代码实现:
初始化模拟IIC的GPIO端口
void IIC_GPIO_Init() {
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStruct.GPIO_Pin = SCL_PIN | SDA_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIO_PORT,&GPIO_InitStruct);
}
配置IIC是读数据还是写数据
void IIC_SDA_Mode(u8 mode) {
GPIO_InitTypeDef GPIO_InitStruct;
if (mode) {
GPIO_InitStruct.GPIO_Pin = SDA_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIO_PORT,&GPIO_InitStruct);
} else {
GPIO_InitStruct.GPIO_Pin = SDA_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIO_PORT,&GPIO_InitStruct);
}
}
IIC起始信号:SCL在高电平期间,SDA由高电平向低电平的变化定义为起始信号
void IIC_start() {
IIC_SDA_Mode(OUT);
IIC_SDA_1;
IIC_SCK_1;
delay_us(5);
IIC_SDA_0;
delay_us(5);
IIC_SCK_0;
}
停止信号:SCL在高电平期间,SDA由低电平向高电平的变化定义为停止信号
void IIC_stop() {
IIC_SDA_Mode(OUT);
IIC_SDA_0;
delay_us(5);
IIC_SCK_1;
delay_us(5);
IIC_SDA_1;
}
应答信号:当SCL为高电平的时候,SDA为低电平则为应答信号,SDA为高电平则为非应答信号
u8 IIC_Wait_Ack(void) {
u8 times = 0;
IIC_SDA_Mode(INPUT);
IIC_SCK_1;
delay_us(5);
while (GPIO_ReadInputDataBit(GPIO_PORT,SDA_PIN)) {
if (++times > 250) IIC_stop();
return 1;
}
IIC_SCK_0;
delay_us(5);
return 0;
}
IIC写一字节数据:
void IIC_write(u8 date) {
u8 i, temp;
temp = date;
IIC_SCK_0;
delay_us(5);
for(i = 0; i < 8; i++) {
IIC_SDA_Mode(OUT);
if (((temp << i) & 0x80) == 0 ) {
IIC_SDA_0;
} else {
IIC_SDA_1;
}
IIC_SCK_1;
delay_us(5);
IIC_SCK_0;
delay_us(5);
}
}
IIC读一字节数据
u8 IIC_read(void) {
u8 i, temp = 0;
for(i = 0; i < 8; i++) {
IIC_SDA_Mode(INPUT);
IIC_SCK_1;
delay_us(5);
temp <<= 1;
if(GPIO_ReadInputDataBit(GPIO_PORT,SDA_PIN) == 1) {
temp |= 0x01;
}
IIC_SCK_0;
delay_us(5);
}
return temp;
}
获取工程源码关注微信公众号:小张嵌入式 回复关键词:软件模拟IIC
|