蓝桥杯嵌入式_STM32学习_IIC

本文详细介绍了I2C通信协议的时序,包括启动、停止、数据传输和应答信号等,并展示了针对24C02E2PROM的单字节和多字节读写操作的C代码实现,包括页写入和连续读取。代码中包含了应答信号的处理和地址计算,以及如何利用复启动信号进行多次通信。
摘要由CSDN通过智能技术生成

时序回顾(加速版)

先回顾 IIC 的时序 ——

总线空闲:SDA  = 1,SCL = 1;
启动信号:SCL = 1,SDA 1 -> 0;
停止信号:SCL = 1,SDA 0 -> 1;

数据传输:SCL为1时,SDA必须保持稳定,即为0或1;
         SCL为0时,才允许改变SDA状态;
         SCL在上升沿时写入数据,在下降沿时读出数据;
         
应答信号:为0时,是有效应答,为1时,是无效应答;
         传输到最后一个字节后,要发送一个无效应答,再发送停止信号;

总线封锁:将SCL锁定为0即可;

多次数据通信,采用复启动信号,即写一个停止信号,再接上一个启动信号;

单片机为主机,24C02为从机;
SCL时钟由主机控制;
写时应答信号从机给出;
读时由主机给出;

24C02器件地址:前四位默认为1010,后四位的前三位为A0,A1,A2,均已接地,即为0,
              最后一位为读写保护位,写时为0(0xA0),读时为1(0xA1).

器件地址:
在这里插入图片描述
单字节写与页写:
在这里插入图片描述
当前地址读取与随机地址读取:
在这里插入图片描述
连续地址读取:
在这里插入图片描述

代码快速配置

打开赛点资源数据包_嵌入式\3-底层驱动代码参考——
在这里插入图片描述
将i2c.c与i2c.h加入工程文件,然后在.c文件写入字节读取和写入函数。

函数代码

根据时序图写代码 ——

单字节写入

在这里插入图片描述

void E2PROM_Write(unsigned char addr, unsigned char data)
{
	do{
		I2CStart();//起始信号
		I2CSendByte(0xa0);//发送器件地址
		if(I2CWaitAck() == SUCCESS)break;	//等待应答
		I2CStop();
	}while(1);
	
	I2CSendByte(addr);//发送数据地址
	I2CWaitAck();//等待应答
	
	I2CSendByte(data);//发送数据
	I2CWaitAck();//等待应答
	
	I2CStop();//停止信号
}

注意:应答信号

注意:此次应答信号不能写为 if(I2CWaitAck() == 0)break;
在这里插入图片描述
在应答信号函数的定义中,无效应答返回FAILURE,有效应答返回SUCCESS;
在这里插入图片描述
跳转到两个字符常量的定义可以发现,FAILURE为0,SUCCESS为1。
所以这里应答信号我们要写为 等于SUCCESS。

多字节页写

/*******************************************************************************
* 函数名	:E2PROM_Write_long
* 输入值	:unsigned char *buf,unsigned char addr,unsigned char len
* 返回值	:none
* 作者	:Moqim Flourite.
* 时间	:2022年3月2日
* 功能描述:连续写入一页数据
* 备注	:buf为源数据指针,addr为E2PROM中要写入的数据起始地址,len为写入长度。
*******************************************************************************/

void E2PROM_Write_long(unsigned char *buf,unsigned char addr,unsigned char len){
	while(len){
		do{
		I2CStart();
		I2CSendByte(0xa0);          //用寻址操作查询当前是否可进行读写操作
		if(I2CWaitAck() == SUCCESS)break;	//应答则跳出循环,非应答则进行下一次查询
		I2CStop();
	}while(1);
	
	I2CSendByte(addr);
	I2CWaitAck();
	
	while(len --){
		I2CSendByte(*buf ++);       //写入一个字节数据
		I2CWaitAck();            
		addr ++;                    //E2PROM地址递增
		if((addr & 0x07) == 0)break;//检查地址是否到达页边界,24C02每页8字节
	}                             //到达页边界时,跳出循环,结束本次写操作
	
	I2CStop();
	}
}

单字节读取:
在这里插入图片描述

unsigned char E2PROM_Read(unsigned char addr)
{
	unsigned char data;
		do{
		I2CStart();
		I2CSendByte(0xa0);
		if(I2CWaitAck() == SUCCESS)break;	
		I2CStop();
	}while(1);
		
	I2CSendByte(addr);
	I2CWaitAck();
	I2CStop();
	
	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	data = I2CReceiveByte();
	
	I2CSendNotAck();
	I2CStop();
	return data;
}

多字节读取:

/*******************************************************************************
* 函数名	:E2PROM_Read_long
* 输入值	:unsigned char *buf,unsigned char addr,unsigned char len
* 返回值	:none
* 作者	:Moqim Flourite.
* 时间	:2022年3月2日
* 功能描述:连续读取多字节数据
* 备注	:buf为存储数组指针,addr为E2PROM中要读取的数据起始地址,len为读取长度。
*******************************************************************************/

void E2PROM_Read_long(unsigned char *buf,unsigned char addr,unsigned char len){
	do{
		I2CStart();
		I2CSendByte(0xa0);
		if(I2CWaitAck() == SUCCESS)break;
		I2CStop();
	}while(1);
	I2CSendByte(addr);
	I2CWaitAck();
	I2CStop();
	
	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	
	while(len --){
		*buf++ = I2CReceiveByte();
		I2CSendAck();
	}
	I2CSendNotAck();
	I2CStop();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Moqim Flourite.

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值