如果简单应用,选择软件I2C。如果对性能指标要求比较高 选择硬件I2C
有硬件电路自动反转引脚电平,软件只需要写入控制寄存器CR和数据寄存器DR 为了实时监控时序的状态,还要读取状态寄存器SR
写入控制寄存器CR,就相当于踩油门、打方向盘 控制汽车的运行
读取状态寄存器SR,就像是观看仪表盘
首先移位寄存器和数据寄存器DR的配合是通信的核心部分
因为I2C是高位先行,所以这个移位寄存器是向左移位,在发送的时候最高位先移出去,然后是次高位,移位8次,由高到低位,依次放到SDA线上
在接受的时候,数据通过GPIO口从右边依次移进来
最后GPIO口这里 使用硬件I2C的时候,这两个对应的GPIO口 都要配置成复用开漏输出的模式
复用就是GPIO的状态是交由片上外设来控制的
开漏输出这是I2C协议要求的端口配置
这里即使是开漏输出模式,GPIO口也是可以进行输入的
然后SCL这里,时钟控制器通过GPIO去控制时钟线
指定地址写
首先初始化之后,总线默认空闲状态,STM32默认是从模式
为了产生一个起始条件,STM32需要写入控制寄存器,在START位写1,STM32就自动产生起始条件
之后STM32由从模式转为主模式 就是多主机模型下,STM32有数据要发,就要跳出来
控制完硬件电路之后,就要检查标志位,来看看硬件有没有达到我们想要的状态
起始条件之后会发生EV5事件,可以把EV5当成标志位 这个手册这里都是用EV(Event)几这个事件来代替标志位的
因为有的状态会同时产生多个标志位,这个EV几事件是组合了多个标志位的一个大标志位
在库函数中也会有对应的,检查EV几事件是否发生的函数,可以当成一个大标志位来理解
当检测其实条件已发送时,就可以发送从机地址了,从机地址需要写到数据寄存器DR中
硬件电路就会自动把这一个字节转到移位寄存器里
再把这一个字节发送到I2C总线上
之后硬件会自动接收应答并判断,如果没有应答硬件会置应答失败的标志位
寻址完成之后,会发生EV6事件,之后是EV8_1事件
到了EV8事件,这时就是移位寄存器正在发送数据的状态,流程图上,数据1的时序就产生了
这个位置EV8事件没有了,对于EV8写入DR将清除该事件,所以在EV8事件末尾应该是写入了写一个数据
也就是后面的数据2
在这个时刻就被写入到寄存器里等着了
然后在数据1接收到应答之后,数据2就转入移位寄存器进行发送
EV8事件就又发生了
在第二个EV8事件末尾,数据2还正在移位发送
但此时下一个数据已经被写到数据寄存器等着了
所以EV8事件结束
一旦我们检测到EV8事件,就可以写入下一个数据了
最后当我们发送的数据写完之后
这时就没有新的数据可以写入到数据寄存器了
当移位寄存器当前的数据移位完成时,此时就是移位寄存器空数据寄存器也空的状态,就是后面的EV8_2事件
当检测到EV8_2时,就可以产生终止条件了,(控制寄存器CR1中STOP位进行控制停止
软件I2C和硬件I2C的区别,在通信的底层,就是之前写的MyI2C.c
把MyI2C模块移出工程
利用硬件I2C外设 来替换这些注释的代码,来实现相同的功能
配置I2C外设,对I2C外设进行初始化,来替换MyI2C_Init
控制外设电路,实现指定地址写的时序
控制外设电路,实现指定地址读的时序
开启I2C外设和对应GPIO口的时钟
把I2C外设对应的GPIO口初始化为复用开漏输出
使用结构体对整个I2C外设进行配置
I2C_Cmd使能I2C,这样初始化配置就完成了
I2C_GenerateSTART 生成起始条件 Start可以通过手册对寄存器描述来了解
I2C_GenerateSTOP 设置Stop位产生停止条件
I2C_AcknowledgeConfig 配置ACK这一位 手册里有相关描述 在收到一个字节后是否给从机应答
I2C_SendData 发送数据 实际就是把Data这个数据直接写到DR寄存器
I2C_ReceiveData 接收数据 读取DR
I2C_Send7bitAddress 发送地址 也可以使用I2C_SendData进行地址发送
在.h下面 库函数给了我们多种监控标志位的方案 Basic state monitoring: I2C_CheckEvent(同时判断一个或多个标志位,来确定EV几这个状态是否发生,和ppt流程是对应的)
Flag-based state monitoring: 标志位的状态监控 I2C_GetFlagStatus() 可以判断某一个标志位是否置1
对应着软件I2C的流程和ppt时序图
硬件I2C函数都不是阻塞式的 这些硬件I2C函数只管给寄存器的位置置1 或者只在DR写入函数,就结束,退出函数,不管波形是否发送完毕 所以对于这种非阻塞时的程序,在函数结束之后,我们都要等待对应的标志位,确保函数的操作执行到位
生成起始条件
等待EV5(也可以叫做主机模式已选择事件)事件的到来 使用状态监控函数 使用I2C_CheckEvent函数 等待SUCCESS
发送从机地址 接收应答 I2C_SendData 和 I2C_Send7bitAddress 都可以完成
接收应答 这里并不需要一个函数来操作 在这个库函数中发送数据都自带了接收应答的过程 同样 发送数据也自带了发送应答的过程
如果应答错误 硬件会通过标志位和中断来提示我们
所以发送地址之后不需要就收应答 直接等待事件
发送完地址之后 等待EV6事件
EV8_1事件是告诉你你该写入DR发送数据了,并不需要等待这个EV8_1事件,库函数参数列表也没有EV8_1事件的参数
直接写入DR发送数据 发送RegAddress 等待EV8事件
继续调用I2C_SendData发送一个字节的数据
发送完Data之后就需要终止了,所以最后这个等待事件有所不同
在连续数据进行发送时,需要等待EV8事件
而当我们发送完最后一个字节数据时,需要等待EV8_2事件
当BTF等于1,就是移位完成了,并且没有新的数据可以发的时候,置BTF也就是EV8_2
使用终止函数
在这个位置,要把应答位置0,同时把停止条件生成位STOP置1 ,
虽然这时候是应该接收数据,数据都没收到,就要产生停止条件?答案确实如此,这里规定就是在接收一个字节之前,就要提前把ACK置0,同时设置停止位STOP
因为我们目前是接收一个字节
所以在进入接收模式之后,就要立刻ACK置0,STOP置1
如果不提前在数据还么收到的时候给ACK置0,等时序到了接收第二个数据的时候,数据已经收到了,再说要置0,要给非应答,
,这时就晚了,数据收到之前应到位就已经发送出去了
这时再给ACK置0,只能实在下一个数据之后给非应答,所以在 最后一个数据之前,就要给ACK置0
在EV6事件之后,配置ACK位和停止位
之后再等待EV7事件,等待EV7事件之后,数据就已经到了DR寄存器里了
可以读取DR寄存器 存到Data变量里
最后把ACK置1,默认状态下就要把ACK置1,给从机应答
在接收数据之前 临时把ACK置0,给非应答
这个流程是为了方便指定地址收多个字节
文章浏览阅读1.6w次,点赞8次,收藏41次。生活中我们无时不刻不都要在网站搜索资源,但就是缺少一个趁手的资源搜索网站,如果有一个比较好的资源搜索网站可以帮助我们节省一大半时间!今天小编在这里为大家分享5款超厉害的资源搜索网站,每一款都可以让你的资源丰富精彩!网盘传奇一款最有效的网盘资源搜索网站你还在为找网站里面的资源而烦恼找不到什么合适的工具而烦恼吗?这款网站传奇网站汇聚了4853w个资源,并且它每一天都会持续更新资源;..._最全资源搜索引擎
文章浏览阅读4.5k次,点赞5次,收藏18次。阅读测试程序,设计一个Book类。函数接口定义:class Book{}该类有 四个私有属性 分别是 书籍名称、 价格、 作者、 出版年份,以及相应的set 与get方法;该类有一个含有四个参数的构造方法,这四个参数依次是 书籍名称、 价格、 作者、 出版年份 。裁判测试程序样例:import java.util.*;public class Main { public static void main(String[] args) { List <Book>_6-1 book类的设计java
文章浏览阅读613次,点赞28次,收藏27次。相比于以前的传统手工管理方式,智能化的管理方式可以大幅降低学校的运营人员成本,实现了校园导航的标准化、制度化、程序化的管理,有效地防止了校园导航的随意管理,提高了信息的处理速度和精确度,能够及时、准确地查询和修正建筑速看等信息。课题主要采用微信小程序、SpringBoot架构技术,前端以小程序页面呈现给学生,结合后台java语言使页面更加完善,后台使用MySQL数据库进行数据存储。微信小程序主要包括学生信息、校园简介、建筑速看、系统信息等功能,从而实现智能化的管理方式,提高工作效率。
传统上用户登陆状态会以 Session 的形式保存在服务器上,而 Session ID 则保存在前端的 Cookie 中;而使用 JWT 以后,用户的认证信息将会以 Token 的形式保存在前端,服务器不需要保存任何的用户状态,这也就是为什么 JWT 被称为无状态登陆的原因,无状态登陆最大的优势就是完美支持分布式部署,可以使用一个 Token 发送给不同的服务器,而所有的服务器都会返回同样的结果。有状态和无状态最大的区别就是服务端会不会保存客户端的信息。
文章浏览阅读784次。发表于10小时前| 2674次阅读| 来源TechCrunch| 19 条评论| 作者Jon EvansiOSAndroid应用开发产品编程语言JavaObjective-C摘要:即便Android市场份额已经超过80%,对于开发者来说,使用哪一个平台做开发仍然很难选择。本文从开发环境、配置、UX设计、语言、API、网络、分享、碎片化、发布等九个方面把Android和iOS_ios 开发角度
搜索引擎的发展历史可以追溯到20世纪90年代初,随着互联网的快速发展和信息量的急剧增加,人们开始感受到了获取和管理信息的挑战。这些阶段展示了搜索引擎在技术和商业模式上的不断演进,以满足用户对信息获取的不断增长的需求。
文章浏览阅读990次。对象特性是指控制对象的输出参数和输入参数之间的相互作用规律。放大系数K描述控制对象特性的静态特性参数。它的意义是:输出量的变化量和输入量的变化量之比。时间常数T当输入量发生变化后,所引起输出量变化的快慢。(动态参数) ..._控制对象特性
文章浏览阅读5.7w次,点赞50次,收藏276次。FRP搭建内网穿透1.概述:frp可以通过有公网IP的的服务器将内网的主机暴露给互联网,从而实现通过外网能直接访问到内网主机;frp有服务端和客户端,服务端需要装在有公网ip的服务器上,客户端装在内网主机上。2.简单的图解:3.准备工作:1.一个域名(www.test.xyz)2.一台有公网IP的服务器(阿里云、腾讯云等都行)3.一台内网主机4.下载frp,选择适合的版本下载解压如下:我这里服务器端和客户端都放在了/usr/local/frp/目录下4.执行命令# 服务器端给执_locyanfrp
文章浏览阅读687次。题目:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=93745#problem/A题意:给出r*c的01矩阵,可以翻转格子使得0表成1,1变成0,求出最小的步数使得每一行中1的个数相等,每一列中1的个数相等。思路:网络流。容量可以保证每一行和每一列的1的个数相等,费用可以算出最小步数。行向列建边,如果该格子是_uva12534
文章浏览阅读504次。1、Let's Encrypt 90天,支持泛域名2、Buypass:https://www.buypass.com/ssl/resources/go-ssl-technical-specification6个月,单域名3、AlwaysOnSLL:https://alwaysonssl.com/ 1年,单域名 可参考蜗牛(wn789)4、TrustAsia5、Alpha..._csdn alphassl免费申请
文章浏览阅读1.6k次。测试算法的性能 很多时候我们需要对算法的性能进行测试,最简单的方式是看算法在特定的数据集上的执行时间,简单的测试算法性能的函数实现见testSort()。【思想】:用clock_t计算某排序算法所需的时间,(endTime - startTime)/ CLOCKS_PER_SEC来表示执行了多少秒。【关于宏CLOCKS_PER_SEC】:以下摘自百度百科,“CLOCKS_PE_算法性能测试
文章浏览阅读1.2k次。fromhttps://towardsdatascience.com/finding-lane-lines-simple-pipeline-for-lane-detection-d02b62e7572bIdentifying lanes of the road is very common task that human driver performs. This is important ..._lanedetectionlite