IIC 通信协议
I2C(IIC,Inter-Integrated Circuit)
两线式串行总线(中文应该是集成电路总线),PHILIPS公司开发 连接微控制器及外围设备
由数据线SDA(Serial Data Line)用来一位一位的传输数据)和SCL(SYSTEM CLOCK LINE)构成的串行总线
可以发送接收数据
CPU与被控IC、IC和IC之间的双向传输
高速IIC总线一般可达400kbps以上
半双工通信方式
空闲状态
规定:SDA和SCL两条信号线同时处于高电平时,总线处于空闲状态
开始信号
SCL为高期间 SDA发生由高到低的跳变
是时序信号不是电平信号
停止信号
SCL为高期间 SDA发生由低到高的跳变
是时序信号不是电平信号
void IIC_Start(void)
{
SDA_OUT(); //sda线输出
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;// START CLK是high DATA由高电平到低电平
delay_us(4);
IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
IIC_SCL=0;
IIC_SDA=0;//STOP CLK 是high DATA 从低电平转为高电平
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//发送I2C 总线结束信号
delay_us(4);
}
应答信号ACK
发送器每发送一字节,就在时钟脉冲9 期间释放数据线,由接收器反馈一个应答信号
规定:应答信号为低电平为有效应答
表示接收器已成功接收
要求:接收器在第九个时钟脉冲之前的低电平期间将SDA拉低,在时钟高电平期间为稳定的低电平
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN(); //SDA设置输入
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//时钟输出0
return 0;
}
数据的有效性
数据传送时,scl时钟信号为高电平时,数据线上数据必须保持稳定,当时钟线上的信号为低电平时数据线电平状态才被允许变化。
数据输出:
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
IIC_SDA=(txd&0x80)>>7;
txd<<=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
数据输入:
u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA设置输入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
数据传输
每一位数据对应一个时钟脉冲
数据位的传输是边沿触发
24C02操作
EEPROM存储器 总容量是256个字节
接口:IIC
24C02字节写时序
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{
IIC_Start();
if(EE_TYPE>AT24C16)
{
IIC_Send_Byte(0XA0); //写命令
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr>>8);//发送高地址
}else IIC_Send_Byte(0XA0+((WriteAddr/256)<<1)); //发送器件地址写数据
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr%256); //发送低地址
IIC_Wait_Ack();
IIC_Send_Byte(DataToWrite); //发送字节
IIC_Wait_Ack();
IIC_Stop();//产生一个停止条件
delay_ms(10);
}
24C02读时序
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{
u8 temp=0;
IIC_Start();
if(EE_TYPE>AT24C16)
{
IIC_Send_Byte(0XA0); //发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr>>8);//发送高地址
}else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1)); //发送器件地址
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr%256); //发送低地址
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(0XA1); //接收模式
IIC_Wait_Ack();
temp=IIC_Read_Byte(0);
IIC_Stop();//产生停止条件
return temp;
}
实验程序
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "24cxx.h"
#include "key.h"
//写入到24c02的字符串数组
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);
delay_init(168);
uart_init(115200);
LED_Init();
LCD_Init(); ¯
KEY_Init();
AT24CXX_Init();
POINT_COLOR=RED;
LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
LCD_ShowString(30,70,200,16,16,"IIC TEST");
LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,110,200,16,16,"2021/9/9");
LCD_ShowString(30,130,200,16,16,"KEY1:Write KEY0:Read");
while(AT24CXX_Check())//检测不到24c02
{
LCD_ShowString(30,150,200,16,16,"24C02 Check Failed!");
delay_ms(500);
LCD_ShowString(30,150,200,16,16,"Please Check! ");
delay_ms(500);
LED0=!LED0;//DS0闪烁
}
LCD_ShowString(30,150,200,16,16,"24C02 Ready!");
POINT_COLOR=BLUE;
while(1)
{
key=KEY_Scan(0);
if(key==KEY1_PRES)//KEY1按下 写入24c02
{
LCD_Fill(0,170,239,319,WHITE);//清除半屏
LCD_ShowString(30,170,200,16,16,"Start Write 24C02....");
AT24CXX_Write(0,(u8*)TEXT_Buffer,SIZE);
LCD_ShowString(30,170,200,16,16,"24C02 Write Finished!");//提示完成
}
if(key==KEY0_PRES)//KEY0 读取字符串并显示
{
LCD_ShowString(30,170,200,16,16,"Start Read 24C02.... ");
AT24CXX_Read(0,datatemp,SIZE);
LCD_ShowString(30,170,200,16,16,"The Data Readed Is: ");//提示传送完成
LCD_ShowString(30,190,200,16,16,datatemp);//显示读到的字符串
}
i++;
delay_ms(10);
if(i==20)
{
LED0=!LED0;//提示系统正在运行
i=0;
}
}
}