I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备。它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。IIC是半双工通信方式。
I2C协议
1)空闲状态
I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。
2)起始信号与停止信号
3)应答信号ACK
发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。 应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
对于反馈有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。 如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放SDA线,以便主控接收器发送一个停止信号P。
4)数据有效性
I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
即:数据在SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。
5)数据的传送
在I2C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。
总容量是256(2K/8)个字节。
接口:IIC
正点原子开发板在硬件上设置了A0=A1=A2=0。
本实验功能简介:开机的时候先检测 24C02 是否存在,然后在主循环里面检测两个按键, 其中 1 个按键(KEY1)用来执行写入 24C02 的操作,另外一个按键(KEY0)用来执行读出操作,在串口上输出相关信息。同时用 DS0 提示程序正在运行。
在正点原子的程序源码中myiic.c文件用来存放iic底层驱动。24cxx.c 文件用来存放 24C02 的底层驱动。
IIC 驱动代码,实现包括 IIC 的初始化(IO 口)、IIC 开始、IIC 结束、ACK、IIC 读写等功能,在其他函数里面,只需要调用相关的 IIC 函数就可以和外部 IIC 器件通信了,这 里并不局限于 24C02,该段代码可以用在任何 IIC 设备上。
myiic.h 头文件还定义了几个宏定义标识符:
//IO 方向设置
#define SDA_IN() {GPIOB->MODER&=~(3MODER|=0MODER&=~(3MODER|=1<<9*2;}
//PB9 输入模式
#define SDA_OUT() {GPIOB->MODER&=~(3MODER|=1<<9*2;} //PB9 输出模式
//IO 操作函数
#define IIC_SCL PBout(8) //SCL
#define IIC_SDA PBout(9) //SDA
#define READ_SDA PBin(9) //输入 SDA
SDA_IN()和 SDA_OUT()分别用于设置 IIC_SDA 接口为输入和输出
24cxx.c 源文件代码,这部分代码理论上是可以支持 24Cxx 所有系列的芯片的(地址引脚必须都设置为 0)。
main函数
const u8 TEXT_Buffer[]={"Explorer STM32F4 IIC TEST"};
#define SIZE sizeof(TEXT_Buffer)
int main(void)
{
u8 key;
u16 i=0;
u8 datatemp[SIZE];
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //初始化延时函数
uart_init(115200); //初始化串口波特率为115200
LED_Init(); //初始化LED
KEY_Init(); //按键初始化
AT24CXX_Init(); //IIC初始化
while(AT24CXX_Check())//检测不到24c02
{
printf("24C02 Check Failed!\r\n");
delay_ms(500);
printf("Please Check!\r\n");
delay_ms(500);
LED0=!LED0;//DS0闪烁
}
printf("24C02 Ready!\r\n");
while(1)
{
key=KEY_Scan(0);
if(key==KEY1_PRES)//KEY1按下,写入24C02
{
printf("Start Write 24C02....\r\n");
AT24CXX_Write(0,(u8*)TEXT_Buffer,SIZE);
printf("24C02 Write Finished!\r\n");//提示传送完成
}
if(key==KEY0_PRES)//KEY0按下,读取字符串并显示
{
printf("Start Read 24C02....\r\n");
AT24CXX_Read(0,datatemp,SIZE);
printf("The Data Readed Is: ");//提示传送完成
printf("%s\r\n",datatemp);//显示读到的字符串
}
i++;
delay_ms(10);
if(i==20)
{
LED0=!LED0;//提示系统正在运行
i=0;
}
}
}
运行结果
I2C通信实验