前言
最近想重温一下32标准库的内容,所以打算写几篇博客梳理一遍之前学过的知识点,图片和代码都是参考江科大的,江科大32教程非常不错,不管是小白还是大佬想学习32标准库都可以看他b站的课程。
一、建立第一个工程文件
步骤主要如下:
- 建立工程文件夹,Keil中新建工程,选择型号
- 工程文件夹里建立Start、Library、User等文件夹,复制固件库里面的文件到工程文件夹
- 工程选项,C/C++,Include Paths内声明所有包含头文件的文件夹
- 工程选项,C/C++,Define内定义USE_STDPERIPH_DRIVER
- 工程选项,Debug,下拉列表选择对应调试器,Settings,Flash Download里勾选Reset and Run
1.新建文件选择型号
在这里选择stm32f103c8t6
2.从固件包添加工程必要文件
(1)添加启动文件
D:固件库\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST
\STM32F10x\startup\arm
STM32的程序是从启动文件开始执行的,新建文件夹把启动文件和需要的文件添加进去
后续选择md.s启动文件添加上去
(2)添加库文件
定义外设库文件后下面语句才成立
(3)添加库文件头文件包含关系文件和中断相关文件
3.添加路径和头文件
添加文件路径,后续自己新添加的文件都需要添加文件路径,在这里只示例一个
添加一个文件放main.c文件,然后加入头文件编译测试无错误
编码如图选择,才不会产生中文乱码
4.烧录代码
Debug选择ST-Link
编译后无错误点击LOAD下载即可烧录
二、GPIO输入输出
- GPIO(General PurposeInput Output)通用输入输出口
- 可配置为8种输入输出模式
- 引脚电平:0V~3.3V,部分引脚可容忍5V
- 输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器模拟通信协议输出时序等
- 输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等
1.8种输入输出模式
通过配置GPIO的端口配置寄存器,端口可以配置成以下8种模式:
浮空/上拉/下拉输入:IN_FLOATING/IPD(In Pull Down)/IPU(In Pull Up)
模拟输入:AIN(Analog input)
开漏/推挽输出:Out_OD(Out Open Drain)/ Out_PP(Out Push Pull)
复用开漏/推挽输出:AF_OD(Atl Open Drain)/ AF_PP(ATL Push Pull)
对于普通的开漏/推挽输出,引脚的控制权是来自输出数据寄存器,复用开漏/推挽输出可以使引脚的控制权是来自外设,例如我们想用定时器控制引脚输出PWM波形,那就需要使用复用开漏/推挽输出的模式
2.LED灯和蜂鸣器示例
硬件原理图:
NPN:高通低断(负载在上方)
PNP:低通高断(负载在下方)
通过原理图可知仅需要配置时钟和GPIO初始化,然后设置引脚高低电平即可实现对应功能。
(1)点亮一个灯
#include "stm32f10x.h" // Device header #include "Delay.h" int main(void) { /*开启时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟 //使用各个外设前必须开启时钟,否则对外设的操作无效 /*GPIO初始化*/ GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式,赋值为推挽输出模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIO引脚,赋值为第0号引脚 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度,赋值为50MHz GPIO_Init(GPIOA, &GPIO_InitStructure); //将赋值后的构体变量传递给GPIO_Init函数 //函数内部会自动根据结构体的参数配置相应寄存器 //实现GPIOA的初始化 /*主循环,循环体内的代码会一直循环执行*/ while (1) { /*设置PA0引脚的高低电平,实现LED闪烁,下面展示3种方法*/ /*方法1:GPIO_ResetBits设置低电平,GPIO_SetBits设置高电平*/ GPIO_ResetBits(GPIOA, GPIO_Pin_0); //将PA0引脚设置为低电平 Delay_ms(500); //延时500ms GPIO_SetBits(GPIOA, GPIO_Pin_0); //将PA0引脚设置为高电平 Delay_ms(500); //延时500ms /*方法2:GPIO_WriteBit设置低/高电平,由Bit_RESET/Bit_SET指定*/ GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); //将PA0引脚设置为低电平 Delay_ms(500); //延时500ms GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); //将PA0引脚设置为高电平 Delay_ms(500); //延时500ms /*方法3:GPIO_WriteBit设置低/高电平,由数据0/1指定,数据需要强转为BitAction类型*/ GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0); //将PA0引脚设置为低电平 Delay_ms(500); //延时500ms GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1); //将PA0引脚设置为高电平 Delay_ms(500); //延时500ms } }
(2)流水灯
#include "stm32f10x.h" // Device header #include "Delay.h" int main(void) { /*开启时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟 //使用各个外设前必须开启时钟,否则对外设的操作无效 /*GPIO初始化*/ GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式,赋值为推挽输出模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //GPIO引脚,赋值为所有引脚 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度,赋值为50MHz GPIO_Init(GPIOA, &GPIO_InitStructure); //将赋值后的构体变量传递给GPIO_Init函数 //函数内部会自动根据结构体的参数配置相应寄存器 //实现GPIOA的初始化 /*主循环,循环体内的代码会一直循环执行*/ while (1) { /*使用GPIO_Write,同时设置GPIOA所有引脚的高低电平,实现LED流水灯*/ GPIO_Write(GPIOA, ~0x0001); //0000 0000 0000 0001,PA0引脚为低电平,其他引脚均为高电平,注意数据有按位取反 Delay_ms(100); //延时100ms GPIO_Write(GPIOA, ~0x0002); //0000 0000 0000 0010,PA1引脚为低电平,其他引脚均为高电平 Delay_ms(100); //延时100ms GPIO_Write(GPIOA, ~0x0004); //0000 0000 0000 0100,PA2引脚为低电平,其他引脚均为高电平 Delay_ms(100); //延时100ms GPIO_Write(GPIOA, ~0x0008); //0000 0000 0000 1000,PA3引脚为低电平,其他引脚均为高电平 Delay_ms(100); //延时100ms GPIO_Write(GPIOA, ~0x0010); //0000 0000 0001 0000,PA4引脚为低电平,其他引脚均为高电平 Delay_ms(100); //延时100ms GPIO_Write(GPIOA, ~0x0020); //0000 0000 0010 0000,PA5引脚为低电平,其他引脚均为高电平 Delay_ms(100); //延时100ms GPIO_Write(GPIOA, ~0x0040); //0000 0000 0100 0000,PA6引脚为低电平,其他引脚均为高电平 Delay_ms(100); //延时100ms GPIO_Write(GPIOA, ~0x0080); //0000 0000 1000 0000,PA7引脚为低电平,其他引脚均为高电平 Delay_ms(100); //延时100ms } }
(3)蜂鸣器
#include "stm32f10x.h" // Device header #include "Delay.h" int main(void) { /*开启时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启GPIOB的时钟 //使用各个外设前必须开启时钟,否则对外设的操作无效 /*GPIO初始化*/ GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式,赋值为推挽输出模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //GPIO引脚,赋值为第12号引脚 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度,赋值为50MHz GPIO_Init(GPIOB, &GPIO_InitStructure); //将赋值后的构体变量传递给GPIO_Init函数 //函数内部会自动根据结构体的参数配置相应寄存器 //实现GPIOB的初始化 /*主循环,循环体内的代码会一直循环执行*/ while (1) { GPIO_ResetBits(GPIOB, GPIO_Pin_12); //将PB12引脚设置为低电平,蜂鸣器鸣叫 Delay_ms(100); //延时100ms GPIO_SetBits(GPIOB, GPIO_Pin_12); //将PB12引脚设置为高电平,蜂鸣器停止 Delay_ms(100); //延时100ms GPIO_ResetBits(GPIOB, GPIO_Pin_12); //将PB12引脚设置为低电平,蜂鸣器鸣叫 Delay_ms(100); //延时100ms GPIO_SetBits(GPIOB, GPIO_Pin_12); //将PB12引脚设置为高电平,蜂鸣器停止 Delay_ms(700); //延时700ms } }
STM32标准库基础知识-2