ARM学习笔记基础STM32

这篇博客主要介绍了STM32的基础知识,包括GPIO的工作原理、常用寄存器和实验,时钟配置,IO引脚的复用和映射,串口通信方式和配置,独立看门狗的使用,以及通用定时器的配置和实验。通过这些内容,读者可以了解STM32如何进行GPIO的配置,串口通信的实现以及定时器中断的设置。此外,还涵盖了外部中断和ADC的相关知识点。
摘要由CSDN通过智能技术生成

资料来源:正点原子STM32

目录

GPIO工作原理

常用寄存器

实验:跑马灯(库函数版本)

实验步骤

时钟

IO引脚的复用和映射

串口

串行通信方式

异步通信特点

串口配置方法

串口配置步骤(将PA9,PA10设置为串口1)

实验:串口通信

独立看门狗

实验:看门狗

窗口看门狗

窗口看门狗实验

通用定时器

实验:定时器中断

外部中断

外部中断配置步骤

ADC

量程(模拟量输入范围)

精度(分辨率resolution)

转换速率(MSPS与conventor clock的不同)

通道数

转换模式

ADC采样时间

参数相关配置

DMA

请求映射

流配置过程

DMA中断

库函数

多重ADC

三重ADC转换原理

DMA模式请求

三重ADC采样单通道信号ADC与DMA配置


GPIO工作原理

一个stm35包括7组IO,一组IO有16个IO口,一组IO口下面有10个寄存器用于配置这16个IO口的状
态。 
如果一个IO口需要两位寄存器控制,则一组IO口由32位的IO口控制。 
如果一个IO口需要一位寄存器控制,则一组IO口由32位的IO口控制,其中只用到了低16位,高16
位保留。
GPIO工作方式: 
4种输入模式: 
输入浮空 
输入上拉 
输入下拉 
模拟输入 
4种输出模式: 
开漏输出(带上拉或者下拉) 
开漏复用功能(带上拉或者下拉) 
推挽式输出(带上拉或者下拉) 
推挽式复用功能(带上拉或者下拉)
4种最大输出速度: 
­2MHZ 
­25MHz 
­50MHz 
­100MHz

常用寄存器

每组IO口都拥有以下常用寄存器: 
一个端口模式寄存器(GPIOx_MODER) 
一个端口输出类型寄存器(GPIOx_OTYPER) 
一个端口输出速度寄存器(GPIOx_OSPEEDR) 
一个端口上拉下拉寄存器(GPIOx_PUPDR) 
一个端口输入数据寄存器(GPIOx_IDR) 
一个端口输出数据寄存器(GPIOx_ODR) 
一个端口置位/复位寄存器(GPIOx_BSRR) 
一个端口配置锁存寄存器(GPIOx_LCKR) 
两个复位功能寄存器(低位GPIOx_AFRL & GPIOx_AFRH)

实验:跑马灯(库函数版本)

以下是几个寄存器的库函数参数: 
GPIO_InitTypeDef GPIO_InitStructure;
MODER寄存器 
端口模式控制寄存器,用于控制GPIOx的工作模式,每2位控制一个IO口,代码中属性为:
GPIO_InitStructure.GPIO_Mode

typedef enum
{
GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode 输入模式*/
GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode 输出模式*/
GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode 复用功能模式*/
GPIO_Mode_AN = 0x03 /*!< GPIO Analog Mode 模拟模式*/
}GPIOMode_TypeDef;

OTYPER寄存器 
用于控制GPIOx的输出类型,每1位控制一个IO口,该寄存器仅用于输出模式,输入模式下不
起作用,代码属性:GPIO_InitStructure.GPIO_OType

typedef enum
{
GPIO_OType_PP = 0x00,/*输出推挽(复位状态)*/
GPIO_OType_OD = 0x01/*输出开漏*/
}GPIOOType_TypeDef;

OSPEEDR寄存器 
用于控制GPIOx的输出速度,每2位控制一个IO口,仅用于输出模式,代码中属性为:
GPIO_InitStructure.GPIO_Speed

#define GPIO_Speed_2MHz GPIO_Low_Speed
#define GPIO_Speed_25MHz GPIO_Medium_Speed
#define GPIO_Speed_50MHz GPIO_Fast_Speed
#define GPIO_Speed_100MHz GPIO_High_Speed

PUPDR寄存器 
控制GPIOx的上拉/下拉,每2位控制一个IO口,代码属性位:GPIO_InitStructure.GPIO_PuPd

typedef enum
{
GPIO_PuPd_NOPULL = 0x00, /*无上拉或下拉*/
GPIO_PuPd_UP = 0x01, /*上拉*/
GPIO_PuPd_DOWN = 0x02 /*下拉*/
}GPIOPuPd_TypeDef;

实验步骤

1.模板文件夹新建HARDWARE文件,并且打开程序建立led.h,led.c保存。引入.h文件,添加头文件
路径。 
2.在头文件中定义初始化函数.

#ifndef __LED_H
#define __LED_H
void LED_Init(void);
#endif

3.再.c重实现初始化函数

#include "led.h"
#include "stm32f4xx.h"
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//设置一个结构体对GPIO各个状态的设置
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);//设置GPIOF为始能状态
//F9
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//设置GPIOF9
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//50MHZ
GPIO_Init(GPIOF,&GPIO_InitStructure);//库函数中的初始化函数
GPIO_SetBits(GPIOF,GPIO_Pin_9);//设置为1
//F10
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOF,&GPIO_InitStructure);
GPIO_SetBits(GPIOF,GPIO_Pin_10);
}

4.main函数

#include "stm32f4xx.h"
#include "led.h"
#include "delay.h"
int main(void)
{
delay_init(168);
LED_Init();
while(1){
GPIO_SetBits(GPIOF,GPIO_Pin_9);
GPIO_SetBits(GPIOF,GPIO_Pin_10);
delay_ms(500);
GPIO_ResetBits(GPIOF,GPIO_Pin_9);
GPIO_ResetBits(GPIOF,GPIO_Pin_10);
delay_ms(500);
}
}

时钟

同一个电路,时钟越快功耗越大,同时抗电磁干扰能力也会越弱,可以理解为时钟就是执行命令的
时间,始终越快,执行一条命令时间越短。时钟图:

MCO1和MCO2是两个引脚用于输出芯片中的时钟,最大频率不超过100M
CSS:时钟安全单元,如果系统时钟的输入HSE外部晶振出了问题,则CSS会将系统时钟切换
到HSI时钟源 
STM32 中有5个时钟源,HSI,HSE,LSI,LSE,PLL。 
①、LSI 是低速内部时钟,RC 振荡器,频率为 32kHz 左右。供独立看门狗和自动唤醒单元使
用。 
②、LSE 是低速外部时钟,接频率为 32.768kHz 的石英晶体。这个主要是 RTC 的时钟源。 
③、HSE 是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为
4MHz~26MHz。 
我们的开发板接的是 8M 的晶振。HSE 也可以直接做为系统时钟或者 PLL 输入。 
④、HSI 是高速内部时钟,RC 振荡器,频率为 16MHz。可以直接作为系统时钟或者用作 PLL 
输入。 
⑤、PLL 为锁相环倍频输出。STM32F4 有两个 PLL: 
1) 主 PLL(PLL)由 HSE 或者 HSI 提供时钟信号,并具有两个不同的输出时钟。 
第一个输出 PLLP 用于生成高速的系统时钟(最高 168MHz) 
第二个输出 PLLQ 用于生成 USB OTG FS 的时钟(48MHz),随机数发生器的时钟和 SDIO 
时钟。 
2)专用 PLL(PLLI2S)用于生成精确时钟,从而在 I2S 接口实现高品质音频性能。
主 PLL 时钟的时钟源要先经过一个分频系数为 M 的分频器,然后经过 
倍频系数为 N 的倍频器出来之后的时候还需要经过一个分频系数为 P(第一个输出 PLLP)或 
者 Q(第二个输出 PLLQ)的分频器分频之后,最后才生成最终的主 PLL 时钟。 
例如我们的外部晶振选择 8MHz。同时我们设置相应的分频器 M=8,倍频器倍频系数 N=336, 
分频器分频系数 P=2,那么主 PLL 生成的第一个输出高速时钟 PLLP 为: 
PLL=8MHz * N/ (M*P)=8MHz* 336 /(8*2) = 168MHz
系统初始化或者复位时,调用 SystemInit 函数对相关时钟进行默认配置,如果我们需要修改某些时
钟源配置,我们则再RCC相关寄存器中配置。 
STM32F4 的外设在使用之前,必须对时钟进行使能,如果没有使能时钟,那么外设是无法正常工
作的。下面是外设始能相关函数:

void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewS
tate);
void RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB2Periph, FunctionalState NewS
tate);
void RCC_AHB3PeriphClockCmd(uint32_t RCC_AHB3Periph, FunctionalState NewS
tate);
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewS
tate);
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewS
tate);

这里主要有5个外设始能函数,5个函数分别代表5个总线下面挂载的外设时钟,分别是AHB1 总
线,AHB2 总线,AHB3 总线,APB1 总线以及 APB2 总线。要使能某个外设,调用对应的总线外
设时钟使能函数即可。
修改系统时钟: 
在system_stm32f4xx.c中,代码721行设置HSE为系统时钟输入源,在316行设置各个分频系
数,默认输出是168M的系统时钟
初始化后的时钟: 
SYSCLK(系统时钟) =168MHz 
AHB总线时钟(HCLK=SYSCLK) =168MHz 
APB1总线时钟(PCLK1=SYSCLK/4) =42MHz 
APB2总线时钟(PCLK2=SYSCLK/2) =84MHz 
PLL主时钟 =168MHz

IO引脚的复用和映射

STM32F4系列微控制器IO引脚通过一个复用器连接到内置外设或模块。该复用器一次只允许一个
外设的复用功能(AF)连接到对应的IO口。这样可以确保共用同一个IO引脚的外设之间不会发生冲
突。 
每个IO引脚都有一个复用器,该复用器采用16路复用功能输入(AF0到AF15),可通过
GPIOx_AFRL(针对引脚0­7)和GPIOx_AFRH(针对引脚8­15)寄存器对这些输入进行配置,每四
位控制一路复用。 
相当于每个IO口的引脚都有一个复用器,而这个复用器对每个IO口的功能进行配置。比如说有一个
IO口PA2,他的一个复用器如图: 

因为是引脚2,所以用寄存器AFPL进行配置,AFPL配置该引脚的复用器选择哪一个AF,则选定了
该IO口的功能。
接下来看AFRL的示意图:

AFRL是一个32位寄存器,对于每一组IO口,一共16位IO,AFRL控制一个IO口的低8位,AFRH控
制一组IO口的高8位,比如我们要控制GPIOA2引脚的复用功能则调用GPIOA 这组IO的寄存器
AFRL,如上图,需要修改AFRL2的值来控制PA2 IO口,如果我们需要他的串口1功能,由图可以看
出USART1接连到复用器的AF7,所以我们需要根据图选择AF7,就是把AFRL2设置为0111。
接下来以PA9,PA10配置为串口1为例。 
①GPIO端口时钟使能。 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
②复用外设时钟使能。 
比如你要将端口PA9,PA10复用为串口,所以要使能串口时钟。 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
③端口模式配置为复用功能。 GPIO_Init()函数。 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能 
④配置GPIOx_AFRL或者GPIOx_AFRH寄存器,将IO连接 
到所需的AFx。
/PA9连接AF7,复用为USART1_TX /
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
/* PA10连接AF7,复用为USART1_RX*/ 
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟 ①
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟 ②
//USART1端口配置③
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10
//串口1对应引脚复用映射 ④
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USAR
T1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为US
ART1

串口

串行通信方式

按照数据传送方向,分为: 
单工: 
数据传输只支持数据在一个方向上传输 
半双工: 
允许数据在两个方向上传输,但是,在某一时刻,只允许数 
据在一个方向上传输,它实际上是一种切换方向的单工通信; 
全双工: 
允许数据同时在两个方向上传输,因此,全双工通信是两个 
单工通信方式的结合,它要求发送设备和接收设备都有独立 
的接收和发送能力。

按照时钟分类 
同步通信:带时钟同步信号传输。(由时钟控制) 
­SPI,IIC通信接口 
异步通信:不带时钟同步信号。(有一个约定) 
­UART(通用异步收发器),单总线
常见串行通信接口

stm32中的UART串口引脚:

异步通信特点

异步传输需要定义的参数: 
起始位 
数据位(8位或者9位) 
奇偶校验位(第9位) 
停止位(1,15,2位) 
波特率设置

奇偶校验的意思:比如数据位8位有偶数个1,进行偶校验,则第九位填0,若奇校验,则补1.

串口配置方法

相关寄存器: 
USART_SR状态寄存器 
USART_DR数据寄存器 
USART_BRR波特率寄存器
串口初始化方法: 
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct); 
第一个参数是串口几,第二个是一个结构体,结构体参数: 
结构体就是一种约定

typedef struct
{
uint32_t USART_BaudRate;//波特率
uint16_t USART_WordLength; //字长,8还是9位
uint16_t USART_StopBits; //停止位
uint16_t USART_Parity; //奇偶校验
uint16_t USART_Mode; //始能发送,接收选择
uint16_t USART_HardwareFlowControl; //硬件流控制
} USART_InitTypeDef;

串口配置步骤(将PA9,PA10设置为串口1)

1.同样打开模板,清空main函数,始能串口时钟与GPIO时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口时钟,始能AHB2,r
cc.h
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//GPIO时钟,始能GPI
OA,IO口用AHB1

2.引脚复用映射:

GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);//PA9映射到串口1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);//PA10映射到串
口1

3.对IO口进行初始化

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//设置为复用模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

4.对串口1进行初始化,并且始能:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值