STM32学习笔记

STM32

GPIO输出

  • 基本介绍在这里插入图片描述

    注:16个引脚,从PO到P15,用了低十六位,高十六位没有用。

  • 位结构在这里插入图片描述

    注:VDD开关上拉默认高电平,VSS开关下拉默认低电平,两者阻值较大,弱上拉,弱下拉。

    端口位设置/清除寄存器:高16位进行位清除,低十六位进行位设置。

    位设置寄存器:对某一位进行置一操作,在位设置寄存器的对应位写1即可,其它位写0,内部就会有电路,自动将输出数据寄存器对 应位置为1,而剩下写0的位则保持不变,保证只操作一位而不影响其它位。

    位清零寄存器:对某一位进行清零的操作,就在位清除寄存器的对应位写1即可。

    端口输出数据寄存器:用低十六位对应16个引脚,高十六位没有使用。

    输出控制在推挽模式下:输出数据寄存器为1时,上管(VDD)导通,下管断开,输出直接接到VDD,就是输出高电平。

    ​ 输出数据寄存器为0时,上管(VDD)断开,下管导通,输出直接接到VSS,就是输出低电平。

    输出控制在开漏模式下:P-MOS无效,只有N-MOS在工作,数据寄存器为1时,下管断开,这时输出相当于断开,也就是高阻模式

    ​ 数据寄存器为0时,下管导通,输出直接接到VSS,就是输出低电平。

    输出控制在关闭模式下:两个MOS均关闭,也就是输出关闭,端口的电平由外部信号来控制。

    推挽模式下高低电平均具有较强的驱动能力,开漏模式只有低电平具有驱动能力,常用来作为通信协议的驱动方式,多机通信情况下该模式可以避免各个设备的互相干扰,还可用于输出5V的电平信号。

    在这里插入图片描述

    注:施密特触发器保证了输入信号的稳定,避免抖动现象。高于上限了,那就一直为高电平,直到其低于下限,称为低电平,一直维持低电平,直到高于上限。

  • GPIO模式在这里插入图片描述

  • 浮空/上拉/下拉在这里插入图片描述

    注:输入时,下方输出断开。

  • 模拟输入在这里插入图片描述

    注:ADC专用模式,将模拟信号转换为计算机可操作的数字信号,触发器和输出端均断开。

  • 开漏/推挽输出在这里插入图片描述

    注:P-MOS如果无效就是开漏输出,都有效就是推挽输出。

GPIO输入

  • 传感器模块

    在这里插入图片描述

    注:C2滤波电容用来保证电路稳定

    杆子弹簧模型分析:弹簧在杆子上下拉扯,中间的输出端会往拉力强的方向偏移。阻值越小,拉力越强,当N1越来越小时,下拉作用越来越强,A0就趋向于GND,当N1阻值越来越大时,下拉作用越来越弱,A0变大,往上偏移。

    左边的三角是电压放大器,可以对电压进行二值化。

  • 硬件电路

    在这里插入图片描述

    注:一般采用下接方式。第一幅图,PA0是个I/O个,按键下压时,读取PA0电压为低电平,松手引脚为高电平。第二幅图外部接了一个上拉电阻,可以输出高电平更加稳定,但同样下拉时,损耗会大点。

    D0数字输出随便接一个端口,比如PA0,用于读取数字量。

    在这里插入图片描述

    在这里插入图片描述

    注意下面的用法。

OLED

  • OLED在这里插入图片描述

  • 硬件电路在这里插入图片描述

  • 功能函数在这里插入图片描述

EXTI中断

  • 中断系统在这里插入图片描述

  • 中断执行流程在这里插入图片描述

  • STM32在这里插入图片描述

  • NVIC在这里插入图片描述

    注:n代表的是有n条线(n个通道)接入到NVIC。

  • 优先级分组在这里插入图片描述

    注:抢占优先级可以中断嵌套,响应优先级可以优先排队。

  • EXIT外部中断在这里插入图片描述

    注:事件响应不会触发中断,而是触发别的外设操作,属于外设之间的联合工作

  • EXIT基本结构在这里插入图片描述

  • 对于引脚选择,依靠AFIO的作用在这里插入图片描述

  • EXTI框图在这里插入图片描述

    注:

    或门:执行或的逻辑,多个输入,一个输出,只要有一个输入为1,输出就为1,全为0,输出才是0;

    与门:执行与的逻辑,多个输入,一个输出,只有输入全部为1时输出才为1,否则全为0;

    非门:执行非的逻辑,一个输入,一个输出,输入1就输出0,输入0就输出1;

    当中断屏蔽寄存器输出0时,相当于屏蔽函数,0&任何数都是0,当其输出1时,1&x就是x。相当于一个开关。

TIM定时中断

  • 基本介绍在这里插入图片描述

  • 定时器类型在这里插入图片描述

    注:不同型号的32,所有的定时器不同。

    向上计数模式:从0向上自增,计数到重装值,清零并申请中断。基本定时器仅支持该模式。

    向下计数模式:从重装值开始,向下自减直到0,回到重装值同时申请中断。

    中央计数模式:从0开始,先向上自增到重装值,申请中断;再向下自减,减到0,申请中断;继续下一轮,依次循环。

  • 通用定时器框图在这里插入图片描述

    注:上面主要为内外时钟源的选择,和定时中断。下面是输入捕获和比较输出电路,共用相同的引脚。

    预分频器写0就是不分频(1分频),写1就是2分频,输出=输入/2,实际分频系数=预分频器的值+1。

  • 通用计时器简图在这里插入图片描述

    注:简化版,主要说外部时钟选择和定时器中断这两块。

    中断输出控制(TIM_ITConfig):允许或者禁止申请的中断。

    运行控制(void TIM_Cmd):使能计数器可以运行,失能计数器停止运行

  • 预分频器时序在这里插入图片描述

    注:第一行预分频器的内部时钟72MHz,第二行是计数器使能,高电平计数器正常运行,低电平计数器停止。

    从图中可看出,重装值为FC,更新计数器清零。预分频控制寄存器改变频率,频率改变并不是立刻生效,而是有一个缓冲器,直到下次计数开始才生效。

  • 计数器时序在这里插入图片描述

    注:分频因子为2。第一行预分频器的内部时钟72MHz,第二行是计数器使能,高电平计数器正常运行,低电平计数器停止。为了防止出错,加入一个影子寄存器(不会立即生效,更新事件后才会生效,缓冲)。计算式为1就是一秒。

  • 带预装时序的计数器在这里插入图片描述

输出比较

  • 输出比较简介在这里插入图片描述

    注:IC:全称是Input Capture,意为输入捕获

    CC:全称是Capture/Compare,输入捕获和输出比较的单元

  • PWM简介在这里插入图片描述

    注:占空比越大,等效的模拟电压就趋近于高电平;占空比越小,那等效的模拟电压就越趋近于低电平,线性关系。比如高电平5v,低电平0v,50%占空比就是(中间电压)2.5v,20%占空比(1/5处电压)就是1v。

  • 输出比较通道在这里插入图片描述

    注:oc1ref:参考信号

    CC1P:极性选择,前面有一个非门进行取反,输出信号是输入信号高低电平反转的信号。

  • 输出模式控制器中的比较模式在这里插入图片描述

    注:冻结:可以暂停输出,高低电平保持原状态

    置有效电平:高电平;置无效电平:低电平。

  • PWM基本结构在这里插入图片描述

    注:不用中断,ARR不管。配置好时基单元,CNT开始不断自增运行,CCR自己设定,不断进行比较,执行PWM1模式逻辑

    蓝色线是CNT的值,黄色线是ARR的值,红色线是CCR(自己设定的值),绿色线是输出。可以看到,CCR设置的高,占空比大,CRR设置的低,占空比小。REF就是频率可调,占空比也可调的PWM波形,最终经过极性选择,输出使能,最终通向GPIO口。

  • PWM的参数计算在这里插入图片描述

    注:CCR的变化范围取决于ARR的值,正比,对应的分辨率就越大,。这里的分辨率是指占空比最小的变化步距,这个值越小越好。占空比变化的越细腻越好。频率=1/周期(s),单位Hz

输入捕获Failed to fetch

  • 输入捕获简介在这里插入图片描述

    注:基本定时器没有输入捕获

  • 频率测量在这里插入图片描述

    注:当待测信号频率小于中界频率时,测周法更合适,误差更小;反之,选用测频法。

  • 输入捕获通道详图在这里插入图片描述

  • 主从触发模式(自己起的名字)在这里插入图片描述

    注:其中主模式可以将定时器内部的信号,映射到TRGO引脚用于触发别的外设;从模式就是接受其他外设,或者自身外设的的一些信号用于控制自身定时器的运行,也就是被别的信号控制;触发源选择就是选择从模式的触发信号源,选择指定的一个信号,得到TRGI,TRGI去触发从模式,从模式选择一项操作来执行。三者都有对应的库函数代码调用。TI3和TI4需要手动中断清零CNT。

  • 输入捕获基本结构在这里插入图片描述

    注:该图只使用了一个通道,目前只能测量频率。配置时基单元,启动定时器,CNT在预分频之后的时钟驱动下不断自增,这个CNT,就是我们测周法用来计数计时的东西。经过预分频之后这个位置的时钟频率,就是驱动CNT的标准频率fc,标准频率=72M/预分频系数。输入捕获通道1的GPIO口,输入左上所示的方波型号,经过滤波器和极性选择,TI1FP1为上升沿触发,之后输入选择直连通道,分频器选择不分频,当TI1FP1出现上升沿,CNT的当前计数值转运到CCR1里,同时触发源选择,选中TI1FP1为触发信号,从模式选择复位操作,清零CNT。先记录,再清0。

  • PWMI基本结构在这里插入图片描述

    相对于输入捕获基本结构,多了TIFP2这一块内容,可以计算出占空比。左上角的波形图,CCR2记录的是高电平时CNT的值,CCR1记录的是整个周期的CNT值。两者比值既是占空比。

TIM编码器接口

  • 编码器简介在这里插入图片描述

  • 旋转编码器在这里插入图片描述

  • 正交编码器在这里插入图片描述

    注:利用表格状态确定正反转。

  • 通用定时器的编码器接口在这里插入图片描述

    注:用通道CH1和CH2,3,4不用;是否交叉,预分频器,CCR寄存器,与编码器接口无关;编码器输出,不需要用到内部时钟和时基单元初始化时设置的计数方向,因为此时计数时钟和计数方向都处于编码器接口托管的状态,计数器的自增和自减,受编码器控制。

  • 编码器接口的基本结构在这里插入图片描述

    注:GPIO口分别接AB相,编码器接口,通过预分频器控制计数器增减,同时还根据编码器的旋转方向,控制CNT的计数方向,ARR设置为最大数65535。

    1. RCC开启时钟,开启GPIO和定时器的时钟
    2. 配置GPIO,把PA6和PA7配置成输入模式
    3. 配置时基单元,预分频器不分频吗,自动重装给最大,只需要给CNT执行计数就可
    4. 配置输入捕获单元,这边只用到滤波器和极性选择
    5. 配置编码器接口模式,直接调用库函数
    6. 调用TIM_Cmd ,启动定时器
  • 编码器接口的三种模式在这里插入图片描述

  • 实例1(均不反向)在这里插入图片描述

    注:技术来回摆动,过滤噪声。

  • 实例2(A反向,B不反向)在这里插入图片描述

    注:不是通过边沿检测反转,而是通过极性选择,选择上升沿参数,高低电平不反转,选择下降沿参数,高低电平反转,信号通过非门,高低电平极性反转来进行。

    先把反向后的向,高低电平进行取反,这才是返相后实际给编码器接口的电平,然后再查表。

ADC数模转换器

  • ADC简介在这里插入图片描述

  • 逐次逼近型ADC在这里插入图片描述

    注:外部待测电压(外部通道输入,未知编码的电压)和DAC电压(已知编码的电压)同时输入到电压比较器,进行大小判断,如果DAC输出电压比较大,就调小DAC;如果DAC输出电压小,就调大DAC,直到DAC输出的电压和外部通道输入的电压近似相等。这样DAC输入的数据就是外部电压的编码数据了。采用二分法进行,相当于对二进制从高位到低位依次判断是0还是1。

    EOC:转换结束信号

  • ADC基本结构在这里插入图片描述

    注:规则组依次只能一个结果,注入可以4个

    代码思路:

    1. 开启RCC时钟,包括ADC和GPIO时钟,ADCCLK分频器也需要配置
    2. 配置GPIO,模拟输入模式
    3. 配置多路开关,把左边的通道接入到右边规则组(点菜)
    4. 配置ADC转换器:转换方式,几个通道,触发源,数据对齐(一大堆参数用结构体配置即可)
    5. 开关控制,调用ADC_Cmd,开启ADC
  • ADC输入通道在这里插入图片描述

    注:该芯片没有ADC3,PC0-PC5没有。

  • ADC转换模式

    1. 单次转换,非扫描模式在这里插入图片描述

      注:需手动进行转换,每触发一次,转换结束后就会停下来,想要进行下一次再次手动触发。

    2. 连续转换,非扫描模式在这里插入图片描述

      注:只需触发一次,无需手动转换,无需判断是否结束,想要读AD值的时候,直接从数据寄存器取就是了。

    3. 单次转化,扫描模式在这里插入图片描述

      注:可以指定通道数目,比如7就只看7个序列,可以进行点菜,通道顺序随意安排,可以重复。因为规则组一次只能存一个数据,为了防止数据被覆盖,就需要用DMA(数据转运)及时将数据挪走存储。7个通道完成后,产生EOC信号,转换结束,然后再手动触发下一次,就又开始新一轮的转换。

    4. 连续转换,扫描模式在这里插入图片描述

      注:在上一个模式上,进行自动触发,无需手动操作

  • 触发控制在这里插入图片描述

    注:最右边是寄存器,可以通过寄存器设置地址完成,也可以通过库函数来完成。

  • 数据对齐在这里插入图片描述

    注:ADC是12位的,数据寄存器是16位的。一般用右对齐,左对齐相当于左移了4位,乘了16。如果不需要这么高的分辨率,可以选择左对齐,截取高8位数据,舍弃后面四位的精度,12位的ADC就退化成了8位的ADC。

  • 转换时间在这里插入图片描述

    注:12.5个周期,因为有12位,至少需要12个周期。

  • ADC内置校准在这里插入图片描述

  • 硬件电路在这里插入图片描述

DMA直接存储器读取

  • DMA简介在这里插入图片描述

    注:存储器到存储器的数据转运,一般使用软件出发;外设到存储器的转运(本质也是存储器到存储器),一般用硬件触发。特定指的是每个DMA通道,它的硬件触发源是不一样的。

  • 存储器映像在这里插入图片描述

    注:电脑由运算器、控制器、存储器、输入设备、和输出设备,其中运算器和控制器,一般会合在一起,叫做CPU。计算机核心关键部分是CPU和存储器。存储器又有两个重要知识点,一个是存储器内容,另一个是存储器的内容。图中外设寄存器也是存储器。寄存器是一种特殊的存储器,一方面CPU可以对寄存器进行读写,就像读写运行内存一样,另一方面,寄存器的每一位背后,都连接了一根导线,这些导线可以用于控制外设电路的状态,比如置引脚的高低电平、导通和断开开关、切换数据选择器或者多位组合起来,当作计数器、数据寄存器等。所以寄存器是连接软件和硬件的桥梁,软件读写寄存器,就相当于在控制硬件的执行,外设就是寄存器,寄存器就是存储器。

    Flash:常量数据也是存储在Flash。

  • DMA框图在这里插入图片描述

    注:图中的Flash,是ROM的一种,如果通过总线直接访问,无论是CPU还是DMA,都是只读的,不能写入。DMA目的地址不能填Flash地址,不然转运时会出错。

    仲裁器:用于调度各个通道,决定优先级,防止发生冲突。

    AHB从设备:用于配置DMA参数。

    DMA请求:用于硬件触发DMA的数据转运。

  • DMA基本结构在这里插入图片描述

    注:外设寄存器当中填写flash或者sram的地址。

    传输寄存器:用来指定,总共需要转运几次,自减计数器。减到0后不再执行,外设自增的地址也会恢复到起始地址的位置。

    自动重装器:决定转运模式,不重装,单次模式;重装,循环模式。如果需要再次执行,那就重置计数器为初始值,不执行,转运清零后,DMA结束。

    M2M:memory to memory,存储器到存储器。数据选择器的控制位,给位1,DMA就会选择软件触发,这个软件触发并不是调用某个函数一次,触发一次。它这个软件触发的执行逻辑是,以最快的速度,连续不断地触发DMA,争取早日把传输计数器清零,完成这一轮的转换。软件触发和循环模式不能同时用,会冲突,软件触发想清零,循环模式会重装,停不下来。

    开关控制:EN位,EN=0时不工作,EN=1时工作,DMA_Cmd函数,给DMA使能后,DMA就准备就绪,可以进行转运了,但有几个条件需满足,首先开关控制,必须使能;第二传输计数器必须大于0;第三触发源得有触发信号。当DMA开始运行,传输计数器自减到0后,如果没有自动重装,必须先关闭DMA_Cmd,再给计数器次数,重新开始。

    代码步骤:

    1. RCC开启DMA时钟
    2. 调用DMA_Init,初始化各个参数
    3. 进行开关控制
  • 数据宽度与对齐在这里插入图片描述

    注:当源端宽度小于目标宽度,高位补零;当源端宽度大于目标宽度时,多出来的高位舍弃。

  • 例子

    • 数据转运在这里插入图片描述

    • ADC配合DMA在这里插入图片描述

      注:如果EOC使用扫描模式,DMA也要相应的用自动重装。ADC把数据一个个传到DMA外设地址,DMA在一个个转运到DMA存储器地址当中。因为要保证时间的同步,因此选择ADC硬件触发。

USART串口协议

  • 通信接口介绍在这里插入图片描述

  • 串口通信在这里插入图片描述

  • 硬件电路在这里插入图片描述

    注:双方设备有独立电源,可不接VCC。TX发送端,RX接收端,交叉连接。STM32是3.3V的器件,如果线路(TX)对地是3.3V,就代表发送了逻辑1。如果线路对地是0V,就代表发送了逻辑0。

    异步时序:省一根时钟线,节省资源,缺点是对时间要求严格,对硬件电路的依赖比较严重。该电路是异步通信,需要双方规定严格的时钟标准。

    同步时序:对时间要求不严格,对硬件电路不怎么依赖,在一些低端单片机,没有硬件资源的情况下,也很容易使用软件来模拟时序,缺点是多一根时钟线。

  • 电平标准在这里插入图片描述

    注:RS485电平标准,通信距离可以达到上千米,而上面这两种电平,最远只能达到几十米,再远就传不了了。TTL电平看所接设备是3.3V还是5V。

  • 串口参数及时序在这里插入图片描述

    注:波特率单位bps(比特每秒),数据位9位,最后一位为校验位。

  • 串口时序例子在这里插入图片描述

    注:TX引脚输出定时翻转的高低电平,RX引脚定时读取引脚的高低电平,每个字节的数据加上起始位、停止位、可选的校验位,打包为数据帧。

USART简介

  • 简介在这里插入图片描述

    注:USART的时钟只支持输出,不支持输入,同步模式更多是为了兼容别的协议或者特殊用途而设计,不支持两个USART之间进行同步通信,主要学习异步通信。

    波特率发生器:用来配置波特率,相当于分频器。数据位长度,停止位长度,可选校验位,都可用库函数配置。

    同步模式:多了个时钟CLK的输出。

    硬件流控制:可以防止因为B处理慢而导致数据丢失的问题。比如A设备有个TX向B设备的RX发送数据,A设备一直在发,发的太快了,B处理不过来,如果没有硬件流控制,那B就只能抛弃新数据或者覆盖旧数据,如果有硬件流控制,在硬件电路上,会多出一根线,如果B没准备好接收,就置高电平,如果准备好了,就置低电平,A接收到了B反馈的准备信号,就只会在B准备好的时候,才发数据。

  • USART基本结构在这里插入图片描述

    注:时钟来源PCLK2或1,经波特率发生器分频后,产生的时钟通向发送和接受控制器,发送和接受控制器用来控制发送移位和接收移位,然后由发送数据寄存器和发送移位寄存器这两个寄存器的配合,将数据一位一位地移出去,通过GPIO口的复用输出,输出到TX引脚,产生串口协议规定的波形,右移符号表示往右移,低位先行。当数据由数据寄存器转移到移位寄存器时,会置一个TXE的标志位,我们判断这个标志位,就可以知道是不是可以写下一个数据了;RX引脚波形,通过GPIO输入,在接受控制器的控制下,一位一位地移入接收移位寄存器,左边开始移进来,低位先行,移完一帧后,数据就会统一转运到接收数据寄存器,在转移的同时,置一个RXNE标志位,检查这个标志位,就可以知道是不是收到数据了,同时这个标志位也可以申请中断,在收到数据时,直接进入中断函数,快速读取和保存数据。实际上有四个寄存器,但是在软件层面只有一个DR寄存器可以供我们读写。写入DR走上面,读取DR走下面。

    代码步骤:

    1. 开启USART时钟和GPIO时钟
    2. GPIO初始化,把TX配置成复用输出,RX配置成输入
    3. 配置USART,直接使用一个结构体
  • 细节讨论

    • USART数据帧在这里插入图片描述

      注:选择9位字长,那就8位数据,一位校验位;选择8位字长,那就8位数据,无校验位。

    • 数据帧中停止位选择在这里插入图片描述

    • 起始位侦测在这里插入图片描述

      输出TX要比输入RX简单,输出定时翻转TX引脚高低电平即可,输入不仅要保证采样频率和波特率一致还要保证每次输入采样的位置,要正好处于每一位的正中间。三位当中至少有两个0才有效,如果两个0一个1,表明出现噪声,状态寄存器会置一个NE(Noise Error),噪声标志位。如果1个0,两个0,那就不算检测到了起始位,可能前面下降沿时噪声导致,忽略前面数据,重新开始捕捉下降沿。通过起始位侦测,那接受状态就由空闲,变为接收起始位。

    • 数据采样在这里插入图片描述

      注:1-16一个数据位地长度,有16个采样时钟,起始位侦测已经对齐了采样时钟,所以这里直接在第8、9、10次采样数据位,为了保证数据地可靠性,这里连续采样三次,按照2:1地规则采样,非理想情况(2个1,1个0,即有噪声)噪声标志位NE置1.

    • 波特率发生器在这里插入图片描述

      注:15-4整数部分,3-0小数部分。不同系统设备之间需要共地才能比较。

    • 数据接收模式在这里插入图片描述

数据包

  • HEX数据包在这里插入图片描述

    注:如果载荷出现会出现包头包尾重复的情况,最好选择固定包长,可以避免接受错误;载荷不会和包头包尾重复,选择可变包长。发送double,结构体等都没问题,内部都由结构体构成,只需用一个uint8_t的指针指向它,把它们当作字节数组发送即可。

  • 文本数据包在这里插入图片描述

    注:每个字节经过了一层编码和译码,最终表现出文本格式,但实际上每个文本字符背后,都是一个字节的HEX数据。

  • HEX数据包接收在这里插入图片描述

    • 状态机在这里插入图片描述

      1. 现根据项目要求定义状态,画几个圈
      2. 然后考虑好各个状态在什么情况下进行转移,如何转移,画好线和转移条件
      3. 最后根据图来进行编程
  • 文本数据包接收在这里插入图片描述

I2C通信协议

  • 简介在这里插入图片描述

    注:SCL:串行时钟线;SDA:串行数据线;一根数据线,实现半双工。每个从机设备都有一个唯一的地址。

    一主多从:单片机作为主机,主导I2C总线的运行,挂载在I2C总线的所有外部模块都是从机,从机只有被主机点名之后才能控制I2C总线,不能在未经允许的情况下去碰I2C总线,防止冲突。

    多主多从:总线上任何一个模块都可以跳出来指挥做主机,但是同一个时间只能有一个人指挥,造成总线冲突时,I2C协议会进行冲裁,仲裁胜利方取得控制权,失败方变为从机。

  • 硬件电路在这里插入图片描述

    注:开漏加上拉输出模式有以下好处:

    1. 完全杜绝了电源短路现象,保证电路的安全,无论怎么拉杆子或者放手,杆子都不会处于一个被同时强拉和强推的状态,即使有多个人同时往下拉杆子。
    2. 避免了引脚模式的频繁切换,开漏加弱上拉,同时兼具了输入和输出的功能。想输出,就去拉杆子或放手,操作杆子变化即可;想输入,就直接放手,然后观察杆子高低就行,因为开漏模式下,输出高电平就相当于断开引脚,所以在输入之前,可以直接输出高电平。释放SDA就相当于切换成输入模式,所有设备包括主机都始终处于输入模式,当主机需要发送时,就可以主动去拉低SDA,而主机在被动接收的时候,就必须先释放SDA。
    3. 这个模式会有一个“线与”现象,就是只要有任意一个或多个设备输出了低电平,总线就处于低电平,只有所有的设备都输出高电平,总线才处于高电平。I2C可以利用这个特征执行多主机模式下的时钟同步和总线仲裁。
  • 时序基本单元

    • 起始/终止条件在这里插入图片描述

      注:拽下SCL时钟线是为了保证:一方面占用这个总线;另一方面也是为了方便我们这些基本单元的拼接,保证除了起始和终止条件,每个时序单元的SCL都是以低电平开始,低电平结束,这样这些单元拼接起来,SCL才能续的上。

    • 发送一个字节在这里插入图片描述

      注:低电平主机放数据,高电平从机读数据。主机拉低SCL,把数据放在SDA上,主机松开SCL,从机读取SDA数据(高位先行)。如果主机一个字节发送一半,突然进中断了,不操作SCL和SDA了,时序就会在中断的位置不断拉长,SCL和SDA电平都暂停变化,传输也完全暂停,等中断结束后,主机回来继续操作。传输仍然不会出问题,这就是同步时序的好处。发送一个字节时SCL和SDA全程都由主机掌控,从机只能被动读取。

    • 接受一个字节在这里插入图片描述

      注:低电平从机放数据,高电平主机读数据。实线代表主机控制,虚线代表从机控制,SDA主机在接受前要释放,交由从机控制。

    • 应答机制在这里插入图片描述

  • 拼接时序

    注:每个从机设备都有一个唯一的地址(相同型号芯片地址一样,不同型号一般都不同,如果有相同芯片挂载同一条总线上,改变地址中的可变部分),主机在起始条件之后,要先发送一个字节叫一下从机名字,所有从机都会第一个字节,和自己名字进行比较。如果不一样,后面的时序就不用管了。

    • 指定地址写在这里插入图片描述

      在这里插入图片描述

    • 当前地址读在这里插入图片描述

    • 指定地址读在这里插入图片描述

      在这里插入图片描述

      注:也称为复合时序,先起始,再重复起始,再停止。前面是寻址,后面才是读数据。注意想要继续读取数据,给应答,如果只想读取一个字节,要给非应答,否则,从机会继续发,这个时候想停止,SDA已经被从机往下拉了,不能正常弹回高电平。从机控制SDA发送一个字节的权利,开始于读写标志位为1,结束于主机给应答为1。

MPU6050

  • 简介在这里插入图片描述

    注:加速度计,静态稳定,动态不稳定。陀螺仪动态稳定,静态不稳定。

  • 参数在这里插入图片描述

    注:0xD0是左移一位后的从机地址,0x68是7位直接转换成了十六进制。总之在进行读写操作前,左移后在或上读写位即可。

  • MU6050硬件电路在这里插入图片描述

    注:XCL和XDA通常就是用于外接磁力计或者气压计,接上后,MPU6050主机接口可以直接访问这些扩展芯片的数据,把这些扩展芯片的数据读取到MPU6050里面,在MPU6050里面会有DMP单元,进行数据融合和姿态解算。如果不需要MPU6050的解算功能,可以把磁力计或者气压计直接挂载在SCL和SDA这条总线上。

  • MPU6050框图在这里插入图片描述

    注:上面一部分是从机I2C接口和SPI通信接口用于和STM32通信,下面是MPU6050主机的I2C通信接口,用于和MPU6050扩展的设备进行通信。MUX是一个接口旁路选择器,就是一个开关拨到上面辅助的(MPU6050)I2C引脚就和正常的I2C引脚接到一起,两路总线合并。STM32控制所有设备。拨到下面,就由其自身控制。

I2C通信外设

  • 外设简介在这里插入图片描述

    注:多主机模型分为固定主机,可变多主机,对于STM32的I2C而言它使用的是可变多主机模型。硬件I2C引脚固定,不像软件那么方便,具体看引脚定义图。标准速度,占空比参数没用,低电平:高电平=1:1。

  • I2C框图在这里插入图片描述

    注:把地址写入自身地址寄存器(可以写两个,双地址),当STM32作为从机被外部设备召唤时,收到的寻址通过比较器判断,和自身地址相同,响应召唤,并且STM32支持同时响应两个从机地址。PEC是进行CRC帧检验,数据帧错误,硬件就会置校验错误标志位,告诉你数据错误,使用需谨慎。

  • I2C基本结构在这里插入图片描述

    注:移位寄存器和数据寄存器DR的配合,是通信的核心部分,数据先写入DR,移位寄存器空时,转到移位寄存器进行发送。高位先行,移位寄存器左移,一个SCL时钟,移位一次,移位8次,这样就可以把一个字节从高位到低位,依次放到SDA线上了。在硬件输出模式下,两个GPIO口都要配置成复用开漏输出模式。复用就是GPIO口状态是交由片上外设来控制的,开漏输出,这是I2C协议要求的端口配置,上节说过,这里即使是开漏输出模式GPIO口也是可以进行输入的。时钟控制器通过GPIO控制时钟线(简化为一主多从模型),如果是多主机模型,始终也可以输入。

    输出数据,通过GPIO,输出到端口;输入数据,也是通过GPIO,输入到移位寄存器。I/0口改成I/0引脚。

    替换代码步骤:

    1. 配置I2C外设,对I2C2外设进行初始化
    2. 控制外设电路,实现指定地址写的时序
    3. 控制外设电路,实现指定地址读的时序

    写代码步骤:

    1. 开启I2C外设和对应GPIO口的时钟
    2. 把I2C外设对应的GPIO初始化为复用开漏模式(开漏是I2C协议要求,复用是需要交给外设(硬件)控制,软件控制,选通用即可)
    3. 第三步使用结构体,对整个I2C进行配置
    4. I2C_Cmd,使能I2C
  • 主机发送在这里插入图片描述

    注:EV几代表一个大的标志位(可能不止一个),CR控制寄存器,DR数据寄存器,SR状态寄存器。

  • 主机接受在这里插入图片描述

    注:写入CR的Start位,等待EV5事件(起始条件已发送)。寻址接收应答,结束后产生EV6事件(寻址已完成)。数据1这一块代表数据正在通过移位寄存器进行输入,EV6_1,可以看到,数据1其实还正在移位。还没收到,所以这个事件就没有标志位。通过配置CR控制应答。当这个时序单元结束后就说明移位寄存器就已经成功移入一个字节的数据1了。这时移入的一个字节就整体转移到数据寄存器,同时置RxNE标志位,表示数据寄存器非空,也就是收到了一个字节的数据,这个状态就是EV7事件。当然数据1还没读走的时候数据2就可以直接移入移位寄存器了,之后数据2移位完成,收到数据2,产生EV7事件,读走数据2,EV7事件没有了。最后不需要在接受数据时,提前把应答位控制寄存器ACK置0,并且设置终止条件请求,这就是EV7_1事件。

  • 软/硬件波形对比

    • 在这里插入图片描述

      注:SCL低电平数据变化,高电平数据读取,低电平时间要长点,不然来不及变化,尤其是高通讯速度时。

    • 在这里插入图片描述

      注:看出软件波形有少许波动,不是非常稳定,但因为同步时序,可以容忍不标准的波形,因此不影响通信。

SPI通信协议

  • 相比于I2C的优缺点

    • 速度快,最大可达,80MHz,I2C最快400KHz
    • 设计比较简单粗暴,实现功能没有I2C多
    • SPI硬件开销比较大,通信线的个数比较多,通信过程中,经常会有资源浪费的现象
  • 简介在这里插入图片描述

    注:SCK(SCLK,CLK,CK):串行时钟线 MOSI(DO->Data Output):主机输出从机输入 MISO(DI->Data Input):主机输入从机输出 SS(NSS->Not Slave Select、CS->Chip Select):从机选择

  • 硬件电路在这里插入图片描述

    注:想和哪个从机通信,就把对应通信线置低电平。同一时间,只能选一个从机通信。当SS位低电平时,MISO才允许变为推挽输出,为了避免从机同时输出造成高电平冲突。

  • 移位示意图(核心)在这里插入图片描述

    注:SPI通信的基础是交换一个字节,有了交换一个字节,就可以实现发送一个字节,接受一个字节,和发送同时接收一个字节,这三种功能,可以看出SPI在只执行发送或只执行接收的时候会存在一些资源浪费的现象。

  • 时序基本单元在这里插入图片描述

  • 交换一个字节(模式1)在这里插入图片描述

    注:MISO中间线表示高阻态,在SS为高电平时,从机输出要置为高阻态。SCK第一个上升沿主机和从机同时移出最高位,然后时钟运行,产生下降沿,此时主机和从机同时移入数据,也就是进行数据采样,这里主机移出的B7,进入从机移位寄存器的最低位,从机移出的B7进入主机移位寄存器的最低位,一个时钟脉冲产生完毕,一个数据位传输完毕。重复8次,主机和从机完成一个字节的数据交换。如果主机只想交换一个字节,这时就可以置SS为高电平,结束通信。

  • 交换一个字节(模式0)在这里插入图片描述

    注:与模式1的区别在于,数据移出移入的时机,会提前半个时钟,也就是相位提前了。SCK在第一个边沿之前(SS开始下降沿时),就要提前开始移出数据了。下降沿是触发数据移出的前提条件,对于硬件SPI来说,由于使用了硬件的移位寄存器电路。所以这两个动作几乎是同时发生的,而对于软件SPI来说,由于程序是一条条执行的,我们不可能完成两个动作,因此看成先后执行的逻辑,先SS下降沿,再移出数据,再SCK上升沿,再移入数据,SCK下降沿移出数据。

  • 交换一个字节(模式2)在这里插入图片描述

    注:把模式0的SCK电平翻转

  • 交换一个字节(模式3)在这里插入图片描述

    注:把模式1的SCK电平翻转,CHPA表示的是时钟相位决定是第一个时钟采样移入还是第二个时钟采样移入并不是规定上升沿采样还是下降沿采样的,当然在CPOL确定的情况下CPHA确实会改变采样时刻的上升沿和下降沿。

  • 发送指令在这里插入图片描述

  • 指定地址写在这里插入图片描述

  • 指定地址读在这里插入图片描述

    注:首先发送读指令,然后发送指定地址24位,分三个字节发送,高位先行,最后开始读取数据,主机随便发送一个指令FF,读取从机数据一个字节,继续读取,从机内部地址指针自动加1,从机就会继续把指定地址下一个位置的数据发过来。

硬件SPI通信外设

  • 基本介绍在这里插入图片描述

    注:SPI1是APB2的外设,SPI2是APB1的外设,开启时钟及计算时钟频率时需要注意。APB2的PCLK时72MHz,APB1的PCLK是36MHz。时钟频率=PCLK/分频系数。

  • 硬件SPI框图在这里插入图片描述

    注:发送数据先写入TDR,再转到移位寄存器发送,发送的同时,接收数据,接收到的数据转到RDR,我们再从RDR读取数据,数据寄存器和移位寄存器配合,可以实现无延迟的连续传输。NSS引脚实现多主机,了解即可,主要应用还是一主多从。

  • SPI硬件基本结构在这里插入图片描述

    注:TDR数据,整体转入移位寄存器的时刻,置TXE标志位;移位寄存器数据,整体转入RDR的时刻,置RXNE标志位。波特率发生器,产生时钟,输出到SCK引脚,数据控制器,看成是一个管理员,控制着所有电路的运行。开关控制SPI_CMD,初始化后,给个enable,使能整个外设。一主多从时,GPIO模拟的SS是最佳的选择。

    配置步骤:

    1. 开启时钟,开启SPI和GPIO的时钟
    2. 初始化GPIO口,其中SCK和MOSI是由硬件外设控制的输出信号所以配置为复用推挽输出,MISO是硬件外设的输入信号,配置为上拉输入,SS是软件控制的输出信号,配置为通用推挽输出
    3. 配置SPI外设,使用结构体,调用SPI_Init
    4. 开关控制,调用SPI_Cmd,给SPI使能即可
  • 非连续传输在这里插入图片描述

W25Q64简介

  • 简介在这里插入图片描述

    注:W25Q256分为3字节模式和四字节模式,在3字节模式下24位地址对于32MB来说寻址不够,只能寻到前16MB,需进入4字节模式。

  • 结构框图在这里插入图片描述

    注:发送三个字节,前两个字节,会进到这个页地址锁存计数器里,最后一个字节,会进到字节地址锁存计数器里。然后页地址,通过这个写保护和行解码来选择我要操作那一页,字节地址,通过这个列解码和256字节页缓存来进行指定字节的读写操作,那又因为我们这个地址锁存,都是有一个计数器的,所以这个地址指针,在读写之后,可以自增,这样就很容易实现从指定地址开始读写多个字节的目的了。

    256字节页缓存区:其实是一个256字节的RAM存储器,数据读写是通过RAM缓存区来进行的,写入数据会先放到缓存区里,然后在时序结束后,芯片再将缓存区的数据复制到对应的Flash里,进行永久保存,为啥要弄一个缓存区呢,直接往Flah里写不好吗?那是因为,SPI写入频率非常高,Flash写入由于需要掉电不丢失,留下刻苦铭心的印象,它就比较慢,所以这个芯片的设计思路就是,你写入的数据,我先放在页缓存区里存着,因为缓存区是RAM,所以它的速度非常快,可以跟的上SPI总线速度。但因为缓存区只有256个字节,写入有限制条件。就是写入的一个时序,连续写入的数据量,不能超过256字节(超过回到页首覆盖)。然后等你写完了,我芯片再慢慢把数据从缓存区转移到Flash存储器,那我数据从缓存区转到Flash里,需要一定时间,所以在写入时序结束后,芯片会进入一段忙的状态。给状态寄存器的BUSY位置1。在忙的时候,芯片就不会响应新的读写时序了。读取数据就快了,虽然也是通过缓存区来读取,但是由于读取,只是看一下电路的状态就行了,基本不花时间,所以读取的限制就很少了,速度也非常快。

    整个结构:

    1. 第一个是这整个Flash的空间划分,会划分为块,扇区和页。
    2. 第二个是SPI控制逻辑,它就是整个芯片的管理员,执行指令、读写数据都靠它。
    3. 第三个是这个状态寄存器,他和忙状态、写使能、写保护等功能相关
    4. 256字节的页缓存,它会对一次性写入的数据量,产生限制
  • Flash操作注意事项在这里插入图片描述

    注:在Flash中,FF代表空白,而不是00;Flash的擦除,有最小擦除的单元限制,不能指定某一个字节去擦除,要擦就得一大片一起擦,可以选择按块擦除,或者按扇区擦除,再小就没了。所以最小擦除单元,就是一个扇区。

    页缓存区和Flash的页是对应的,你必须得从页起始位置开始,才能最大写入256字节。如果从页中间的地址开始写,那写道页尾时,这个地址就会跳回到页首,这会导致地址错乱所以,我们在进行多字节写入时,一定要注意,这个地址范围,不能跨越页的边沿。

在忙的时候,芯片就不会响应新的读写时序了。读取数据就快了,虽然也是通过缓存区来读取,但是由于读取,只是看一下电路的状态就行了,基本不花时间,所以读取的限制就很少了,速度也非常快。

整个结构:

  1. 第一个是这整个Flash的空间划分,会划分为块,扇区和页。
  2. 第二个是SPI控制逻辑,它就是整个芯片的管理员,执行指令、读写数据都靠它。
  3. 第三个是这个状态寄存器,他和忙状态、写使能、写保护等功能相关
  4. 256字节的页缓存,它会对一次性写入的数据量,产生限制
  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值