程序员

STM32F4-------I2C通信

作者:admin 2021-06-08 我要评论

STM32F4-------I2C通信 I2C两线式串行总线是由数据线SDA和时钟线SCL构成的串行总线是一种半双工通信方式。 数据线SDA有时需要用做输入有时需用做输出。需要通过M...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

STM32F4-------I2C通信

I2C:两线式串行总线,是由数据线SDA和时钟线SCL构成的串行总线,是一种半双工通信方式。

数据线SDA有时需要用做输入,有时需用做输出。需要通过MODER寄存器进行配置;

#define SDA_IN()  {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=0<<9*2;}
#define SDA_OUT() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=1<<9*2;}
#define IIC_SCL    PBout(8) //SCL
#define IIC_SDA    PBout(9) //SDA输出	 
#define READ_SDA   PBin(9)  //SDA输入

I2C协议

  1. 空闲状态;
  2. 起始信号和停止信号;
  3. 应答信号ACK;
  4. 数据的有效性;
  5. 数据传输;

1.空闲状态

数据线SDA和时钟线SCL同时处于高电平时,为I2C总线的空闲状态。

IIC_SDA = 1;
IIC_SCL = 1;

2.起始信号和停止信号

起始信号:在时钟线SCL为高电平时,数据线SDA由高跳变至低;
停止信号:在时钟线SCL为高电平时,数据线SDA由低跳变至高;
这两种信号是一种电平跳变时序信号,而不是一个电平信号。
在这里插入图片描述

//起始信号
void IIC_Start(void)
{
	SDA_OUT(); 
	IIC_SDA = 1;
	IIC_SCL = 1;
	delay_us(4);
	IIC_SDA = 0;
	delay_us(4);
	IIC_SCL = 0;
}
//停止信号
void IIC_Stop(void)
{
	SDA_OUT();
	IIC_SCL=0;
	IIC_SDA=0;
	delay_us(4);
	IIC_SCL=1; 
	IIC_SDA=1;
	delay_us(4);
}

3.应答信号ACK

发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。
应答信号为低电平时,为有效应答位(ACK);应答信号为高电平时,为非应答位(NACK),一般表示接收器接收该字节没有成功。
有效应答位(ACK):接收器在第9个时钟脉冲前的低电平期间将数据线SDA拉低,并且要保证在该时钟高电平期间数据线SDA为稳定的低电平。
在这里插入图片描述

//产生应答信号
void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}
//不产生应答信号
void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}
//等待应答信号,返回1为接收应答成功,返回0为接收应答失败
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTim=0;
	SDA_IN();    
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us(1);	 
	while(READ_SDA)
	{
		ucErrTim++;
		if(ucErrTim>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0; 	   
	return 0;  
} 

4.数据的有效性

使用I2C总线进行数据传输时,时钟线SCL为高电平期间,数据线SDA上的数据必须保持稳定。在时钟线上的信号转为低电平时,数据线上的高电平或低电平状态才允许变化。
在这里插入图片描述

5.数据传输

逐位地串行发送数据,从高位开始发送。每一位数据都有一个时钟脉冲相对应。

//数据发送
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	SDA_OUT(); 	    
    IIC_SCL=0;
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1; 	  
		delay_us(2);  
		IIC_SCL=1;
		delay_us(2); 
		IIC_SCL=0;	
		delay_us(2);
    }	 
} 	    
//数据读取
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();
    for(i=0;i<8;i++ )
	{
        IIC_SCL=0; 
        delay_us(2);
		IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
		delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();
    else
        IIC_Ack();  
    return receive;
}












;原文链接:https://blog.csdn.net/CJH32/article/details/115541090

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • 第 2 章 基本数据类型

    第 2 章 基本数据类型

  • LeetCode笔记:Weekly Contest 234 比

    LeetCode笔记:Weekly Contest 234 比

  • 2021-04-11

    2021-04-11

  • 字符串算法 |   AC自动机算法

    字符串算法 | AC自动机算法

腾讯云代理商
海外云服务器