标准库初始化
[!IMPORTANT]
采用Keil IDE基于C语言进行编写stm32运行代码(以stm32f10x系列为例),使用标准库首先需要引入相应的库文件,该文件需要自己去网上下载
新建工程
编写逻辑代码前需要对keil将文件夹中的内容读入到IDE中 ,点击keil上方tab栏中的Project
里面的New μVisioon Project...
,找到存放共工程的文件夹,并在该文件夹中在下方的文件名中输入该工程的名称,后点击保存。
在芯片选择中选择STM32F1x
对应的芯片,后点击OK,后续的窗口直接关闭即可。
后面再将对应的固件库文件放入到该工程文件夹中。
keil中把文件导入工程
在keil中点击三个方块样式的工程管理按钮
在Project Items
中的Groups
可添加对应名的文件夹,然后在再右侧的files
的下方Add Files
添加对应的固件库文件,即可成功创建文件。
然后点击三个方块样式旁边的魔术棒按钮。
在Tab栏中C/C++中的Include Paths
中添加工程所用到的文件以及Define
中改为USE_STDPERIPH_DRIVER
。
注:程序烧入到单片机中需要在该tab中的Debug
中设置
这样就成功完成了工程创建。
操作STM32的GPIO所需的初始化
先引入包
#include "stm32f10x.h"
再进行后续操作
首先需要将stm32的时钟使能,对应的函数方法在stm32f10x_rcc.h
中,主要函数为以下三个
void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState); //使能AHB的外设时钟
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState); //使能PB2的外设时钟
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState); //使能PB1的外设时钟
还需要使用void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
函数,使用结构体的参数来初始化GPIO口,使用该函数需要定义以该结构体GPIO_InitTypeDef
为类型的结构体变量,以下为例:
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
加上以上操作的完整代码为:
#include "stm32f10x.h" // Device header
int main(void)
{
//ENABLE CLOCK
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //采用推挽输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2; //使用GPIO0,1,2号引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出速度设置为50MHz
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化GPIOA外设的0号引脚
while(1)
{
}
}
GPIO的工作模式
typedef enum
{ GPIO_Mode_AIN = 0x0, //模拟输入
GPIO_Mode_IN_FLOATING = 0x04, //浮空输入
GPIO_Mode_IPD = 0x28, //下拉输入
GPIO_Mode_IPU = 0x48, //上拉输入
GPIO_Mode_Out_OD = 0x14, //开漏输出
GPIO_Mode_Out_PP = 0x10, //推挽输出
GPIO_Mode_AF_OD = 0x1C, //复用开漏
GPIO_Mode_AF_PP = 0x18 //复用推挽
}GPIOMode_TypeDef;
GPIO八种模式 | 特点以及应用 |
---|---|
模拟输入 | ADC和DAC使用。此模式下引脚电平不被采样或拉动。在此模式GPIO的数字输入功能关闭。 |
浮空输入 | 不使用内部电阻,完全浮空,默认状态不定,通常用于外部电路已经提供明确的上拉或下拉信号的场景。如 I²C 总线 SDA/SCL 引脚,外部已经设计有上拉电阻。 |
下拉输入 | 使用内部下拉电阻,默认输入低电平。适用于引脚通常为低电平,仅在特定情况下拉高。 |
上拉输入 | 使用内部上拉电阻,默认输入高电平。适用于检测低电平的输入信号,例如开关按钮的闭合状态。 |
开漏输出 | 引脚通过 MOS 管连接到地,输出低电平时导通,输出高电平时需外部上拉电阻。适用于多设备共享总线,如 I²C、多个设备的中断信号线以及电平兼容,如3.3V和5V设备互联。 |
推挽输出 | 引脚可以输出高电平或低电平,内部由MOS管驱动。适用于控制 LED、蜂鸣器、继电器等负载。 |
复用开漏 | 配置为复用功能,并使用开漏输出方式。适用于I²C 总线通信的 SDA 和 SCL 引脚以及多设备共享复用引脚时。 |
复用推挽 | 配置为复用功能,并使用推挽输出方式驱动信号。适用于外设信号需要主动输出高低电平。如 USART 的 TX、SPI 的 SCK/ MOSI 等时序信号。 |
模拟输入(下方所有×号代表不启用)
浮空输入
输入上拉(上开关打开,默认为高电平)
输入下拉(下开关打开,默认为低电平)
开漏输出(允许输入,且输出低电平导通)
推挽输出(输出数据寄存器输出高电平P-MOS导通,低电平N-MOS导通)
复用开漏(类似开漏输出,不过输出电平来自片上外设)
复用推挽(类似推挽输出,不过输出电平来自片上外设)
GPIO的函数使用
设置函数
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); //将GPIO_Pin设置为高电平,支持多引脚
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); //将GPIO_Pin设置为低电平,支持多引脚
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);//第三个参数为Bit_SET置为高电平,Bit_RESET置为低电平,仅支持单引脚配置
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
使用实例:
GPIO_SetBits(GPIOA,GPIO_Pin_0); //将GPIOA端口的第0号引脚置为高电平
GPIO_ResetBits(GPIOA,GPIO_Pin_0); //将GPIOA端口的第0号引脚置为低电平
GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET); //将GPIOA端口的第0号引脚置为低电平
GPIO_Write(GPIOA,~0x0001); //将GPIOA端口的第0号引脚置为低电平
读取函数
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); //读取GPIO_Pin的输入值,返回值代表该端口的电平
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx); //读取整个输入寄存器,返回每一位端口的电平
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); //
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx); //
AHB总线连接的外设
注:在APB1的操作速度最大频率为36MHz,在APB2的操作速度最大频率为72MHz
AFIO重映射
当使用的引脚的功能冲突时可以通过AFIO重映射来使用其他引脚来实现对应的功能,如USART1和TIM1的CH2和CH3引脚冲突,此时就可以使用AFIO将USART1_TX和USART1_RX的引脚改为PB6和PB7。
void USART1_Remap_Init(void) {
// 1. 启用 GPIOB 和 AFIO 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
// 2. 重映射 USART1 引脚到 PB6 (TX) 和 PB7 (RX)
GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);
// 3. 配置 GPIOB 的引脚为复用功能
GPIO_InitTypeDef GPIO_InitStruct;
// 配置 PB6 为复用推挽输出(USART1_TX)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
// 配置 PB7 为浮空输入(USART1_RX)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStruct);
// 4. 启用 USART1 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// 5. 配置 USART1 参数
USART_InitTypeDef USART_InitStruct;
USART_InitStruct.USART_BaudRate = 9600; // 波特率 9600
USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 数据位 8 位
USART_InitStruct.USART_StopBits = USART_StopBits_1; // 停止位 1 位
USART_InitStruct.USART_Parity = USART_Parity_No; // 无校验
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 收发模式
USART_Init(USART1, &USART_InitStruct);
// 6. 启用 USART1
USART_Cmd(USART1, ENABLE);
}
时钟
在STM32中由三种不同的时钟源来驱动系统时钟(SYSCLK):
- HSI振荡器时钟(High Speed Internal)
- HSE振荡器时钟(High Speed External)
- PLL时钟()
SYSCLK通过时钟树分发到不同的子系统和外设,如
- SYSCLK->AHB时钟
- 通过AHB Prescaler分频器生产AHB时钟(HCLK)用于:
- Cortex-M内核
- DMA控制器
- 内存接口(SRAM、FLASH等)
- 通过AHB Prescaler分频器生产AHB时钟(HCLK)用于:
- HCLK->APB时钟
- 通过APB和APB Prescaler 分频器生成APB时钟(PCLK1和PCLK2),用于:
- APB1 外设(如 TIM2、USART2 等)
- APB2 外设(如 ADC、USART1 等)
- 通过APB和APB Prescaler 分频器生成APB时钟(PCLK1和PCLK2),用于:
时钟配置可以使高速设备接高速时钟,低速设备接低速时钟,起到最大程度的节能效果。
名称 | 频率 | 外部连接 | 功能 | 用途 | 特性 |
---|---|---|---|---|---|
HSE(High-Speed External),高速外部时钟 | 4~16MHz | 4~16MHz晶体 | 系统时钟/RTC | 成本高,温漂小 | |
LSE(Low-Speed External),低速外部时钟 | 32kHz | 32.768kHz晶体 | 带校准功能 | RTC | 成本高,温漂小 |
HSI(High-Speed Internal),高速内部时钟 | 8MHz | 无 | 经出产调校 | 系统时钟 | 成本低,温漂大 |
LSI(Low-Speed Interal),低速内部时钟 | 40kHz | 无 | 带校准功能 | RTC | 成本低,温漂大 |