IIC读写

IIC通信中读的过程比较复杂,在从slave读出数据前,你必须先要告诉它哪个内部寄存器是你想要读取的,因此必须先对其进行写入(dummy write):

发送起始位;
发送slave地址+write bit set;
发送内部寄存器地址;
重新发送起始位,即restart;
重新发送slave地址+read bit set;
读取数据
主机接收器在接收到最后一个字节后,也不会发出ACK信号。于是,从机发送器释放SDA线,以允许主机发出P信号结束传输。
发送停止位
在这里插入图片描述
在这里插入图片描述

.主设备向从设备发送数据

主设备发送起始位,这会通知总线上的所有设备传输开始了,接下来主机发送设备地址,与这一地址匹配的slave将继续这一传输过程,而其它slave将会忽略接下来的传输并等待下一次传输的开始。主设备寻址到从设备后,发送它所要读取或写入的从设备的内部寄存器地址; 之后,发送数据。数据发送完毕后,发送停止位:

写入过程如下:

发送起始位

发送从设备的地址和读/写选择位;释放总线,等到EEPROM拉低总线进行应答;如果EEPROM接收成功,则进行应答;若没有握手成功或者发送的数据错误时EEPROM不产生应答,此时要求重发或者终止。
发送想要写入的内部寄存器地址;EEPROM对其发出应答;
发送数据
发送停止位.
EEPROM收到停止信号后,进入到一个内部的写入周期,大概需要10ms,此间任何操作都不会被EEPROM响应;(因此以这种方式的两次写入之间要插入一个延时,否则会导致失败,博主曾在这里小坑了一下)

在这里插入图片描述
在这里插入图片描述
IIC代码:
void I2C_SendByte(uint8_t _ucByte)
{
uint8_t xdata i;

IIC_Delay();
/* 先发送字节的高位bit7 */
for (i = 0; i < 8; i++)
{
	if (_ucByte & 0x80)
	{
		SDA = 1;
	}
	else
	{
		SDA = 0;
	}
	IIC_Delay();
	SCL = 1;
	IIC_Delay();
	SCL = 0;
	if (i == 7)
	{
		 SDA = 1;
	}
	_ucByte <<= 1;	/* 左移一个bit */
	IIC_Delay();
}

}

uint8_t I2C_ReadByte(void)
{
uint8_t xdata i;
uint8_t xdata value = 0;
IIC_Delay();
/* 读到第1个bit为数据的bit7 */
for (i = 0; i < 8; i++)
{
value <<= 1;
SCL = 1;
IIC_Delay();
if (SDA == 1)
{
value++;
}
IIC_Delay();
SCL = 0;
IIC_Delay();
}
return value;
}
void I2C_Start(void)
{
IIC_Delay();
SDA = 1; //顺序不能反了,先是SDA=1;
SCL = 1;
IIC_Delay();
SDA = 0;
IIC_Delay();
SCL = 0;
IIC_Delay();
}

/SDA上升沿/
void I2C_Stop(void)
{
IIC_Delay();
SDA = 0; //顺序不能反了,先是SDA=0;
IIC_Delay();
SCL = 1;
IIC_Delay();
SDA = 1;
}

void I2C_Ack(void)
{
IIC_Delay();
SDA = 0;
IIC_Delay();
SCL = 1;
IIC_Delay();
SCL = 0;
IIC_Delay();
SDA = 1;
}

void I2C_NAck(void)
{
IIC_Delay();
SDA = 1;
IIC_Delay();
SCL = 1;
IIC_Delay();
SCL = 0;
IIC_Delay();
}
void I2C_WaitAck(void)
{
uint8_t xdata i=100;

IIC_Delay();
SCL = 1;
IIC_Delay();
while((SDA==1)&&(i>0))
{
	IIC_Delay();
	i--;
}
SCL = 0;
IIC_Delay();
if(i==0)
{

// TDE_SendData(“noack\r”,6);
}
}

void I2C_WriteSensor(uint8_t addr,uint8_t buf)
{
I2C_Start(); /* 发送启动信号 /
I2C_SendByte(ADDRESS_LIS3DH);
I2C_WaitAck();/
检测设备的ACK应答 /
I2C_SendByte(addr);
I2C_WaitAck();/
检测设备的ACK应答 /
I2C_SendByte(buf);
I2C_WaitAck();/
检测设备的ACK应答 */
I2C_Stop();
}
void I2C_ReadSensor(uint8_t addr,uint8_t buffer,uint8_t len)
{
uint8_t xdata i;
I2C_Start(); /
发送启动信号 /
/
发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 /
I2C_SendByte(ADDRESS_LIS3DH);
I2C_WaitAck();/
检测设备的ACK应答 /
I2C_SendByte(addr);
I2C_WaitAck();/
检测设备的ACK应答 /
I2C_Start(); /
发送启动信号 /
I2C_SendByte(ADDRESS_LIS3DH+1);
I2C_WaitAck();/
检测设备的ACK应答 */
for(i=0;i<len-1;i++)
{
*buffer++=I2C_ReadByte();
I2C_Ack();
}
*buffer++ = I2C_ReadByte();
I2C_NAck();
I2C_Stop();
}
void IIC_Delay(void)
{
uint8_t xdata i;
for(i=0;i<8;i++)
{
nop();
}
}
void I2C_Init(void) //初始化
{
SDA = 1;
IIC_Delay();
SCL = 1;
IIC_Delay();
sGsensorStruct.outX = 0;
sGsensorStruct.outY = 0;
sGsensorStruct.outZ = 0;
I2C_WriteSensor(CTRL_REG1,0x67);//
I2C_WriteSensor(CTRL_REG4,0x80);//± 2g 65535/4 =16384
I2C_WriteSensor(CTRL_REG5,0x80);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值