STM32IIC外设

STM32IIC外设介绍

1、IIC通信协议

IIC通信协议是同步半双工通信协议,支持总线挂载多设备,两根通信线(SCL、SDA),带数据应答功能。
IIC时序基本单元:
起始条件:SCL高电平期间,SDA从高电平切换到低电平,之后SCL切换低电平
终止条件:SCL高电平期间,SDA从低电平切换到高电平
发送一位数据:SCL低电平期间,主机数据放置SDA,释放SCL,从机在SCL高电平期间读取数据,数据高位先行
接收一位数据:SCL低电平期间,从机数据放置SDA,释放SCL,主机在SCL高电平期间读取数据,数据高位先行。主机接收之前,需释放SDA
发送应答:主机接收字节后,发送数据。0表示应答,1表示非应答
接收应答:主机发送字节后,释放SDA接收数据。0表示应答,1表示非应答

2、STM32IIC外设资源

STM32F103C8T6有两个IIC资源,IIC1_SCL引脚为PB6,IIC1_SDA引脚为PB7,IIC2_SCL引脚为PB10,IIC2_SDA引脚为PB11。支持多主机模式,支持7位/10位地址模式。
7位地址:一位读写位,7位地址
10位地址:一位读写位,前5位必须是11110,10位地址

3、软件模拟IIC通信

1、引脚选择,配置时钟和函数封装
软件模拟IIC对引脚没有要求,可以任意引脚,这里选用PB10为SCL,PB11为SDA。
对写SCL、SDA和读SDA进行函数封装。SCL和SDA均要配置成开漏输出模式(Out_OD)

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
		
	void IIC_W_SCL(uint8_t BitValue) //写SCL
	{
		GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue);
		Delay_us(10);
	}
	
	void IIC_W_SDA(uint8_t BitValue) //写SDA
	{
		GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValue);
		Delay_us(10);
	}
	
	uint8_t IIC_R_SDA(void) //读SDA
	{
		uint8_t BitValue;
		BitValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11);
		Delay_us(10);
		return BitValue;
	}

2、起始条件

	IIC_W_SDA(1);
	IIC_W_SCL(1);
	IIC_W_SDA(0);
	IIC_W_SCL(0);

3、终止条件

	IIC_W_SDA(0);
	IIC_W_SCL(1);
	IIC_W_SDA(1);

4、发送字节

	uint8_t i;
	for(i=0;i<8;i++) //循环8次,发送字节数据
	{
		IIC_W_SDA(Byte & (0x80>>i)); //写入Byte某一位
		IIC_W_SCL(1);
		IIC_W_SCL(0);
	}

5.接收字节

	uint8_t i, Byte = 0x00;
	IIC_W_SDA(1); //接收前先释放SDA
	for (i = 0; i < 8; i ++)
	{
		IIC_W_SCL(1);
		if (IIC_R_SDA() == 1){Byte |= (0x80 >> i);}
		IIC_W_SCL(0);
	}
	return Byte;

6、发送应答

		IIC_W_SDA(AckBit);
		IIC_W_SCL(1);
		IIC_W_SCL(0);

7、接收应答

	uint8_t AckBit;
	IIC_W_SDA(1); //接收前先释放SDA
	IIC_W_SCL(1);
	AckBit=IIC_R_SDA();
	IIC_W_SCL(0);
	return AckBit;

4、硬件IIC通信(基于标准库,STM32作为主机)

1、配置时钟
引脚需配置成复用开漏输出模式,选用IIC2外设,IIC2_SCL引脚为PB10,IIC2_SDA引脚为PB11。

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;	//复用开漏输出模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

2、IIC结构体配置

	I2C_InitTypeDef I2C_InitStructure;
	I2C_InitStructure.I2C_Ack=I2C_Ack_Enable;	//开启应答
	I2C_InitStructure.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit; //响应7位地址模式
	I2C_InitStructure.I2C_ClockSpeed=50000;	//时钟数率,标准速度,50KHZ
	I2C_InitStructure.I2C_DutyCycle=I2C_DutyCycle_2;	//低电平:高电平=2:1,占空比(在时钟数率>100KHZ情况下才有用)
	I2C_InitStructure.I2C_Mode=I2C_Mode_I2C;	//I2C模式
	I2C_InitStructure.I2C_OwnAddress1=0x00;	//自主地址(作为从机才使用到)
	I2C_Init(I2C2,&I2C_InitStructure);

3、IIC使能

	I2C_Cmd(I2C2,ENABLE);

4、IIC相关常用库函数介绍

I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT); //用于检查具体事件的发生
I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);  //生成起始条件
I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState); //生成终止条件
I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction); //发送7位地址
I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data); //发送数据
I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState); //配置ACK位

5、主发送

	void  I2C_WaiteEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT) //超时退出机制,避免大量死循环等待
	{
		uint32_t Time;
		Time=10000;
		while(I2C_CheckEvent(I2Cx,I2C_EVENT)!=SUCCESS)
		{
			Time--;
			if(Time==0)
			{
				break;
			}
		}
	}
	I2C_GenerateSTART(I2C2,ENABLE);
	I2C_WaiteEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT); //检查EV5事件
	
	I2C_Send7bitAddress(I2C2,uint8_t Address,I2C_Direction_Transmitter); //第二个参数写入发送给设备的地址
	I2C_WaiteEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //检查EV6事件
	
	I2C_SendData(I2C2,uint8_t Data); //第二个参数写入发送设备寄存器的地址
	I2C_WaiteEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTING); //检查EV8事件
	
	I2C_SendData(I2C2,uint8_t Data); //发送数据
	I2C_WaiteEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED); //检查EV8_2事件

	I2C_GenerateSTOP(I2C2,ENABLE);

在这里插入图片描述
6、主接收
接收最后一个字节之前,要提前设置ACK和STOP

	uint8_t Data;
	
	I2C_GenerateSTART(I2C2,ENABLE);
	I2C_WaiteEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT); //检查EV5事件
	
	I2C_Send7bitAddress(I2C2,uint8_t Address,I2C_Direction_Transmitter); //第二个参数写入发送给设备的地址
	I2C_WaiteEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //检查EV6事件
	
	I2C_SendData(I2C2,uint8_t Data); //第二个参数写入发送设备寄存器的地址
	I2C_WaiteEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTING); //检查EV8事件
	
	I2C_GenerateSTART(I2C2,ENABLE);
	I2C_WaiteEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT); //检查EV5事件
	
	I2C_Send7bitAddress(I2C2, uint8_t Address, I2C_Direction_Receiver); //第二个参数写入需要接收哪个寄存器的地址
	I2C_WaiteEvent(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED); //检查EV6事件
	
	I2C_AcknowledgeConfig(I2C2,DISABLE); //ACK=0,不给应答
	I2C_GenerateSTOP(I2C2,ENABLE);
	
	I2C_WaiteEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED); //检查EV7事件
	Data=I2C_ReceiveData(I2C2);
	
	I2C_AcknowledgeConfig(I2C2,ENABLE); //ACK=1,给应答
	return Data;

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值