STM32小白入门(第12天)-------I2C协议

本文介绍了STM32中I2C协议的基础知识,包括信号概念和AT24C02 EEPROM的使用。在配合单片机存储数据时,详细阐述了AT24C02的写入和读取时序,并针对控制时钟时的5us延时进行了讨论,指出延时至少需1.2us,但大于5us也是可行的。


一、概述



二、信号概念



三、AT24C02(EEPROM电可擦除ROM)--配合单片机存贮掉电前需要保存的数据,类似单片机的硬盘


1、写时序


2、读时序


思考题2:在24c02控制时钟的时候,为什么要进行5us的延时,小于5us延时或许大于5us的延时是否可以,示例代码如下:

	        //设置SCL高电平
		SCL=1;
		delay_us(5);
	
		//设置SCL低电平
		SCL=0;
		delay_us(5);

回答:大于5us是可以的,如果使用5ms是可以的。但是延时是不能低于1.2us,详细描述如下图。




3、起始信号和停止信号


//sda输入输出模式切换函数
void OLED_SDA_Mode(GPIOMode_TypeDef IOMode)
{
	//PB9初始化设置 
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin   =  OLED_SDA_PIN;			//9号引脚
	GPIO_InitStructure.GPIO_Mode  = IOMode;			    	//输出模式/输入模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;		      //推挽输出,驱动LED需要电流驱动
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;		 //100MHz
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;				//上拉
	GPIO_Init(OLED_GPIO_PORT, &GPIO_InitStructure);			//初始化GPIOB,把配置的数据写入寄存器		
}
/**********************************************
//IIC Start
**********************************************/
void IIC_Start(void)
{
	//保证SDA引脚为输出模式
	OLED_SDA_Mode(GPIO_Mode_OUT);
	OLED_SCLK = 1;
	OLED_SDA_W = 1;
	/*注:原版代码是没有加延时的,这里一定要延时,因为M4是高速芯片,3.3MHz通信速率,所以一个时钟周	期约为0.3us,有与我们处理器是168MHz,执行一条指令比这个时间快很多所以我们需要加至少1us的延时,
	但是在频率较低的处理器中我们可以不加延时
*/
	delay_us(1);	
	OLED_SDA_W = 0;    //数据线先拉低,时钟线后拉低,即为启动信号
	delay_us(1);
	OLED_SCLK = 0;
	delay_us(1);
}

/**********************************************
//IIC Stop
**********************************************/
void IIC_Stop(void)
{
	//保证SDA引脚为输出模式
	OLED_SDA_Mode(GPIO_Mode_OUT);
	
	OLED_SCLK = 1;    //时钟线先拉高,数据线后拉高,即为停止信号
	OLED_SDA_W = 0;
	delay_us(1);
	OLED_SDA_W = 1;
	delay_us(1);
}
uint8_t IIC_Wait_Ack(void)
{
	uint8_t ack=0;
	//保证SDA引脚为输入模式
	OLED_SDA_Mode(GPIO_Mode_IN);
	
	OLED_SCLK = 1;
	delay_us(1);
	//有应答为低电平,无应答为高电平
	if(OLED_SDA_R)		//无应答
	{
		ack=1;
		IIC_Stop();
	}
	else			//有应答
		ack=0;
	
	OLED_SCLK = 0;
	delay_us(1);
	return ack;
}
/**********************************************
// IIC Read byte
**********************************************/
uint8_t i2c_recv_byte(void)
{
uint8_t byte=0;

uint32_t i=0;
//保证SDA引脚为输出模式
i2c_sda_mode(GPIO_Mode_OUT);

//设置为低电平
SCL=0;
SDA_W=0;

delay_us(5);

//保证SDA引脚为输入模式
i2c_sda_mode(GPIO_Mode_IN);

for(i=0; i<8; i++)
{
//设置时钟为高电平,告诉从机,可以对SDA引脚进行控制
SCL=1;
delay_us(5);

//读取SDA引脚的电平
if(SDA_R)
byte|=1<<(7-i);


//设置时钟为低电平,告诉从机,不可以对SDA引脚进行控制
SCL=0;
delay_us(5);
}

return byte;
}
void at24c02_read(uint8_t addr,uint8_t *pbuf,uint32_t len)    //从机读取数据
{
	uint32_t ack=0;
	
	//发送起始信号
	i2c_start();
	
	
	//发送寻址地址
	i2c_send_byte(0xA0);


	//等待应答
	ack=i2c_wait_ack();
	
	if(ack)
	{
		printf("i2c ack device address fail\r\n");
		
		return ;	
	}
	printf("i2c ack device address ok\r\n");

	//发送24c02的数据存储地址
	i2c_send_byte(addr);

	//等待应答
	ack=i2c_wait_ack();
	
	if(ack)
	{
		printf("i2c ack word address fail\r\n");
		
		return ;
	}
	printf("i2c ack word address ok\r\n");
	
	//再一次发送起始信号
	i2c_start();
	
	//发送寻址地址,读访问操作
	i2c_send_byte(0xA1);
	
	//等待应答
	ack=i2c_wait_ack();
	if(ack)
	{
		printf("i2c ack device address_r fail\r\n");
		
		return ;
	}
	printf("i2c ack device address_r ok\r\n");
	
	len=len-1;
	
	while(len--)
	{
		*pbuf++=i2c_recv_byte();
	
		i2c_ack(0);
	}
	
	*pbuf=i2c_recv_byte();
	
	i2c_ack(1);	
	
	//发送停止信号
	i2c_stop();
	printf("i2c ack read data ok\r\n");
	
}
/**********************************************
// IIC Write byte
**********************************************/

void Write_IIC_Byte(unsigned char IIC_Byte)
{
	unsigned char i;

	//保证SDA引脚为输出模式
	OLED_SDA_Mode(GPIO_Mode_OUT);
	
	OLED_SCLK = 0;
	delay_us(1);
	for(i=0;i<8;i++)		
	{
		if(IIC_Byte&(1<<(7-i)))  MSB
			OLED_SDA_W = 1;
		else 
			OLED_SDA_W = 0;
		delay_us(1);
		OLED_SCLK = 1;
		delay_us(1);
		OLED_SCLK = 0;
		delay_us(1);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值