I2C
一.I2C总线(主站模式)
1.I2C总线简介
I2C总线(Inter-Integrated Circuit)是一种串行通信总线,由飞利浦半导体公司(现为NXP)在1982年开发。I2C总线是一种两线制总线,由一条双向的数据线(SDA)和一条时钟线(SCL)组成。I2C总线支持多主多从结构,允许多个设备通过总线进行通信。
2.I2C总线的工作原理
I2C总线的工作原理基于时钟和数据信号的同步传输。主设备通过SCL线发送时钟信号,从设备通过SCL线接收时钟信号,并根据时钟信号的上升沿或下降沿同步传输数据。数据传输时,主设备通过SDA线发送数据,从设备通过SDA线接收数据。数据传输采用8位数据格式,每个字节后跟随一个应答位。
3.I2C总线的通信协议
(1)I2C总线_发送数据
- 主机发送起始信号
- 发送从机地址 + 写方向(最低位,第八位为0)
- 等待从机应答ACK
- 发送寄存器地址和数据
- 每发送1字节都需从机应答
- 最后发送停止信号
(2)I2C总线_接收数据
- 主机发送起始信号
- 发送从机地址 + 写方向(0)
- 等待应答,发送寄存器地址
- 发送重新开始信号(重复START): 主机要改变通信模式(主机将由发送变为接收,从机将由接收变为发送),所以主机重新发送一个开始start信号,然后紧跟着发送一个从机地址,注意此时该地址的第8位为1,表明将主机设置成接收模式,开始读取数据
- 发送从机地址 + 读方向(1)
- 接收数据,每接收一个字节主机需发送 ACK
- 最后一个字节发 NACK + 停止信号
(3)I2C总线_通信协议_时序图
请参考: I2C总线_时序图
二.关于STC8G单片机中的I2C主机总线
1.单片机的i2c的引脚确定
对于 stc8g1k08a单片机,其i2c引脚可以是 p3.2 和 p3.3, 也可以是 p5.4 和 p5.5
2.单片机i2c的寄存器问题
由于stc8g1k08a单片机中i2c的寄存器的地址是在 0FA00H~0FFFFH, 这个地址属于扩展 SFR范围. 要访问这里面的寄存器,需要将P_SW2的BIT7设置为1, 也就是将P_SW2的BIT7设置为1, 这样就可以访问到扩展 SFR范围了.
3.单片机i2c的寄存器操作流程
重点关注一下: 标题为<<20.2.2 I2C 主机控制寄存器(I2CMSCR)>> 也就是 手册 上的第 700页.
三.I2C的代码实现
i2c.c源文件
c
#include "stc8g.h"
/* 指定对应的引脚. 这个引脚是固定的
SCL 引脚 = P3.2
SDA 引脚 = P3.3
这个引脚可以更换为
SCL 引脚 = P5.4
SDA 引脚 = P5.5
需要 P_SW2 |= 1<<4;
对应的引脚也要设置为开漏输出
*/
// I2C初始化函数
void I2C_Init(void) {
P_SW2 |= 0x80; //设置允许读取EXTERN SFR范围的SFR
//默认输出引脚,配置P3.2(SCL)和P3.3(SDA)为开漏输出
P3M1 |= 0x0C; // P3.2和P3.3设置为开漏输出
P3M0 |= 0x0C;
// 配置使用P5.4和P5.5作为SCL和SDA输出引脚
// P_SW2 |= 1<<4;
// P5M1 |= 0x30; // P3.2和P3.3设置为开漏输出
// P5M0 |= 0x30;
I2CCFG = 0xE0; // 设置I2C时钟频率(约400kHz)
I2CMSST = 0x00; // 清除状态寄存器
}
// I2C启动信号
void I2C_Start(void) {
I2CMSCR = 0x01; // 发送START信号
while(!(I2CMSST & 0x80)); // 等待 MSBUSY 为1
I2CMSST &= ~0x40; // 清除中断标志
}
// I2C停止信号
void I2C_Stop(void) {
I2CMSCR = 0x06; // 发送STOP信号
}
// I2C发送一个字节
bit I2C_WriteByte(unsigned char dat) {
I2CTXD = dat;
I2CMSCR = 0x0A; // 发送数据并接收ack信号
while(!(I2CMSST & 0x40)); // 等待发送完成
I2CMSST &= ~0x40;
return 1;
}
// I2C读取一个字节
unsigned char I2C_ReadByte(bit ack) {
I2CMSCR = ack ? 0x0B : 0x0C; // 设置ACK/NACK
while(!(I2CMSST & 0x40)); // 等待接收完成
I2CMSST &= ~0x40;
return I2CRXD;
}