STM32学习笔记

  绪论:此笔记为记录我学习STM32的一些学习总结,写此笔记的原因一是为了让自己养成记录学习过程的好习惯,二是为了今后如果因为太久没用到这方面的内容,还可以回来复习一下,因此决定写下此笔记。

  参考内容:《STM32中文参考手册》、《STM32数据手册》、《零死角转玩STM32》、《STM32开发指南-库函数版本》

1、STM32_GPIO

  我们一般使用一款单片机,最常用的就是对单片机的GPIO进行操作了,下面我分两个方面分别对GPIO的介绍和GPIO的配置及应用。

1.1、STM32_GPIO介绍

  
STM32的GPIO有8种模式,如下:
输入浮空
输入上拉
输入下拉
模拟输入
  
开漏输出
推挽输出
推挽复用
开漏复用
  8种模式分为了4种输入模式和4种输出模式,应用于不同场合,由模式的命名也可看出模式的具体作用,下面将对应GPIO初始化的一些函数对GPIO的应用进行讲解。

1.2、STM32_GPIO的配置及应用

  STM32初始化信息都是写入一个结构体,再由外设初始化函数来完成的。其结构体的命名规则为XXX_InitTypeDef,初始化函数为XXX_Init(),其中XXX为外设英文缩写,现在列出GPIO初始化的步骤的代码进行详细讲解。
在这里插入图片描述
此函数实现了对GPIOB端口的第8第9引脚进行了配置,具体如下:
第一句:定义初始化的结构体,
第二句:打开时钟(使用STM32的任何外设都必须开启相对应的 时钟)
结构体:对初始化结构体内容进行赋值,具体为哪个引脚、引脚模式、翻转速度
初始化:将赋值后的结构体内容写入到相对应的寄存器中设置GPIO输出电平(不是必要的)一般就使用普通的GPIO功能这样配置就可以了,其他的复用功能之类的后面再去介绍,本内容只介绍基本的GPIO的配置并且使用。掌握了GPIO的配置之后,就可以进行简单的按键检测,点亮小灯之类的操作了。

2、STM32_EXTI

	EXTI是STM32的外部中断,是GPIO的复用功能,STM32的每个IO口都可以复用成外部中断,可设置成是上升沿还是下降沿中断。提到中断就不得不提到中断管理NVIC(嵌套向量中断控制器),为啥需要这玩意儿呢?因为我们的STM32中断非常的多,基本每个外设都可以配置中断,那么如此多的中断我们应该如何管理就是一个问题,比如我配置了10个中断,那么谁先执行谁后执行呢?因此需要NVIC。至于如何用,我们下面再讲。

2.1、STM32_EXTI的配置

  外部中断感觉没啥好介绍的,那么我们就直接来根据代码配置来讲解吧,因为外部中断是GPIO的复用功能,最终使用的还是GPIO端口,所以我们还是需要配置GPIO的初始化的,我们将GPIOE的3,4引脚和GPIOA 0引脚配置成外部中断,先初始化相应的GPIO,如下:
在这里插入图片描述

  因为外部中断是用来检测外部电压的边沿信号,因此我们要设置为输入模式,如果上升沿触发外部中断,则配置下拉输入(配置好默认低电平),下降沿则相反。继而我们就可以开始配置复用功能EXTI了,配置如下:
在这里插入图片描述

  可以看出,跟初始化GPIO过程差不多,初始化的结构体和初始化的函数,不过注意的是,外部中断是GPIO的复用功能,因此需要打开复用时钟AFIO。GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3)函数是用来配置你所使用的中短线是哪个GPIO的哪一个IO口,结构体第一个赋值是指定映射的外部中断线,第二个是选择是外部中断还是事件(事件和中断的流程大致一样,不同的是中断在中断函数里面执行,而事件是一个标志或者其他方式来激活ADC转换或者DMA搬运数据等,不需要CPU参与),第三个是选择上升沿还是下降沿或者是上升下降沿都中断。此时EXTI也配置完毕。我们上面说过了,由于中断是要进行集中管理的,由NVIC进行管理,因此我们还要对NVIC进行配置。配置代码如下:
在这里插入图片描述

  第一个参数为选择中断的通道,第二个为设置抢占优先级,第三个为响应优先级,这是根据中断分组函数来决定的,最后使能中断即可。
  
总结:
外部中断的配置要有三个步骤:
①外部中断IO口的模式配置
②EXTI模式的配置
③NVIC的配置
注意:使用到了中断一定要调用中断分组函数void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)进行中断分组哦。

3、STM32_DMA

  DMA是STM32的一个外设,主要作用就是实现数据的搬运而不使用CPU去处理,(可以理解为不需要通过运行程序去写数据的传输过程,只要配置好了DMA之后,硬件会根据你配置的信息自己去搬运数据)减轻了CPU的负担。可以实现以下几种搬运:
--------外设到存储器
--------存储器到外设
--------存储器到存储器

3.1、STM32_DMA介绍

  DMA通道对应可搬运外设表:

DMA1
在这里插入图片描述

DMA2
在这里插入图片描述
  
名词解释:
①通道
DMA 具有 12个独立可编程的通道,其中 DMA1有7个通道,DMA2有5个通道,每一个通道对应不同的 外设的DMA请求。虽然每个通道可以接收多个外设的请求,但是同一时间只能接收一个。
②仲裁器
当发生多个DMA通道请求时,就意味着有先后响应处理的顺序问题,这个就由仲裁器也管理。仲裁器管理DMA通道请求分为两个阶段。第一阶段属于软件阶段,可以在DMA_CCRx寄存器中设置,有4个等级:非常高、高、中和低四个优先级。第二阶段属于硬件阶段,如果两个或以上的 DMA通道请求设置的优先级一样,则他们优先级取决于通道编号,编号越低优先权越高,比如通道О高于通道1。在大容量产品和互联型产品中,DMA1控制器拥有高于DMA2控制器的优先级。
③DMA数据配置
使用DMA,最核心就是配置要传输的数据,包括数据从哪里来,要到哪里去,传输的数据的单位是什么,要传多少数据,是一次传输还是循环传输等等。
1从哪里来到哪里去
我们知道DMA传输数据的方向有三个:从外设到存储器,从存储器到外设,从存储器到存储器。具体的方向 DMA_CCR位4 DIR 配置:0表示从外设到存储器,1表示从存储器到外设。这里面涉及到的外设地址由 DMA_CPAR 配置,存储器地址由 DMA_CMAR配置。
外设到存储器
当我们使用从外设到存储器传输时,以ADC采集为例。DMA外设寄存器的地址对应的就是ADC数据寄存器的地址,DMA存储器的地址就是我们自定义的变量(用来接收存储AD采集的数据)的地址。方向我们设置外设为源地址。
存储器到外设
当我们使用从存储器到外设传输时,以串口向电脑端发送数据为例。DMA外设寄存器的地址对应的就是串口数据寄存器的地址,DMA存储器的地址就是我们自定义的变量(相当于一个缓冲区,用来存储通过串口发送到电脑的数据)的地址。方向我们设置外设为目标地址。
存储器到存储器
当我们使用从存储器到存储器传输时,以内部FLASH向内部SRAM 复制数据为例。DMA 外设寄存器的地址对应的就是内部FLASH(我们这里把内部FALSH当作一个外设来看〉的地址,DMA存储器的地址就是我们自定义的变量(相当于一个缓冲区,用来存储来自内部 FLASH 的数据)的地址。方向我们设置外设(即内部FLASH)为源地址。跟上面两个不一样的是,这里需要把 DMA_CCR位 14: MEM2MEM:存储器到存储器模式配置为l,启动M2M模式。
  
2.要传多少,单位是什么
当我们配置好数据要从哪里来到哪里去之后,我们还需要知道我们要传输的数据是多少,数据的单位是什么。以串口向电脑发送数据为例,我们可以一次性给电脑发送很多数据,具体多少由DMA_CNDTR配置,这是一个32位的寄存器,一次最多只能传输65535个数据。要想数据传输正确,源和目标地址存储的数据宽度还必须一致,串口数据寄存器是8位的,所以我们定义的要发送的数据也必须是8位。外设的数据宽度由 DMA_CCRx的PSIZE[1:0]配置,可以是8/16/32位,存储器的数据宽度由 DMA_CCRx的 MSIZE[ 1:0]配置,可以是8/16/32位。
在 DMA控制器的控制下,数据要想有条不紊的从一个地方搬到另外一个地方,还必须正确设置两边数据指针的增量模式。外设的地址指针由 DMA_CCRx的PINC配置,存储器的地址指针由MINC 配置。以串口向电脑发送数据为例,要发送的数据很多,每发送完一个,那么存储器的地址指针就应该加l,而串口数据寄存器只有一个,那么外设的地址指针就固定不变。具体的数据指针的增量模式由实际情况决定。
  
3.什么时候传输完成
数据什么时候传输完成,我们可以通过查询标志位或者通过中断的方式来鉴别。每个DMA通道在DMA传输过半、传输完成和传输错误时都会有相应的标志位,如果使能了该类型的中断后,则会产生中断。有关各个标志位的详细描述请参考 DMA中断状态寄存器DMA_ISR的详细描述。
传输完成还分两种模式,是一次传输还是循环传输,一次传输很好理解,即是传输一次之后就停止,要想再传输的话,必须关断 DMA使能后再重新配置后才能继续传输。循环传输则是一次传输完成之后又恢复第一次传输时的配置循环传输,不断的重复。具体的由DMA_CCRx寄存器的CIRC循环模式位控制。①-③截取自野火STM32库函数开发指南。

3.2、STM32_DMA配置

  首先我们看一下初始化结构体
在这里插入图片描述

  第3行顾名思义就是就是用来指定要搬运数据的外设的基地址(比如STM32串口1的数据寄存器是USART1->DR,向该寄存器写数据那么就是发送数据,用检查接收完成标志位或者开启接收中断的方式读取该寄存器就是读取接收到的串口数据,接收和发送的数据寄存器公用同一寄存器)如果外设是串口1,那么就可赋值为&USART1->DR.
  第4行的存储器地址可以是我们自己定义的变量或者数组(数组的话得传送首地址,也就是数组名或者第一个元素的地址)的地址
  第5行是传输方向选择,只能选择外设到存储器还是存储器到外设的
  第6行是指定传输数据的数目,也就是多少个,比如第9第10双方规定数据的宽度为一个字节,那么这一项的意思就是DMA需要搬运多少个字节。
  第7第8行是指每传输一个单位数据(单位数据可通过第9第10项设置成8、16、32位),地址是否需要自增,一般来说,外设的地址是固定的,比如串口1的USART1->DR寄存器,它的地址是固定死不会变化的,所以可以设置成不自增,但是如果我们搬运到的存储器的地址是我们自己创建的数组,因为数组的每一个元素地址都是在前一个地址+1得到的,因此存储器的地址是需要自增的。注意:还是以串口1的USART1->DR数据寄存器举例,虽然说此寄存器只用到了8位(串口一次只能发送8位数据),但是它实际上是32位的寄存器,只是说高24位没有用到,因此我们传输地址的时候,应该把此寄存器和我们要搬运到的存储器地址强制转换为32位的,如下:
在这里插入图片描述

  此函数的作用就是初始化DMA结构体用的,只不过是把几个结构体要用的特殊值用形参的方式进行传递赋值。
  第9第10上面介绍过了,就是设置数据的宽度,比如串口是8位,那就设置成8位的
  第11是设置DMA的模式的,有两种:一次传输和循环传输。一次穿传输就是只传输一次就不传输了。注意:如果设置只搬运一次的话,那么下次再想搬运按理说得先调用DMA_Cmd(DMA_CHx, DISABLE )关闭DMA,然后重新初始化结构体,再DMA_Cmd(DMA_CHx,ENABLE )打开DMA,但是实际上不需要这么麻烦,如果我们第一次设置的结构体的初始化的内容不用改动,我们只需要指定DMA的通道和数据长度即可。也是先关闭DMA,再调用DMA_SetCurrDataCounter(DMA_CHx,DMA1_MEM_LEN),再打开DMA即可。循环传输就是当传输的数据数目到0之后,会重新恢复成配置之前配置的DMA的配置,然后重头再继续搬运,继续到数据数目为0然后重复执行此操作。
  第12就跟中断优先级一样
  第13和第5行一样,设置传输方向,只能设置存储器到存储器的,如果不用就写DESABLE。
  
以下例子距离说明DMA的传输过程便于理解:

  配置好串口和DMA(假设配置成外设到存储器模式)并使能USART1接收中断,当USART接收到数据则会产生中断,此时在中断里面调用DMA_Cmd()函数使能DMA传输即可。

4、STM32_FSMC/FMC

  FSMC和FMC都是STM32用来管理外部扩展的存储器的,F429以前是只支持FSMC,而F429及以上是FMC,区别是FMC支持SDRAM而FSMC不支持。FSMC/FMC只支持100及以上引脚的单片机,100以下引脚是没有的。

4.1、STM32_FSMC/FMC介绍

  众所周知,一般两芯片通信都是要靠通信时序的,FSMC/FMC就是通过一系列的配置之后能产生两者之间相对应的通信时序而不需要程序去模拟时序来实现两个器件之间的正确通信。

  先来看看FSMC的框图:
在这里插入图片描述

  从这张图我们就可以看出来上面所说的,时钟是来自AHB总线,通过配置寄存器可以与3种器件通信,分别是NOR/PSRAM存储器、NAND存储器和PC卡。再看看其地址映射,如图:
在这里插入图片描述

  上面说了,FSMC可以控制三种不同器件,从这个地址映射我们就可以看出来以下信息:
0x6000 0000-0x6FFF FFFF 是来控制NOR/PSRAM存储器
0x7000 0000-0x7FFF FFFF 是来控制NAND闪存存储器
0x8000 0000-0x8FFF FFFF 是来控制NAND闪存存储器
0x9000 0000-0x9FFF FFFF 是来控制PC卡
  我们发现它上面标的是4x64MB,那么我们又可知道,它把每一块又分成了4个区(也就是告诉我们一个块可以挂4个器件,相当于IIC总线可以挂多个器件一样的效果),一个区占64MB,我们取出NOR/PSRAM来看看四个区的地址分配情况,如下:
在这里插入图片描述

  再来看看它占用哪些硬件引脚,这里以控制NOR Flash为例,如图:
在这里插入图片描述
  
根据上图可得知以下信息:
时钟线 1 根
地址线 26 根
数据线 16 根
片选线(也就是上面每块分的4个区对应的片选) 4 根
输出使能 1 根
写使能 1 根
输入 1 根
输出 1 根
  这里面的几个引脚我们需要注意的就是片选线的4个引脚,我们还是以块1的4个区为例,假设我块1的4个区全都挂上了器件,片选的四根线NE1连接到器件1,NE2连接到器件2,NE3连接到器件3,NE4连接到器件4,根据上图的每个区的地址来看,当我访问了0x68000000-0x6BFFFFFF这段地址,因为上图说了,这段地址是属于3区的,因此NE3会被拉低,STM32就会和器件3通信,当访问0x60000000- 0x63FFFFFF对应1区地址,因此NE1被拉低,STM32与器件1通信。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值