IIC协议总结

1.基本理解

        iic通信协议:双线制串行通信协议,由时钟线SCL和数据线SDA构成.

        通信方式:主从模式,主设备发起通信,从设备响应通信

2.通信的基本步骤


    a.主设备发送一个开始信号,表示开始通信,即启动I2C  

        条件:SCL=1,SDA出现下降沿 
        IIC启动之后,SCL=1时,SDA的电平不允许有变化
                              SCL=0时,数据发送方才能在SDA上改变发送电平
    b.主设备发送一个从设备的地址和(读写位) 一般地址的长度是7bit,最后一个bit是读写指令,
        1是读(主机接收从机数据),0是写(主机发送数据到从机)
    C.仲裁机制和应答,从机只有收到自己的地址信息才会被唤醒,这个过程是以一个低电平的SDA脉冲应答,
        主机检测这个应答位,0是 1不是
    d.数据传输 确认目标后,主设备发送或者接收数据,数据传输在每个时钟周期的上升沿或者下降沿进行
    e.停止:SCL = 1,SDA出现上升沿
        注意:I2C外部需根据传输速率匹配上拉电阻,速率越高,上拉电阻越小,否则会影响时序;
                    I2C引脚作为输出时需是开漏输出,作为输入时需是浮空输入,不能匹配内部上拉或下拉电阻;
              

    3.软件模拟


    1.结构体定义总线的SDA和SCL两个引脚:用于控制两个引脚的输入输出

typedef struct{uint32_t SDA_RCC_APB2Periph;//SDA脚的时钟GPIO_TypeDef* SDA_Port;//SDA脚Portuint16_t SDA_Pin;//SDA脚Pinuint32_t SCL_RCC_APB2Periph;//SCL脚的时钟GPIO_TypeDef* SCL_Port;//SCL脚Portuint16_t SCL_Pin;//SCL脚Pin}sw_i2c_gpio_t;


     2.宏定义
      

#define I2C_USE_7BIT_ADDR //如果使用的从机地址是7Bit模式,则打开这个宏,否则注释掉这个宏#define I2C_DELAY                50 // I2C每个Bit之间的延时时间,延时越小I2C的速率越高#define SW_I2C_SCL_LOW          GPIO_ResetBits(gpio->SCL_Port,gpio->SCL_Pin) // I2C SCL脚输出0 地电平#define SW_I2C_SCL_HIGH         GPIO_SetBits(gpio->SCL_Port,gpio->SCL_Pin) // I2C SCL脚输出1 高电平#define SW_I2C_SDA_LOW          GPIO_ResetBits(gpio->SDA_Port,gpio->SDA_Pin) // I2C SDA脚输出0 低电平#define SW_I2C_SDA_HIGH         GPIO_SetBits(gpio->SDA_Port,gpio->SDA_Pin) // I2C SDA脚输出1 高电平#define SW_I2C_SDA_INPUT        sw_i2c_set_sda_input(gpio) // 将SDA脚方向设置为输入 #define SW_I2C_SDA_OUTPUT        sw_i2c_set_sda_output(gpio) // 将SDA脚方向设置为输出#define SW_I2C_SDA_STATUS        sw_i2c_sda_status(gpio) // 获取SDA脚输入电平状态  #define i2c_delay_us(a)            SystemDelayUs(a) // 延时


   3,其他准备函数
  

 SDA输入输出及状态/**************************************************************************
***                          读取SDA脚的状态                             ***
***************************************************************************/
static uint8_t sw_i2c_sda_status(sw_i2c_gpio_t *gpio)
{uint8_t sda_status;sda_status = GPIO_ReadInputDataBit(gpio->SDA_Port,gpio->SDA_Pin);    return sda_status?1:0;
}
/**************************************************************************
***                          设置SDA脚为输入                             ***
***************************************************************************/
static void sw_i2c_set_sda_input(sw_i2c_gpio_t *gpio)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = gpio->SDA_Pin;    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init (gpio->SDA_Port, & GPIO_InitStructure );
}
/**************************************************************************
***                          设置SDA脚为输出                             ***
***************************************************************************/
static void sw_i2c_set_sda_output(sw_i2c_gpio_t *gpio)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = gpio->SDA_Pin;    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;   //开漏输出模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init (gpio->SDA_Port, & GPIO_InitStructure );
}I2C启动static void sw_i2c_start(sw_i2c_gpio_t *gpio)
{// I2C 开始时序:SCL=1时,SDA由1变成0.SW_I2C_SDA_HIGH;         i2c_delay_us(I2C_DELAY);SW_I2C_SCL_HIGH;           i2c_delay_us(I2C_DELAY);SW_I2C_SDA_LOW;i2c_delay_us(I2C_DELAY);SW_I2C_SCL_LOW;i2c_delay_us(I2C_DELAY);
}
I2C停止
static void sw_i2c_stop(sw_i2c_gpio_t *gpio)
{// I2C 开始时序:SCL=1时,SDA由0变成1.SW_I2C_SDA_LOW;i2c_delay_us(I2C_DELAY);SW_I2C_SCL_HIGH;i2c_delay_us(I2C_DELAY);SW_I2C_SDA_HIGH;
}等待数据接收方反馈
static uint8_t sw_i2c_wait_ack(sw_i2c_gpio_t *gpio)
{uint8_t sda_status;uint8_t wait_time=0;uint8_t ack_nack = 1;//先设置SDA脚为输入SW_I2C_SDA_INPUT;//等待SDA脚被从机拉低while(SW_I2C_SDA_STATUS){wait_time++;//如果等待时间过长,则退出等待if (wait_time>=200){ack_nack = 0;break;}}// SCL由0变为1,读入ACK状态// 如果此时SDA=0,则是ACK// 如果此时SDA=1,则是NACKi2c_delay_us(I2C_DELAY);SW_I2C_SCL_HIGH;i2c_delay_us(I2C_DELAY);//再次将SCL=0,并且将SDA脚设置为输出SW_I2C_SCL_LOW;i2c_delay_us(I2C_DELAY);SW_I2C_SDA_OUTPUT;i2c_delay_us(I2C_DELAY);return ack_nack;
}发送ACK给数据发送方  应答信号
static void sw_i2c_send_ack(sw_i2c_gpio_t *gpio)
{// 发送ACK就是在SDA=0时,SCL由0变成1SW_I2C_SDA_LOW;i2c_delay_us(I2C_DELAY);SW_I2C_SCL_HIGH;i2c_delay_us(I2C_DELAY);SW_I2C_SCL_LOW;i2c_delay_us(I2C_DELAY);
}发送NACK给数据发生方 非应答信号,表示接受没有成功
static void sw_i2c_send_nack(sw_i2c_gpio_t *gpio)
{// 发送NACK就是在SDA=1时,SCL由0变成1SW_I2C_SDA_HIGH;i2c_delay_us(I2C_DELAY);SW_I2C_SCL_HIGH;i2c_delay_us(I2C_DELAY);SW_I2C_SCL_LOW;i2c_delay_us(I2C_DELAY);
}

4.主设备接受和发送字节 

static void sw_i2c_write_byte(sw_i2c_gpio_t *gpio,uint8_t aByte)
{uint8_t i;for (i=0;i<8;i++){//先将SCL拉低;SW_I2C_SCL_LOW;i2c_delay_us(I2C_DELAY);//然后在SDA输出数据if(aByte&0x80){SW_I2C_SDA_HIGH;}else{SW_I2C_SDA_LOW;}i2c_delay_us(I2C_DELAY);//最后将SCL拉高,在SCL上升沿写入数据SW_I2C_SCL_HIGH;i2c_delay_us(I2C_DELAY);aByte = aByte<<1;//数据位移}//写完一个字节只后要将SCL拉低SW_I2C_SCL_LOW;i2c_delay_us(I2C_DELAY);
}主设备从从设备读取字节
static uint8_t sw_i2c_read_byte(sw_i2c_gpio_t *gpio)
{uint8_t i,aByte;//先将SDA脚设置为输入SW_I2C_SDA_INPUT;for (i=0;i<8;i++){//数据位移aByte = aByte << 1;//延时等待SDA数据稳定i2c_delay_us(I2C_DELAY);//SCL=1,锁定SDA数据SW_I2C_SCL_HIGH;i2c_delay_us(I2C_DELAY);//读取SDA状态if(SW_I2C_SDA_STATUS){aByte |= 0x01;}//SCL=0,解除锁定SW_I2C_SCL_LOW;}//读完一个字节,将SDA重新设置为输出SW_I2C_SDA_OUTPUT;return aByte;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/716726.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python开源项目月排行 2024年2月

Python 趋势月报&#xff0c;按月浏览往期 GitHub,Gitee 等最热门的Python开源项目&#xff0c;入选的项目主要参考GitHub Trending,部分参考了Gitee和其他。排名不分先后&#xff0c;都是当前月份内相对热门的项目。 入选公式&#xff1d;70%GitHub Trending20%Gitee10%其他 …

jvm面试题-背诵版

按照思维导图抽查和记忆&#xff0c;答案见&#xff1a;四、面试-多线程/并发_scheduledfuture释放-CSDN博客

Jmeter系列(4) 线程属性详解

线程属性 线程组是配置压测策略的一个重要环节线程组决定了测试执行的请求数量 线程数 在这里线程数相当于一个虚拟用户每个线程数大约占内存1M特别注意⚠️ 单台机器最大线程数不要超过1000&#xff0c;不然可能会造成内存溢出 Ramp-Up时间 所有线程在多长时间内全部启动…

【网络工程设计】用GNS3和VMware搭建网络环境

&#x1f4dd;本文介绍 本文主要是使用GNS3和VMware来搭建网络环境 &#x1f44b;作者简介&#xff1a;一个正在积极探索的本科生 &#x1f4f1;联系方式&#xff1a;943641266(QQ) &#x1f6aa;Github地址&#xff1a;https://github.com/sankexilianhua &#x1f511;Gitee地…

计算机网络-第2章 物理层

本章内容&#xff1a;物理层和数据通信的概念、传输媒体特点&#xff08;不属于物理层&#xff09;、信道复用、数字传输系统、宽带接入 2.1-2.2 物理层和数据通信的概念 物理层解决的问题&#xff1a;如何在传输媒体上传输数据比特流&#xff0c;屏蔽掉传输媒体和通信手段的差…

文献阅读笔记《Spatial-temporal Forecasting for Regions without Observations》13页

目录 目录 目录 发行刊物 ABSTRACT 1 INTRODUCTION 2 RELATED WORK&#xff08;相关工作 2.1 Spatial-temporal Forecasting&#xff08;时空预测 2.2 Spatial-temporal Forecasting withIncomplete Data&#xff08;不完全数据的时空预测 2.3 Graph Contrastive Lear…

蓝桥杯集训·每日一题2024 (前缀和)

笔记&#xff1a; 例题&#xff1a; #include<bits/stdc.h> using namespace std; const int N 5000010; char str[N]; int s[N]; int main(){int t;cin>>t;for(int a1;a<t;a){int n;cin>>n;scanf("%s",str1);for(int i1;i<n;i){s[i]s[i-1]…

【MySQL】:约束全解析

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; MySQL从入门到进阶 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一. 约束概述二. 约束演示三. 外键约束3.1 介绍3.2 语法3.3 删除/更新行为 &…

Mybatis - generator(自动生成)

1、生成数据库数据 2、配置pom文件 这个plugin文件里有配置项和依赖以及版本号 修改configurationFile路径为项目里存在的generatorConfig.xml文件&#xff0c;因为后续的配置都在这个文件中进行。 <plugin><groupId>org.mybatis.generator</groupId><…

Netty的InboundHandler 和OutboundHandler

一、InboundHandler 和OutboundHandler的区别 在Netty中&#xff0c;"inbound"表示来自外部来源&#xff08;如网络连接&#xff09;的数据&#xff0c;而"outbound"则表示从应用程序发送到外部目标&#xff08;如网络连接或其他服务&#xff09;的数据。…

Git——Upload your open store

0.default config ssh-keygen -t rsa #之后一路回车,当前目录.ssh/下产生公私钥 cat ~/.ssh/id_rsa.pub #复制公钥到账号 git config --global user.email account_email git config --global user.name account_name1. 上传一个公开仓库 查看当前分支&#xff1a; git branc…

MATLAB基于隐马尔可夫模型-高斯混合模型-期望最大化的MR图像分割

隐马尔可夫模型是一种统计模型&#xff0c;它描述了马尔可夫过程&#xff0c;隐马尔可夫过程中包含隐变量&#xff0c;语音识别和词性自动标注等一些领域常常使用隐马尔可夫模型方法来处理。马尔可夫过程是一类随机过程&#xff0c;马尔可夫链是它的原始模型&#xff0c;马尔可…

GPT对话知识库——FreeRTOS中寄存器BASEPRI的作用

提问模型&#xff1a;GPT-4-TURBO-PREVIEW 提问时间&#xff1a;2024.03.02 1&#xff0c;问&#xff1a; 举例详细说明寄存器BASEPRI在freertos中作用 1&#xff0c;答&#xff1a; 在使用FreeRTOS这样的实时操作系统时&#xff0c;确保系统的实时性和响应能力至关重要。其中…

【C++那些事儿】深入理解C++类与对象:从概念到实践(中)| 默认构造函数 | 拷贝构造函数 | 析构函数 | 运算符重载 | const成员函数

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构冒险记 ✅C那些事儿 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 文章目录 1. 类的6个默认成员函数2. 构造函数2.1 概念2.2 特性 3. 析构函数3.1 概念3.2 特性 4. 拷贝…

国际视频编解码标准提案下载地址

H.266 相关提案下载地址&#xff1a;http://phenix.it-sudparis.eu/jvet/ 更新的地址&#xff1a;https://jvet-experts.org/ H.265 提案下载地址&#xff1a;http://phenix.int-evry.fr/jct/ 标准文档下载地址&#xff1a;http://www.itu.int/rec/T-REC-H.265 H.264 提案下载…

QT多语言切换功能

一.目的 在做项目时&#xff0c;有时希望我们的程序可以在不同的国家使用&#xff0c;这样最好的方式是一套程序能适应于多国语言。 Qt提供了这样的功能&#xff0c;使得一套程序可以呈现出不同的语言界面。本文将介绍QT如何实现多语言&#xff0c;以中文和英文为例。 QT开发…

过于老旧的pytorch_ssim包 请从github下载源码

有些冷门算法真的不要随便pip&#xff0c;有可能下载到史前版本…最好还是找源代码 汗 今天要用到SSIM损失函数&#xff0c;从网上简单看了一下原理就想测试一下&#xff0c;偷了一下懒就直接在命令行输入pip install pytorch_ssim了&#xff0c;结果报了一堆错误&#xff08;汗…

Qt将Unicode转换成UTF8中文

解析字符串&#xff0c;并将里面的Unicode转换成中文 QString unicodeToUtf8(QString unicode) {QString result;for (int i 0; i < unicode.length(); i){QString flag unicode.mid(i,2); if (flag "\\u"){QString s1 unicode.mid(i 2, 4);result.append(s…

如何自定义一个spring-boot-starter

在我的理解中&#xff0c;spring-boot-starter就是一个依赖工具包&#xff0c;但是它和普通的依赖又有所区别&#xff0c;那么首先spring-boot-starter-一定是一个spring-boot项目&#xff0c;然后它和一般的依赖有什么区别呢&#xff0c;我们可以在它的resources目录下定义一个…

Mysql实战(1)之环境安装

1&#xff0c;进入&#xff1a;MySQL :: MySQL Downloads 2&#xff0c; 3&#xff0c; 4&#xff0c;