P0 序言&感想
如有差错,欢迎指出,正在学习,随时更新
1.为什么Stm32初始化外设都需要先打开时钟——每个外设都有独立时钟,如果不打开时钟外设就不能用,原因就是为了低功耗节省用电,不用的外设可以不打开时钟
2.初始化结构体和初始化库函数配合使用是标准库精髓所在,理解初始化结构体每个成员意义(函数经典成员:恢复缺省配置,初始化和结构体初始化)
P5 GPIO输出
·带FT的引脚可容忍5v电压
·所有的GPIO都是在APB2外设总线上
·每个GPIO总共有16个引脚,从0到15
·32是32位单片机,寄存器有32位,但只有16个端口,所以只有低16位有端口
下图为GPIO基本结构:
·以下面GPIO电路图为例,左三为寄存器,中间为驱动器,右边为某一个端口的的IO口的引脚。同时,整体分为两个部分,上面是输入部分,下面是输出部分
GPIO8种工作模式
(PS:详细参考手册)
1.浮空输入:不确定外部模块输出的默认状态或外部信号输出功率小(缺点:当引脚悬空时,没有默认电平,输入受噪声干扰,来回不断跳变)
2.上拉输入:
3.下拉输入:如果外部模块默认输出低电平,则配置下拉输入,上拉反之。一般默认高电平
4.模拟输入:一般时候用不到
5.开漏数入:高电平时呈现高阻态,没驱动能力
6.推挽输入
7.复用开漏输出
8.复用推挽输出
P6 LED闪烁&LED流水灯&蜂鸣器
P13 TIM定时中断
·中断源:对于外部中断来说,可以是引脚发生了电平跳变;对于定时器来说,可以是定时的时间到了;对于串口通信来说,可以是接收到了数据。
·中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源。
·中断嵌套:(中断程序再次中断,二次中断现象)当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回。
·响应优先级和抢占优先级(我的理解是):当程序1运行完后,响应优先级高的即使没排队,也可以直接运行;当程序1正在运行时,可以不等程序1运行完,抢占优先级高的可以让程序1靠边,优先运行,优先值越小,优先级更高。
AFIO
·AFIO主要完成两个任务:复用功能引脚重映射(就是最开始提到的引脚定义表,当想把默认复用功能换到重定义功能时,就是用AFIO来完成的,这也是AFIO的一大主要功能)、中断引脚选择。
EXTIx是外部中断对应的中断资源
·工作原理: EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序。
·触发方式:(引脚电平的变化类型)上升沿/下降沿/双边沿/软件触发(程序执行代码就能触发中断)。
·支持的GPIO口(外部中断引脚):所有GPIO口都能触发中断,但相同的Pin不能同时触发中断(比如PA0和PB0不能同时使用,智能选一个作为中断引脚;所以如果有多个中断引脚要选择不同的pin引脚,比如PA0和PA1、PB3就可以)
·NVIC就是STM32用来管理中断,分配优先级的,其中断优先级共有16个等级
P14 定时器中断&定时器外部时钟
·操作步骤:
(1)RCC时钟中断开始
(2)选择内部时钟源
(3)配置时机单元
(4)配置输出中断控制,允许中断输出到NVIC
(5)配置NVIC,并配置优先级
(6)运行控制-使能计数器
(7)定时器中断函数
·中断输出:ITConfig
·TIM2~7是APB1的外设时钟
·选择内部时钟,则默认是使用内部函数,可以不配置
·计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)
= CK_PSC / (PSC + 1) / (ARR + 1)
·PSC(Prescaler,预分频器值):它用于对输入时钟(CK_PSC)进行分频。通过设置PSC的值,可以降低输入时钟的频率,其计算公式为经过预分频后的时钟CK_CNT = CK_PSC / (PSC + 1)。例如,如果输入时钟CK_PSC是100MHz,设置PSC为9,那么CK_CNT的频率就是100MHz / (9 + 1)=10MHz。
·ARR(Auto - Reload Register,自动重装载寄存器值):决定了计数器的计数上限。当计数器的值达到ARR所设定的值后,计数器会重新从0开始计数,并产生相应的溢出事件,这用于确定计数器的周期,从而影响溢出频率。例如,在定时器应用中,如果ARR设置为999,计数器从0开始计数,计到999后就会溢出重置。
·CK_CNT:这是经过预分频后的时钟信号用于驱动计数器计数的时钟频率。计数器在这个时钟的驱动下进行计数操作,每来一个 CK_CNT 时钟脉冲,计数器的值就会加1。
·CK_CNT_OV:这是计数器的溢出频率。当计数器计数到自动重装载值(由 ARR 决定)时就会产生溢出, CK_CNT_OV 表示这种溢出情况发生的频率,即单位时间内计数器溢出的次数。
P15 TIM输出比较
PWM
· 频率 :f = 1 / Ts(周期的倒数就是频率);变换越快=频率越大(PWM的频率越快,它等效模拟的信号就越平稳,不过同时性能开销就越大;一般来说PWM的频率在几kHz到几十kHz之间。)
· 占空比:q=Ton/Ts( Ton是高电平的时间,Ts是一个周期的时间。q就是高电平时间相对于整个周期时间的比例);占空比决定了PWM等效出的模拟电压的大小。一般用百分比表示。
·分辨率:占空比的变化步距;分辨率就是占空比变化的精细程度。即,占空比最小能以百分之多少的精度变化,它的值可以是1%、0.1%。分辨率的大小要看实际项目的需求定。如果既要高频率,又要高分辨率,就需要硬件电路要有足够的性能。要求不高的情况下,1%的分辨率就足够使用了。
P18 输入捕获模式测频率&PWMI模式测频率占空比
· PWM频率=更新频率=72M/(PSC+1)/(ARR+1),占空比=CCR/(ARR+1),所以通过ARR调节频率,会影响占空比,而通过PSC调节频率不影响
·TIM_PrescalerConfig:单独写入PSC的函数
·IC捕获的初始化:
(1)RCC开启时钟,把GPIO和TIM的时钟打开
(2)GPIO初始化,把GPIO配置成输入模式(上拉或浮空)
(3)配置时机单元,让CNT计数器在内部时钟的驱动下自增运行
(4)配置输入捕获单元
(5)选择从模式的触发源
(6)选择触发之后的操作
·TIM_SelectInputTrigger:选择输入触发源TRGI(对应上图第二个模块)
·TIM_SelectOutputTrigger:选择输出触发源TRGO(主模式的触发源)
·TIM_SelectSlaveMode:选择从模式
P19 编码器接口
P20 编码器测速接口
操作流程:
1.RCC开启时钟,开启GPIO和定时器的时钟
2.配置GPIO
3.配置时机单元,预分频器选择不分频,自动重装一般最大给65535
4.配置输入捕获单元,这里只有滤波器和极性两个有用
5.配置编码器接口模式
6.调用TIM_Cmd,启动定时器
·不需要定时器内部时钟配置,因为编码器接口会托管时钟,是一个带方向控制的外部时钟
·计数器模式也没用,也被托管
P21 ADC模数转换器
·ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁(具体解释:STM32主要是数字电路,数字电路只有高低电平,没有几v电压的概念,所以想读取电压值,就需要借助adc模数转换器来实现,adc读取引脚上的模拟电压转换为一个数据存在寄存器里,我们再把这个数据读取到变量里来就可以进行显示、判断、记录等操作了)
·数字到模拟的桥梁是DAC数字模拟转换器,使用DAC就可以将数字变量转换为模拟电压,PWM也是数字到模拟的桥梁,PWM实现的就是DAC的功能,同时PWM只有完全导通和完全断开两种状态,在这两种状态上都没有功率损耗,所以在直流电机调速这种大功率的应用场景使用PWM来等效模拟量是比DAC更好的选择并且PWM电路更加简单更加常用,所以PWM还是挤占了DAC很多的应用空间
基本结构:
四种转换模式:
·单次转换:每触发一次,转换结束就会停下来,下次转换就得再触发才能开始
·连续转换:一次转换完成后不会停下来,而是立刻开始下一轮的转换,并持续下去
·非扫描模式:只对存放在序列1的通道起作用。
·扫描模式:用到“菜单”列表,可以在菜单里点菜,每个菜单列表位置是通道几是可以任意指定的并且可以重复,然后初始化结构体有个通道数目的参数(表明用了几个通道)。
数据对齐
·STM32中的ADC是12位的,但是数据寄存器拥有16位,故存在数据对齐的问题。数据右对齐,即作为转换结果的12位数据向右靠,高位补0;数据左对齐,即作为转换结果的12位数据向左靠,低位补0。在使用时通常使用数据右对齐,这样在读取时直接读取寄存器即可。
AD转换时间
ADC校准
(不需要理解,这个校准过程是固定的,只需要在ADC初始化的最后加几条代码就行了,至于如何计算如何校准,不需管)
P22 ADC单通道&ADC多通道
AD模块编程步骤:
·开启ADC和GPIO的时钟,设置ADC时钟
·GPIO初始化
·规则组通道配置
·ADC初始化
·ADC使能
·ADC校准
P23 DMA直接存储器存取
·DMA基本结构
P24 DMA数据转运&DMA+AD多通道
P25 USART串口协议
·USART——TX是数据发送引脚,RX是数据接收引脚
·I2C——SCL是时钟,SDA是数据
·SPI——SCLK是时钟,MOSI是主机数据输出脚,MOSI是主机数据输入脚,CS是片选
·CAN——两个是差分数据脚
·USB——两个是差分数据脚
·全双工:通信双方能够同时进行双向通信
串口引脚分布:
P27 串口发送&串口发送+接收
串口的几个重要的参数:
·波特率,串口通信的速率空闲,一般为高电平
·起始位,标志一个数据帧的开始,固定为低电平。当数据开始发送时,产生一个下降沿。(空闲–>起始位)
·数据位,发送数据帧,1为高电平,0为低电平。低位先行。比如 发送数据帧0x0F 在数据帧里就是低位线性 即 1111 0000
·校验位,用于数据验证,根据数据位的计算得来。有奇校验,偶校验和无校验。
·停止位,用于数据的间隔,固定为高电平。数据帧发送完成后,产生一个上升沿。(数据传输–>停止位)
串口发送编程步骤:
1.开启GPIO和USAET时钟
2.GPIO初始化,把TX配置成复用输出,RX配置成输入(查看引脚定义表RX在APB10,TX在APB9)
3.配置USART初始化,使用结构体
4.如果需要接收的功能,加上时钟
TX要选复用推挽输出,RX要选浮空输入或上拉输入(串口波形空闲状态是高电平,所以不使用下拉输入)
其NVIC初始化:
串口发送程序的运行:
1. 当串口发送数据时,会检测发送移位寄存器是不是有数据正在移位,如果没有移位,那么这个数据就会立刻转移到发送移位寄存器里。准备发送。
2. 当数据移动到移位寄存器时,会产生一个TXE发送寄存器空标志位,该位描述如下。当TXE被置1,那么就可以在TDR写入下一个数据了。即发送下一个数据。
3. 发送移位寄存器在发送器控制的控制下,向右移位,一位一位的把数据传输到TX引脚。
4. 数据移位完成后,新的数据就会再次从TDR转移到发送移位寄存器里来,依次重复1-3的过程。通过读取TXE标志位来判断是否发送下一个数据。
串口助手数据模式:
·HEX模式/十六进制模式/二进制模式:以原始数据的形式显示
·文本模式/字符模式:以原始数据编码后的的形式显示
\r\n
的效果是将光标移回当前行的开头,然后移动到下一行,这样下一行打印的内容就会从新的一行开始。
printf函数的移植方法
一、(printf只能有一个,重定向到串口1,串口2就没有用了)
打开工程选项,把Use MicrLIB勾上
fputc是printf函数的底层,printf打印的时候就是调用fputc一个个打印
二、多个串口想用printf—— 使用sprintf可以指定打印的位置
三、封装sprintf
添加头文件#include <stdarg.h>
没学过,不知道,会移植就行
UTF8中文不乱码的方法:
1. 打开工程选项,C\C++,杂项控制栏写上--no-multibyte-chars
2.串口助手编码方式要选UTF8
P28 USART数据包
优点:传输最直接,解析数据非常简单
优点:数据直观易理解,灵活
P29 串口收发HEX数据包&串口收发文本数据包
P30 FlyMcu串口&STLINK Utility
P31 I2C通信协议
基本结构:
·一个I2C总线只使用两条总线线路,一条双向串行数据线(SDA) , 一条串行时钟线 (SCL)。数据线即用来表示数据,时钟线用于数据收发同步
·处于空闲状态,时钟线和数据线都处于高电平状态,谁要放数据谁就掌握SCL(拉低SCL),然后改变SDA ,处于接收的设备需释放SDA发数据SCL低电平,读数据SCL高电平
·每个连接到总线的设备都有一个独立的地址, 主机可以利用这个地址进行不同设备之间的访问
·发送应答:主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答。
·接收应答:主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)(谁接收信息谁就要发应答位)
I2C时序基本单元:
I2C时序:
起始条件:指SCL高电平时,SDA从高电平切换到低电平。在I2C总线处于空闲状态时,SCL和SDA都处于高电平状态。当主机需要数据收发时,会首先产生一个起始条件——SCL保持高电平,然后把SDA拉低,产生一个下降沿。当从机捕获到这个SCL高电平,SDA下降沿信号时,就会进行自身的复位,等待主机的召唤。之后,主机需要将SCL拉低。这样做一方面是占用这个总线,另一方面也是为了方便这些基本单元的拼接。这样,除了起始和终止条件,每个时序单元的SCL都是以低电平开始,低电平结束。
终止条件:SCL高电平期间,SDA从低电平切换到高电平。SCL先放开并回弹到高电平,SDA再放开并回弹高电平,产生一个上升沿。这个上升沿触发终止条件,同时终止条件之后,SCL和SDA都是高电平,回归到最初的平静状态。这个起始条件和终止条件就类似串口时序里的起始位和停止位。一个完整的数据帧总是以起始条件开始、终止条件结束。另外,起始和终止都是由主机产生的。因此,从机必须始终保持双手放开,不允许主动跳出来去碰总线。如果允许从机这样做,那么就会变成多主机模型,不在本节的讨论范围之内。这就是起始条件和终止条件的含义。
I2C的从机设备
12C的完整时序,主要有指定地址写,当前地址读和指定地址读这3种。主机可以访问总线上的任何一个设备,我们需要为每个从设备分配一个唯一的设备地址。这些地址就像是每个设备的名字,主机通过发送这些地址来确定要与哪个设备通信(每个I2C设备在出厂时都会被分配一个7位的地址。例如,MPU6050的7位地址是1101 000,而AT24C02的7位地址是1010 000。不同型号的芯片地址是不同的,但相同型号的芯片地址是相同的。)
I2C的读写
·指定地址写:
·当前地址读:
·指定地址读:=指定地址写 + 当前地址读
P32 MPU6050简介
P33 软件I2C读取MPU6050
程序整体框架:
P34 I2C通信协议
P35 硬件I2C读写MPU6050
P36 SPI通信协议
SS ( Slave Select):从设备选择信号线,常称为片选信号线
SCK (Serial Clock):时钟信号线
MOSI (Master Output, Slave Input):主设备输出/从设备输入引脚。主机的数据从这条信号线输出, 从机由这条信号线读入主机发送的数据,即这条线上数据的方向为主机到从机。
MISO (Master Input,,Slave Output):主设备输入/从设备输出引脚。主机从这条信号线读入数据, 从机的数据由这条信号线输出到主机,即在这条线上数据的方向为从机到主机。