硬件I2C实验

1配置GPIO和I2C模式

1,使能GPIOB,I2C1
RCC->APB2ENR|=1<<3;//使能GPIOB
RCC->APB1ENR|=1<<21;//使能I2C1

GPIOB->CRL&=~((u32)0x0F<<4*6);
GPIOB->CRL|=((u32)0x0F<<4*6);//配置PB6为复用开漏输出

GPIOB->CRL&=~((u32)0x0F<<4*7);
GPIOB->CRL|=((u32)0x0F<<4*7);//配置PB7为复用开漏输出
I2C_InitStructure.I2C_Ack=I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed=400000;
I2C_InitStructure.I2C_DutyCycle=I2C_DutyCycle_2;
I2C_InitStructure.I2C_Mode=I2C_Mode_I2C;
I2C_InitStructure.I2C_OwnAddress1=0x3EF;
I2C_Init(I2C1,&I2C_InitStructure);//配置i2c1模式
I2C_Cmd(I2C1,ENABLE);//使能I2C

2.写单页(不超过8个字节)

while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY))//判断总线是否忙碌
{
	if((I2C_Timeout--)==0)return I2C_TIMEOUT_UserCallPack(1);
}
I2C_GenerateSTART(I2C1,ENABLE);//发送起始信号

I2C_Timeout=I2CT_FLAG_Timeout;
while(!(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)))//检查事件EV5(事件主机模式选择)
{
	if((I2C_Timeout--)==0)return I2C_TIMEOUT_UserCallPack(2);
}

I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Transmitter);//发送地址,模式发送

I2C_Timeout=I2CT_FLAG_Timeout;
while(!(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)))//(检测事件EV6,主机发送模式已选择)
{
	if((I2C_Timeout--)==0)return I2C_TIMEOUT_UserCallPack(3);
}

I2C_SendData(I2C1,WriteAddr);//发送写入地址

I2C_Timeout=I2CT_FLAG_Timeout;
while(!(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)))//(检测事件EV8,主机数据已发送)
{
	if((I2C_Timeout--)==0)return I2C_TIMEOUT_UserCallPack(4);
}

for(i=0;i<NumToWrite;i++)
{
	I2C_SendData(I2C1,pBuffer[i]); //发送数据
	
	I2C_Timeout=I2CT_FLAG_Timeout;
	while(!(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)))//(检测事件EV8,主机数据已发送)
	{
		if((I2C_Timeout--)==0)return I2C_TIMEOUT_UserCallPack(5);
	}
}
I2C_GenerateSTOP(I2C1,ENABLE);//发送结束信号

3接受数据

u32 EEPROM_Byte_Read(u8 ReadAddr,u8 *pBuffer,u8 NumToRead)
{
u8 i;
I2C_Timeout=I2CT_LONG_Timeout;

while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY))//检查总线忙碌状态
{
	if((I2C_Timeout--)==0)return I2C_TIMEOUT_UserCallPack(6);
}

I2C_GenerateSTART(I2C1,ENABLE);//发送起始信号

I2C_Timeout=I2CT_FLAG_Timeout;
while(!(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)))//(检查事件EV5,主机模式选择)
{
	if((I2C_Timeout--)==0)return I2C_TIMEOUT_UserCallPack(7);
}

I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Transmitter);//发送地址,方向发送

I2C_Timeout=I2CT_FLAG_Timeout;
while(!(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)))//(检测事件EV6,主机发送模式已选择)
{
	if((I2C_Timeout--)==0)return I2C_TIMEOUT_UserCallPack(8);
}

I2C_SendData(I2C1,ReadAddr);//发送读取地址

I2C_Timeout=I2CT_FLAG_Timeout;
while(!(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)))//(检测事件EV8,主机数据已发送)
{
	if((I2C_Timeout--)==0)return I2C_TIMEOUT_UserCallPack(9);
}

I2C_GenerateSTART(I2C1,ENABLE);//再次发送起始信号

I2C_Timeout=I2CT_FLAG_Timeout;
while(!(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)))//(检测事件EV5,主机模式选择)
{
	if((I2C_Timeout--)==0)return I2C_TIMEOUT_UserCallPack(9);
}

I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Receiver);//发送地址,方向读取

I2C_Timeout=I2CT_FLAG_Timeout;
while(!(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)))//(检测事件EV6,主机读取模式已选择)
{
	if((I2C_Timeout--)==0)return I2C_TIMEOUT_UserCallPack(10);
}

for(i=0;i<NumToRead;i++)
{
	if(i==NumToRead-1)
	{
		I2C_AcknowledgeConfig(I2C1,DISABLE);//不回应Ack
		
		I2C_GenerateSTOP(I2C1,ENABLE);//发送停止信号
	}
		while(!(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)))//(检测事件EV7,主机数据已读取)
	{
		if((I2C_Timeout--)==0)return I2C_TIMEOUT_UserCallPack(11);
	}
	
	pBuffer[i] = I2C_ReceiveData(I2C1);
	
	I2C_Timeout=I2CT_FLAG_Timeout;
}
I2C_AcknowledgeConfig(I2C1,ENABLE);//重新使能回应Ack
}

3.等待写入

void wait_busy(void)
{
u16 SR1_Tmp;
do
{
I2C_GenerateSTART(I2C1,ENABLE);//发送起始信号
SR1_Tmp=I2C_ReadRegister(I2C1,I2C_Register_SR1);//读取sR1寄存器值
I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Transmitter);//发送地址信号,方向发送
}
while(!(I2C_ReadRegister(I2C1,I2C_Register_SR1)&0x0002));//判断字节是否发送结束
I2C_ClearFlag(I2C1,I2C_FLAG_AF);//清除应答失败标志位
I2C_GenerateSTOP(I2C1,ENABLE);//发送停止信号清除字节发送结束标志位
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值