使用 GD32F470ZGT6,手写 I2C 的实现

我的代码:https://gitee.com/a1422749310/gd32_-official_-code
I2C 具体代码位置:https://gitee.com/a1422749310/gd32_-official_-code/blob/master/Hardware/i2c/i2c.c
黑马 - I2C原理
官方 - IIC 协议介绍

个人学习过程中的理解,有错误,欢迎指出

移植

【I2C 具体代码位置】中,要更改代码的地方

#define SCL(bit) gpio_bit_write(GPIOB, GPIO_PIN_6, bit == 1 ? SET : RESET);
#define SDA(bit) gpio_bit_write(GPIOB, GPIO_PIN_7, bit == 1 ? SET : RESET);
#define DELAY()  delay_1us(5);#define SDA_IN() gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_7);
#define SDA_OUT() gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7);
#define SDA_STATE() gpio_input_bit_get(GPIOB, GPIO_PIN_7)以及 
void I2C_Init()

其他地方,都是和平台无关的

写数据

SCL、SDA 数据的四种形式

在这里插入图片描述

在这里插入图片描述

SCL 和 SDA 的高低电平的持续时间是多少?

回答这个问题,需要涉及:I2C总线的时钟频率
I2C总线的时钟频率,通常在100kHz到400kHz之间,其中

  • 100kHz是标准模式(Standard Mode)
    • 1秒钟,就是 1 000 000us,100 000 个bit,相除,可得:10us 1bit
    • 👆 10us,才得到一个 bit,那么,睡眠的时候,就是 5us(一半,用于开始、停止的变化)
  • 400kHz是快速模式(Fast Mode)
    • 1秒钟,就是 1 000 000us,400 000 个bit,相除,可得:2.5us 1bit
      此外,I2C总线还支持更高速度
  • 高速模式(High Speed Mode):1MHz
  • 超高速模式(Ultra-Fast Mode):5MHz

因此,SCL 和 SDA 的高低电平的持续时间是多少?要看具体使用的 I2C 的外设的 datasheet
比如,如果某个 datasheet 上面写了 100kHz,那么,就是 10us 1bit,就 #define DELAY() delay_1us(5);

开始、结束、发送、等待响应总结

  • 开始(Start):正弦函数
  • 结束(Stop):左边有 1 竖(都是低电平)的【凹函数】
  • 发送(Send):SDA准备 🏃‍,持续3个delay;SCL 从暴富到破产(或者理解为跳水,但是,跳水,SDA 用了。 所以,可以这么理解:SCL,老板,指挥官,与财富相关,SDA,员工,行动派,与行为相关)
  • 等待响应(Wait ACK):SCL、SDA 亲亲😘;SCL 从暴富到破产,SDA 控制权转移
    👆 很奇怪,之前用【亲亲】,感觉不好意思🥵,于是改成【靠近】,后来发现,还是亲亲好,上头😓
    👇 可以看到,只有【开始】(绿点)和【结束】(橙点),有比较长的 SCL(上面的信号是 SCL)(也印证了SCL 连续高两次)
    在这里插入图片描述

懒得复制图片了,直接看这个链接吧 黑马 - IIC

1、开始 Start:【正弦函数】

[图片]

  • 1:SCL 之前,SDA,一定是高的,不然没法下落
  • 2:SCL,暴富,站起来了(起作用了)
  • 3:将 SDA 拉低
  • 4:SCL,破产,没落了,代表之后不起作用了(虎落平阳被犬欺)

买的淘宝链接(👈 LIXIN 给的链接,买贵了。。。)19.5 USB逻辑分析仪
黑马 - 逻辑分析仪
下载:逻辑分析仪Logic-2.4.9-windows-x64.exe

[图片]
[图片]

I2C 要进行配置 👇
[图片]
[图片]
[图片]

最终 👇,注意采样率,不要太低,我之前设置为 100kS/s,采样的波形,是错误的(当时没理解概念,将 100kS/s 和之前的 100kHz是标准模式 那个联系在一起了🤡。。。)
[图片]

2、结束 Stop:左边有 1 竖的【凹函数】

[图片]
[图片]
👆,这里,开始的 4 和结束的 1,共了

  • 1:SCL、SDA 同时变低,方便 SCL 站起来

  • 2:SCL,暴富,站起来了(起作用了)

  • 3:SDA,上岸(游泳🏊‍结束)
    static void stop() {
    SCL(0);
    SDA(0);
    DELAY(); // <— 视频中没有加 delay

    SCL(1);
    DELAY();

    SDA(1);
    DELAY();
    }

2.1、结束代码,有问题

👆 视频中代码有问题,没有加 delay
[图片]
[图片]
测试代码如下 👇,对应波形 👆
可以看到,stop 中,SCL(0)、SDA(0) 后,立马 SCL(1),在波形上,显示的是,是很窄的一个波形(👆 右图中,绿色,1、1 的框框)
另外,注意上面图片中,中间的区域,我将其设置为 11、00、11,目的是为了对比(之后 2.2 中,有关于对这个波形的讨论)
static void stop()
{
SDA_OUT(); // SDA 重新获得控制权,SDA 变成输出

SCL(0);
SDA(0);
// DELAY(); 未加 delaySCL(1);
DELAY();SDA(1);
DELAY();

}

void test_wave()
{
start();

// 中间
SCL(1);    SDA(1);    DELAY();SCL(0);    SDA(0);    DELAY();SCL(1);    SDA(1);    DELAY();stop();

}
加上 delay 之后的波形 👇
[图片]
[图片]
所以我认为,虽然效果是一样,但是,还是加下好些

2.2、结束代码,有问题例子中,中间波形分析

// 中间
SCL(1); SDA(1); DELAY();

SCL(0); SDA(0); DELAY();

SCL(1); SDA(1); DELAY();
[图片]
[图片]
👆,并不是我之前认为的,SCL(1) 、SDA(1),波形就同时变高,而是有一个偏移(SDA,向右偏一点)
并且,SCL(1)、SDA(1),宽度也是不一样的

那么,如果我先设置 SDA 呢?
// 中间
SDA(1); SCL(1); DELAY();

SDA(0); SCL(0); DELAY();

SDA(1); SCL(1); DELAY();
[图片]

[图片]
👆 右图,因为 SDA 提前设置,所以,在 SCL 之前,变低(图中显示,红色在黄色,内部)

但是,之后,第 3 个 SDA(1); SCL(1);,预想中,应该是 SDA 先拉高,SCL 在拉高(可实际上,是 SCL 先拉高)
一种解释,是程序编译的时候,SDA(1); SCL(1); 交换了位置???那为什么 SDA(0); SCL(0); 没有交换?
所以,应该不是这个原因
另一种解释:SDA(1),SDA 拉高的时候,相比于 SCL(1) ,比较耗时,我认为这个是比较合理一点的解释

问下 ChatGPT
你的分析非常到位!让我们一起深入探讨你提出的两个可能的解释:

  1. 程序编译时的代码顺序
    这种解释是比较不太可能的原因。在编译阶段,SDA(1) 和 SCL(1) 的顺序应该是严格按照程序中写的顺序执行的,编译器并不会自动交换这些信号的顺序,除非有特别的宏或硬件抽象层对这些函数做了特殊的处理。所以,SDA(1) 和 SCL(1) 顺序交换的问题,可以排除。
  2. SDA 拉高的耗时问题
    这个解释是比较合理的。
  • SDA 拉高时的时间问题:由于 I2C 总线的物理特性,SDA 线上的信号变化相对较慢,尤其是在高电平拉升时。如果你直接将 SDA 设置为高电平,可能需要一点时间来使 SDA 线达到稳定的高电平状态。而 SCL 线在此时是由外部的时钟拉升的,这意味着如果没有延时,SCL 会很快拉高,但 SDA 可能还没有达到稳定的高电平,导致了信号的不稳定或者错误。
  • SCL 的变化时间较短:SCL 线的状态变化通常由外部时钟控制,所以其变化速度通常比较快。而 SDA 由于是由主设备控制,并且存在内部拉升电阻或者其他电路因素,所以 SDA 的拉高通常会稍微慢一些,尤其是在低电平拉升到高电平时,可能会有延迟。
    为什么 SDA(0); SCL(0); 没有问题?
    当你将 SDA 和 SCL 都拉低时,情况就简单了。因为 I2C 的标准定义在 SDA 和 SCL 都为低电平时,它们处于稳定状态,几乎没有信号的延迟或时序问题。所以 SDA(0); SCL(0); 不会引起问题。
    总结:
    更可能的原因是 SDA 拉高时的时间延迟。 由于 SDA 拉高的过程相较于 SCL 更加耗时,可能会导致在 SDA(1) 和 SCL(1) 同时设置时,SCL 先拉高了,而 SDA 还没有完全稳定。
    3、发送 Send:SDA准备,持续3个delay;SCL 从暴富到破产
    [图片]
    [图片]
  • 1:SDA 准备了
  • 2:SCL,暴富,站起来了(起作用了)
  • 3:SCL,破产,没落了,代表之后不起作用了(虎落平阳被犬欺)
    👆,可以看到,起作用的传输数据,持续了 3 的 delay(准备前、SCL 变高时、SCL 变低时)

4、等待响应 Wait ACK:SCL、SDA 亲亲😘;SCL 从暴富到破产,SDA 控制权转移
[图片]
[图片]

  • 1:SCL、SDA 亲亲😘:SDA 变高,期望跳水;;;SCL 变低,破产,期望暴富,起作用,站起来
  • 2:SCL 高电平,站起来了(起作用了),此时,SDA,已经让出控制权了,然后,观察 SDA
    • SDA:低电平,代表应答
    • SDA:高电平,代表不应答
    • SDA,代表了,主动权
  • 3:SCL,没落了,代表之后不起作用了(虎落平阳被犬欺)

模拟下成功,然后看看波形
模拟的时候,不要开 SDA_IN,会影响波形
static void wait_ack()
{
SDA(1);
SCL(0);
DELAY();

#if MOCK_WAIT_ACK_SUCCESS == 0
// SDA 交出控制权,SDA 变为输入
SDA_IN();
#endif

SCL(1);

#if MOCK_WAIT_ACK_SUCCESS
// 模拟从机,将 SDA 置 1,代表成功响应主机
SDA(0);
#endif
DELAY();

if (RESET == SDA_STATE() || 1 == MOCK_WAIT_ACK_SUCCESS)
{// 成功SCL(0);SDA_OUT();  // SDA 重新获得控制权,SDA 变成输出
}
else
{stop();
}

}
最终波形如下 👇
[图片]

[图片]


read
rece 和 send 通讯信号都是一样的,但是区别:SDA 的信号来源,来自:从设备
[图片]

发送响应:SCL、SDA 开始:ACK 不亲亲🫸,NACK 亲亲😘;SCL 从暴富到破产;最后都亲亲😘
[图片]
[图片]

最后,I2C_Read(0x01, 0x02, &data, 1);(后面 len 改为 2,可以分析 ACK) 输出波形如下
[图片]

[图片]
[图片]
[图片]
可以看到,接收,只有 1、2 —— 设置,是在 SCL(0) 的时候,设置的

模拟代码如下 👇,1011 0010 = 0xB2,和波形一致
#define MOCK_READ_DATA 1

static uint8_t recv()
{
#if MOCK_READ_DATA == 0
// SDA 交给从设备,主设备,应该是输入状态
SDA_IN();
#endif

#if MOCK_READ_DATA
// 1011 0010 = 0xB2
uint8_t mock_bit_array[8] = {1, 0, 1, 1, 0, 0, 1, 0};
#endif

uint8_t data = 0;
for (uint8_t i = 0; i < 8; i++)
{// 给机会,给从设备,准备数据SCL(0);

#if MOCK_READ_DATA
SDA(mock_bit_array[i]); // <— 设置,是在 SCL(0) 的时候,设置的
#endif
DELAY();

   // 开始设置数据有效性SCL(1);

#if MOCK_READ_DATA
data |= mock_bit_array[i] << (7 - i);
#else
data |= SDA_STATE() << (7 - i);
#endif

   DELAY();// SCL(0); 因为下一个循环,还是低电平,这里可以省略
}
// 最后一次,是高电平,不会循环回来,所以,要加上低电平,代表 SCL 没落了
SCL(0);return data;

}

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

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

相关文章

VSCode,Anaconda,JupyterNotebook

文章目录 一. 下载VSCode并安装二. 下载Anaconda并安装1. anaconda介绍2. Anaconda的包管理功能3. Anaconda的虚拟环境管理4.Jupyter Notebook5. Jupyter Notebook使用简介6. Jupyter Notebook快捷键7.Jupyter notebook的功能扩展8. Jupyter notebook和Jupyter lab的区别 三. V…

【安全研究】某黑产网站后台滲透与逆向分析

文章目录 x01. 前言x02. 分析 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python与爬虫领域研究与…

力扣 343. 整数拆分 (JAVA 记忆化搜索->动态规划)

给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 示例 1: 输入: n 2 输出: 1 解释: 2 1 1, 1 1 1。 示例 2: 输入: n 10 输出: 36 解释: 10 3 …

一次tomcat实战jvm线上问题定位排查和解决

问题分析&#xff1a; 问题来源是客户通过闲鱼找到了我这边进行问题的排查&#xff0c;给我发了一个报错日志&#xff0c;让我帮忙分析。 首先他的项目比较老&#xff0c;很多年以前开发的软件&#xff0c;但是具体做什么业务我不知道。下面来看日志的报错分析。 问题&#…

【Linux】软硬链接

文章目录 软链接硬链接软硬链接的使用场景&#xff1a;软链接的使用场景硬链接的应用场景 总结 软链接 软链接是一种指向文件或目录的快捷方式&#xff0c;是文件系统中非常重要的功能。它类似于Windows中的快捷方式&#xff0c;但更灵活&#xff0c;可以跨文件系统创建。 ln…

操作系统(5)进程

一、定义与特点 定义&#xff1a;进程是计算机中的程序关于某数据集合上的一次运行活动&#xff0c;是系统进行资源分配和调度的基本单位&#xff0c;是操作系统结构的基础。 特点&#xff1a; 动态性&#xff1a;进程是动态创建的&#xff0c;有它自身的生命周期&#xff0c;…

安宝特分享 | AR技术助力医院总院与分院间的远程面诊

随着科技的迅猛发展&#xff0c;增强现实&#xff08;AR&#xff09;技术在各行各业的应用愈发广泛&#xff0c;特别是在医疗领域&#xff0c;其潜力和价值正在被不断挖掘。在现代医疗环境中&#xff0c;患者常常面临“看病难、看病远、看病急”等诸多挑战&#xff0c;而安宝特…

CNCF云原生生态版图-分类指南(三)- 运行时

CNCF云原生生态版图-分类指南&#xff08;三&#xff09;- 运行时 CNCF云原生生态版图-分类指南三、运行时&#xff08;Runtime&#xff09;&#xff08;一&#xff09;云原生存储&#xff08;Cloud Native Storage&#xff09;1. 是什么&#xff1f;2. 解决什么问题&#xff1…

通俗易懂的 Nginx 反向代理 配置

通俗易懂的 Nginx 反向代理 配置 首先 root 与 alias 的区别 root 是直接拼接 root location location /i/ {root /data/w3; }当请求 /i/top.gif &#xff0c;/data/w3/i/top.gif 会被返回。 alias 是用 alias 替换 location location /i/ {alias /data/w3/images/; }当请…

HiveQL命令(一)- 数据库操作

文章目录 前言一、数据库操作1. 创建数据库1.1 语法及解释1.2 创建数据库示例 2. 查看数据库2.1 查看所有数据库2.2 查看数据库信息2.2.1 语法及解释2.2.2 查看数据库信息示例 3. 切换数据库3.1 语法3.2 示例 4. 修改数据库4.1 语法4.2 示例 5. 删除数据库5.1 语法及解释5.2 示…

Ubuntu22.04安装docker desktop遇到的bug

1. 确认已启用 KVM 虚拟化 如果加载了模块&#xff0c;输出应该如下图。说明 Intel CPU 的 KVM 模块已开启。 否则在VMware开启宿主机虚拟化功能&#xff1a; 2. 下一步操作&#xff1a; Ubuntu | Docker Docs 3. 启动Docker桌面后发现账户登陆不上去&#xff1a; Sign in | …

FPGA实现GTP光口数据回环传输,基于Aurora 8b/10b编解码架构,提供2套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目我这里已有的 GT 高速接口解决方案 3、工程详细设计方案工程设计原理框图用户数据发送模块基于GTP高速接口的数据回环传输架构GTP IP 简介GTP 基本结构GTP 发送和接收…

(二)多智能体强化学习

目录 前言 一、多智能体强化学习的概念 二、多智能体面临的问题 三、现有算法简介 总结 前言 基于上一篇文章对于强化学习基础概念的介绍&#xff0c;本篇文章针对多智能体强化学习进行介绍和总结&#xff0c;帮助大家了解多智能体的基本概念以及算法&#xff0c;方便大家…

【Linux网络编程】传输协议UDP

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 &#x1f308;个人主页&#xff1a; 南桥几晴秋 &#x1f308;C专栏&#xff1a; 南桥谈C &#x1f308;C语言专栏&#xff1a; C语言学习系…

汽车车牌识别数据集,支持YOLO,COCO,VOC格式的标注,8493张图片,可识别多种环境下的车牌

汽车车牌识别数据集&#xff0c;支持YOLO&#xff0c;COCO&#xff0c;VOC格式的标注&#xff0c;8493张图片&#xff0c;可识别多种环境下的车牌 数据集分割 训练组82&#xff05; 6994图片 有效集12&#xff05; 999图片 测试集6% 500图片 预处理 自动…

流网络复习笔记

所以这里的19是118-019 <s , w> 1/3就是容量是3&#xff0c;流量是1 残留网络就是两个相对箭头上都是剩余对应方向还能同行的流量 所以s->w 3-1 2, w->s 1

Mac m2电脑上安装单机Hadoop(伪集群)

1. 引言 本教程旨在介绍在Mac 电脑上安装Hadoop 2. 前提条件 2.1 安装JDK Mac电脑上安装Hadoop&#xff0c;必须首先安装JDK&#xff0c;并配置环境变量&#xff08;此处不做详细描述&#xff09; 2.2 配置ssh环境 关闭防火墙 在Mac下配置ssh环境&#xff0c;防止后面启…

使用html和JavaScript实现一个简易的物业管理系统

码实现了一个简易的物业管理系统&#xff0c;主要使用了以下技术和功能&#xff1a; 1.主要技术 使用的技术&#xff1a; HTML: 用于构建网页的基本结构。包括表单、表格、按钮等元素。 CSS: 用于美化网页的外观和布局。设置字体、颜色、边距、对齐方式等样式。 JavaScript…

2000-2022年各省产业结构高级化、产业结构合理化指数(两种方法)(含原始数据+计算过程+计算结果)

2000-2022年各省产业结构高级化、产业结构合理化指数&#xff08;两种方法&#xff09;&#xff08;含原始数据计算过程计算结果&#xff09; 1、时间&#xff1a;2000-2022年 2、来源&#xff1a;统计年鉴、各省年鉴、人口和就业年鉴 3、指标&#xff1a;GDP、第一产业增加…

神经网络基础-初识神经网络

人工神经网络&#xff08; Artificial Neural Network&#xff0c; 简写为ANN&#xff09;也简称为神经网络&#xff08;NN&#xff09;&#xff0c;是一种模仿生物神经网络结构和功能的计算模型。人脑可以看做是一个生物神经网络&#xff0c;由众多的神经元连接而成。各个神经…