单片机学习笔记.IIC通信协议(根据数据手册写IIC驱动程序,这里以普中开发板上的AT24C02为例)

硬件原理图:



AT24C02数据图:


I2C电路规范:

  • 所有I2C设备的时钟线SCL和数据线SDA连在一起
  • 设备的SCL和SDA都要配置为开漏输出模式
  • SCL和SDA各需要添加一个 上拉电阻,阻值一般为4.7k
  • 开漏输出模式和上拉电阻共同作用实现了线与的功能,解决了多机通信的问题

首先根据原理图定义对应引脚:

cpp 复制代码
sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;

I2C时序图:

I2C起始信号:

cpp 复制代码
/**
  * @brief  I2C起始
  * @param  无
  * @retval 无
  */
void I2C_Start(void)
{
	I2C_SDA=1;//这里SDA置1是因为可能数据不是刚开始才发送,可能是从停止位开始,SDA可能为0,
	I2C_SCL=1;//因为SCL每次最后都是低电平,这个时候SDA可以改变,起始条件是开始都为1
	
	I2C_SDA=0;
	I2C_SCL=0;
}

I2C停止信号:

cpp 复制代码
/**
  * @brief  I2C停止  
  * @param  无
  * @retval 无
  */
void I2C_Stop(void)
{
	I2C_SDA=0;//保证SDA拉高前是0
	I2C_SCL=1;
	I2C_SDA=1;
}

I2C发送一个字节:

写入一个字节时序分析:

cpp 复制代码
/**
  * @brief  I2C发送一个字节
  * @param  Byte
  * @retval 无
  */
void I2C_SendByte(unsigned char Byte)//由时序图可知在调用该函数是SCL为低电平,                                  
{                                    //此时直接改变SDA的电平
  unsigned char  i;	
	for( i=0;i<8;i++)
	{
		I2C_SDA=Byte&(0x80>>i);               ////I2C协议先存的是最高位然后依次存
		I2C_SCL=1;  //由数据手册可知时间可以不加延时
		I2C_SCL=0;
	}
}

I2C接收一个字节:

  • 在SCL低电平期间从机将数据位依次放到SDA线上还是高位在前,然后拉高SCL,读取数据位,在该期间SDA不能变化

  • 在主机接收时,主机需要释放SDA

cpp 复制代码
/**
  * @brief   I2C接收一个字节
  * @param   无
  * @retval  Byte
  */
unsigned char I2C_ReceiveByte(void)
{
	unsigned char Byte=0x00;
	unsigned char  i;	
	I2C_SDA=1;//释放总线
	for( i=0;i<8;i++)
	{
	I2C_SCL=1;//I2C协议规定在SCL=1时读取
	if(I2C_SDA){Byte|=(0x80>>i);}//如果读取到SDA=1,就把Byte的最高位置1
	I2C_SCL=0;//读完后拉低
  }
	return Byte;
}

I2C发送应答:

  • 发送应答:在接收完一个字节之后,主机在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答
cpp 复制代码
/**
  * @brief  I2C发送应答
  * @param  AckBit 应答位为0应答,为1无应答
  * @retval 无
  */
void I2C_SendAck(unsigned char AckBit)
{
	I2C_SDA=AckBit;
	I2C_SCL=1;
	I2C_SCL=0;
}

I2C接收应答:

  • 接收应答:在发送完一个字节之后,主机在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)
cpp 复制代码
/**
  * @brief  I2C接收应答
  * @param  无
  * @retval AckBit 应答位为0应答,为1无应答
  */
unsigned char I2C_ReceiveAck(void)
{
	unsigned char AckBit;
	I2C_SDA=1;//主机接收前,先释放SDA
	I2C_SCL=1;//读取
	AckBit=I2C_SDA;
	I2C_SCL=0;
	return AckBit;//为0应答,为1无应答
}

AT24C02的设备地址:

固定地址是1010,原理图A2A1A0是000,最低位为0时是Write,最低位为1时是Read.

cpp 复制代码
#define AT24C02_ADDRESS 0XA0 //定义AT24C02的写入时的地址

AT24C02写入一个字节:

分析:

cpp 复制代码
/**
  * @brief  AT24C02写入一个字节
  * @param  WordAddress,要写入字节的地址
  * @param  Data要写入的数据
  * @retval 无
  */
void AT24C02_WriteByte(unsigned char WordAddress,Data)
{
/*
	//unsigned char Ack;用来测试是否应答
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);//1010固定,000原理图,0为w,1为r,写为0XA0,读为0XA1
	//Ack=I2C_ReceiveACK();用来测试是否应答
	//if(Ack==0){P2=0x00;}用来测试是否应答
	*/
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);//1010固定,000原理图,0为w,1为r,写为0XA0,读为0XA1
	I2C_ReceiveACK();
	I2C_SendByte(WordAddress);
	I2C_ReceiveACK();
	I2C_SendByte(Data);
	I2C_ReceiveACK();
	I2C_Stop();
}

AT24C02读取一个字节:

分析:

cpp 复制代码
/**
  * @brief  AT24C02读出一个字节
  * @param  WordAddress,要读出字节的地址
  * @retval Data要读取对应地址存入的数据
  */
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
	unsigned char Data;
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);//1010固定,000原理图,0为w,1为r,写为0XA0,读为0XA1
	I2C_ReceiveACK();
	I2C_SendByte(WordAddress);
	I2C_ReceiveACK();
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS|0x01);
	I2C_ReceiveACK();
	Data=I2C_ReceiveByte();
	I2C_SendAck(1);
	I2C_Stop();
	return Data;
}

主函数测试:

写入完后未加延时立即读取数据:读出的数据有问题

cpp 复制代码
unsigned char Data;
int main()
{
	LCD_Init();
	AT24C02_WriteByte(1,66);
    Data=AT24C02_ReadByte(1);
    LCD_ShowNum(1,1,Data,3);
	while(1)	
	{
		
	}
}

查看数据手册可知:

写入完后加延时5ms读取数据: 数据正常

cpp 复制代码
unsigned char Data;
int main()
{
	LCD_Init();
	AT24C02_WriteByte(1,66);
	Delayms(5);
  Data=AT24C02_ReadByte(1);
  LCD_ShowNum(1,1,Data,3);
	while(1)	
	{
		
	}
}

相关推荐
普中科技34 分钟前
【普中STM32精灵开发攻略】--第 11 章 SysTick系统定时器
stm32·单片机·嵌入式硬件·物联网·arm·普中科技
李夕1 小时前
掌握工程化固件烧录,开启你的技术进阶之路-FPGA ISE(xilinx)
嵌入式硬件·fpga·固件
秋雨qy1 小时前
论文reading学习记录7 - daily - ViP3D
学习·3d
Li X1 小时前
USB2.0协议学习-基础知识
网络·学习
ZLRRLZ1 小时前
【数据结构】哈希扩展学习
数据结构·学习·哈希算法
Hello_Embed2 小时前
STM32HAL 快速入门(二):用 CubeMX 配置点灯程序 —— 从工程生成到 LED 闪烁
笔记·stm32·单片机·学习·嵌入式软件
JasmineX-12 小时前
STM32的SPI通信(软件读写W25Q64)
c语言·stm32·单片机·嵌入式硬件
xiaoxiaoxiaolll4 小时前
多尺度建模新范式:当神经网络融入ABAQUS,复合材料仿真迎来“物理+数据“双引擎!
人工智能·深度学习·神经网络·学习
HW-BASE8 小时前
《C语言》指针练习题--1
c语言·开发语言·单片机·算法·c
勤奋的小笼包8 小时前
论文阅读笔记:《Dataset Distillation by Matching Training Trajectories》
论文阅读·人工智能·笔记