蓝桥杯STM32G431学习记录6——IIC基本原理

IIC基本原理

在学习IIC时由于用到了通信方式学习串口时只是大概看了一下,所以在这里先复习一下之前的内容
处理器与外部设备通信的两种方式:
并行通信
-传输原理:数据各个位同时传输。-优点:速度快
-缺点:占用引脚资源多
串行通信
-传输原理:数据按位顺序传输。-优点:占用引脚资源少
-缺点:速度相对较慢

串行通信:按照数据传送方向,分为:
1、单工:数据传输只支持数据在一个方向上传输;
2、半双工:允许数据在两个方向上传输但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;
3、全双工:允许数据同时在两个方向上传输因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。
在这里插入图片描述

串行通信的通信方式:
同步通信:带时钟同步信号传输。-SPI, IIC通信接口
异步通信:不带时钟同步信号。-UART(通用异步收发器),单总线
下图为常见的串口通信
在这里插入图片描述

多主机I2C总线系统结构

I2C(IC,Inter—Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备。
它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IC总线一般可达40Oops以上。IIC是半双工通信方式
在这里插入图片描述
I2C总线是不同的IC或模块之间的双向两线通信。这两条线是串行数据线(SDA)和串行时钟线(SCL)。这两条线必须通过上拉电路连接至正电源。数据传输只能在总线不忙时启动

开始/停止信息

数据线和时钟线在总线不忙时保持高电平。在时钟线SCL为高电平时,数据线SDA上的一个由高到低的下降沿变化被定义为开始条件。时钟线SCL为高电平时,数据线SDA上的一个由低到高的上升沿变化被定义为停止条件。

在这里插入图片描述

/**
  * @brief I2C起始信号
  * @param None
  * @retval None
  */
void I2CStart(void)
{
    SDA_Output(1);
    delay1(DELAY_TIME);
    SCL_Output(1);
    delay1(DELAY_TIME);	//SCL和SDA在总线空闲时处于高电平
    SDA_Output(0);
    delay1(DELAY_TIME);	//SDA信号拉低
    SCL_Output(0);
    delay1(DELAY_TIME);
}
/**
  * @brief I2C结束信号
  * @param None
  * @retval None
  */
void I2CStop(void)
{
    SCL_Output(0);
    delay1(DELAY_TIME);
    SDA_Output(0);
    delay1(DELAY_TIME);	//时钟线和数据线处于低电平
    SCL_Output(1);
    delay1(DELAY_TIME);	//SCL为高电平
    SDA_Output(1);
    delay1(DELAY_TIME);	//SDA拉高

}

应答信号ACK

发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功
在这里插入图片描述

/**
  * @brief I2C等待确认信号
  * @param None
  * @retval None
  */
unsigned char I2CWaitAck(void)
{
    unsigned short cErrTime = 5;
    SDA_Input_Mode();				//数据输入模式
    delay1(DELAY_TIME);
    SCL_Output(1);					//SCL为高电平
    delay1(DELAY_TIME);
    while(SDA_Input())				//当数据输入不为0,没有收到应答
    {
        cErrTime--;					//延时5个delay1(DELAY_TIME)
        delay1(DELAY_TIME);
        if (0 == cErrTime)
        {
            SDA_Output_Mode();		//SDA变为输出模式
            I2CStop();				//停止
            return ERROR;			//无应答
        }
    }
    SDA_Output_Mode();				//当数据输入为0收到应答变为数据输出模式
    SCL_Output(0);					//SCL为低电平	SCL一高一低发送一位数据
    delay1(DELAY_TIME);
    return SUCCESS;					//有应答
}
/**
  * @brief I2C发送确认信号
  * @param None
  * @retval None
  */
void I2CSendAck(void)
{
    SDA_Output(0);					//SDA为低电平发送应答ACK
    delay1(DELAY_TIME);
    delay1(DELAY_TIME);
    SCL_Output(1);
    delay1(DELAY_TIME);
    SCL_Output(0);
    delay1(DELAY_TIME);				//SCL一高一低发送一位数据
}
/**
  * @brief I2C发送非确认信号
  * @param None
  * @retval None
  */
void I2CSendNotAck(void)
{
    SDA_Output(1);					//SDA为高电平发送非应答NACK
    delay1(DELAY_TIME);
    delay1(DELAY_TIME);
    SCL_Output(1);
    delay1(DELAY_TIME);
    SCL_Output(0);
    delay1(DELAY_TIME);				//SCL一高一低发送一位数据
}

将“i2c.c”中 I2CWaitAck()函数后部的语句:
SDA_output_Mode () ;
SCL_output (0) ; delay1 (DELAY_TIME) ;
修改为(交换顺序,原顺序在高主频时会错误产生停止条件):
SCL_output(0) ; delay1 (DELAY_TIME) ;
SDA_output_Mode () ;

数据信息

一个数据位在每一个时钟脉冲期间传输。SDA线上的数据必须在时钟脉冲的高电压期间保持稳定,这个期间数据线上的改变将被当作控制信号。
在这里插入图片描述

/**
  * @brief I2C发送一个字节
  * @param cSendByte 需要发送的字节
  * @retval None
  */
void I2CSendByte(unsigned char cSendByte)
{
    unsigned char  i = 8;				//传输8位 1个字节
    while (i--)
    {
        SCL_Output(0);					//SCL拉低
        delay1(DELAY_TIME);
        SDA_Output(cSendByte & 0x80);	//SDA输出cSendByte最高位
        delay1(DELAY_TIME);
        cSendByte += cSendByte;			//实现数据左移1位 效果与cSendByte<<1相同
        delay1(DELAY_TIME);
        SCL_Output(1);					//SCL拉高 发送数据
        delay1(DELAY_TIME);
    }
    SCL_Output(0);						//SCL拉低 发送完成
    delay1(DELAY_TIME);
}

/**
  * @brief I2C接收一个字节
  * @param None
  * @retval 接收到的字节
  */
unsigned char I2CReceiveByte(void)
{
    unsigned char i = 8;
    unsigned char cR_Byte = 0;
    SDA_Input_Mode();					//SDA变为输入模式 开始读数据
    while (i--)
    {
        cR_Byte += cR_Byte;				//读入的数据左移一位
        SCL_Output(0);
        delay1(DELAY_TIME);
        delay1(DELAY_TIME);
        SCL_Output(1);
        delay1(DELAY_TIME);
        cR_Byte |=  SDA_Input();		//将读入的数据的值给要返回的数cR_Byte 
    }
    SCL_Output(0);
    delay1(DELAY_TIME);
    SDA_Output_Mode();					//SDA变为默认的输出模式 停止读数据
    return cR_Byte;
}

空闲状态

I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。

版权声明:本文为CSDN博主「lzya.」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_52542756/article/details/122682198

生成海报
点赞 0

lzya.

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32F2————配置时钟延迟不准的问题

STM32F2配置时钟问题 笔者在本科毕业设计使用STM32F207芯片,但是在配置时钟时出现了问题。 问题 我按照F1写代码的延时函数放在F2竟然不准了 换个办法 使用Systick时钟也是不准,原因是笔者代

为什么重写printf函数没有用?

以前在网上找了无数方法去重写printf函数,但发现都没效果,今天偶然发现重写printf函数可以了,原因是以前没有勾选微库(Use MicroLlB)! 这里