stm32入门第二天环境搭建RCC时钟GPIO闪烁实验与有源蜂鸣器实验
Posted 九磅十五便士的业余编程人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了stm32入门第二天环境搭建RCC时钟GPIO闪烁实验与有源蜂鸣器实验相关的知识,希望对你有一定的参考价值。
学习参考:STM32入门教程-2022持续更新中_江科大自化协P3-1~3-3
这两天学的稀里糊涂,这里看一点那里看一点,最后什么也没搞明白,为了电赛净选件但却发现最基础的32还没搞太懂,今天难得清闲,把视频重新看了一遍,觉得收获颇丰,遂开始重新记录笔记。
今日收获:LED闪烁实验、有源蜂鸣器实验
电赛倒计17天
- 开始之前
基础部分全部看完才发现stm32并没有我想象的难,其实流程上和arduino都是一样的,只是自己需要配置的东西变多了,需要很详细的初始化和 使用,而不像arduino那样只需要简单的初始化,但是这也是arduino的弊病,如果想要更改默认的参数会让你感到很迷糊,这可能是stm32做的好的地方。
代码的基础流程:开启时钟👉初始化引脚👉在死循环使用引脚
在平衡车的教学中,范学长直接把各个元件的初始化都包装到其他C文件和.h文件中,修改定义也要到那里去修改,这可能让老手很方便操作和修改,但是让刚入门的我在跳来跳去的过程中感到迷茫,在👆面的教程中,基本上所有代码都是在main函数中写出的,可能不是那么方便管理,但是让我感受到arduino书写代码时候的熟悉感,一种莫名的熟悉感,希望它能帮助我学的更快吧。
第二天环境搭建与GPIO
一、配置环境P3-1
方法1:直接复制已经建立好的环境
方法2:利用stm32f10x的库函数从头创立👇
3-1视频,提供参考
- 建立工程文件夹,Keil中新建工程,选择型号
- 工程文件夹里建立Start、Library、User等文件夹,复制固件库里面的文件到工程文件夹
- 工程里对应建立Start、Library、User等同名称的分组,然后将文件夹内的文件添加到工程分组里
- 工程选项,C/C++,Include Paths内声明所有包含头文件的文件夹
- 工程选项,C/C++,Define内定义USE_STDPERIPH_DRIVER
- 工程选项,Debug,下拉列表选择对应调试器,Settings,Flash Download里勾选Reset and Run
二、复位和时钟设置(RCC)
参考数据手册:STM32F103xx固件函数库用户手册
//常见使用的语句
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
常用的3个函数名 | 描述 |
---|---|
RCC_AHBPeriphClockCmd | 使能或者失能 AHB 外设时钟 |
RCC_APB2PeriphClockCmd | 使能或者失能 AHB2 外设时钟 |
RCC_APB1PeriphClockCmd | 使能或者失能 AHB1 外设时钟 |
3个函数的使用方法是一样的
函数名 | RCC_AHB2PeriphClockCmd |
---|---|
功能描述 | 使能或者失能 AHB 外设时钟 |
输入参数 1 | RCC_AHB2Periph: 门控 AHB 外设时钟 |
功能描述 | NewState:指定外设时钟的新状态 。这个参数可以取:ENABLE 或者 DISABLE |
输出参数 | 无 |
返回值 | 无 |
先决条件 | 无 |
被调用函数 | 无 |
Table 373.RCC_AHB2Periph 值
RCC_AHB2Periph | 描述 |
---|---|
RCC_APB2Periph_AFIO | 功能复用 IO 时钟 |
RCC_APB2Periph_GPIOA | GPIOA 时钟 |
RCC_APB2Periph_GPIOB | GPIOB时钟 |
RCC_APB2Periph_TIM1 | TIM1 时钟 |
RCC_APB2Periph_SPI1 | SPI1 时钟 |
省略了好多值,用到了再查吧
当某个库函数需要被调用函数为时钟函数时,把他使能就好了,大部分的都需要
三、通用输入/输出(GPIO)
GPIO 库函数常用的筛选
函数名 | 描述 |
---|---|
GPIO_Init | 根据 GPIO_InitStruct 中指定的参数初始化外设 GPIOx 寄存器 |
GPIO_StructInit | 把 GPIO_InitStruct 中的每一个参数按缺省值填入 |
GPIO_ReadInputDataBit | 读取指定端口管脚的输入 |
GPIO_ReadInputData | 读取指定的 GPIO 端口输入 |
GPIO_ReadOutputDataBit | 读取指定端口管脚的输出 |
GPIO_ReadOutputData | 读取指定的 GPIO 端口输出 |
GPIO_SetBits | 设置指定的数据端口位 |
GPIO_ResetBits | its 清除指定的数据端口位 |
GPIO_WriteBit | 设置或者清除指定的数据端口位 |
GPIO_Write | 向指定 GPIO 数据端口写入数据 |
GPIO_PinRemapConfig | 改变指定管脚的映射(复用其他功能) |
GPIO_EXTILineConfig | 选择 GPIO 管脚用作外部中断线路 |
具体使用方法参考库函数,只说几个用到的 |
1. GPIO_Init
函数名 | GPIO_Init |
---|---|
功能描述 | 根据 GPIO_InitStruct 中指定的参数初始化外设 GPIOx 寄存器 |
输入参数 1 | GPIOx:x 可以是 A,B,C,D 或者 E,来选择 GPIO 外设 |
输入参数 2 | GPIO_InitStruct:指向结构 GPIO_InitTypeDef 的指针,包含了外设 GPIO 的配置信息 |
输出参数 | 无 |
返回值 | 无 |
先决条件 | 无 |
被调用函数 | 无 |
typedef struct
u16 GPIO_Pin;
GPiospeed_TypeDef GPIO_Speed;
GPIOMode_TypeDef GPIO_Mode;
GPIO_InitTypeDef;
- 其中,GPIO_Pin包含16个管脚,从0~15,所以可以这么设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
//一般情况下↓全选
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
- GPIO_Speed有三个值可以选择,10MHz,2MHz,50MHz,使用如下
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//GPIO_Speed_10MHz,GPIO_Speed_2MHz,GPIO_Speed_50MHz
- GPIO_Mode可以设置引脚的工作状态,共有8种
GPIO_Speed | 描述 |
---|---|
GPIO_Mode_AIN | 模拟输入 |
GPIO_Mode_IN_FLOATING | 浮空输入 |
GPIO_Mode_IPD | 下拉输入 |
GPIO_Mode_IPU | 上拉输入 |
GPIO_Mode_Out_OD | 开漏输出 |
GPIO_Mode_Out_PP | 推挽输出 |
GPIO_Mode_AF_OD | 复用开漏输出 |
GPIO_Mode_AF_PP | 复用推挽输出 |
一般来说,输出设置推挽输出即可,
推挽输出高电平低电平都有供应能力
开漏输出高电平处于高阻抗状态没有供电能力,低电平有供电能力
综上,GPIO的初始化代码一般为:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIOA的时钟
GPIO_InitTypeDef GPIO_InitStructure;
//创建一个GPIO_InitTypeDef 类型的结构体GPIO_InitStructure,初始化所有值
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//选择推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;//使能全部GPIOA的16个引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//频率设置为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
2. 函数GPIO_SetBits与GPIO_ResetBits
GPIO_SetBits是设置数据的端口位,高电平,GPIO_ResetBits是清除数据的端口位,低电平
参数1 | 参数2 |
---|---|
GPIOx:x 可以是 A,B,C,D 或者 E,来选择 GPIO 外设 | GPIO_Pin |
3. 函数GPIO_WriteBit
GPIO_WriteBit是设置或清除数据的端口位,增加了一个参数,相当于聚合了👆面的两个
参数1 | 参数2 | 参数3 |
---|---|---|
GPIOx:x 可以是 A,B,C,D 或者 E,来选择 GPIO 外设 | GPIO_Pin | 该参数必须取枚举 BitAction 的其中一个Bit_RESET;Bit_SET: |
所以 |
//这两行语句是完全等价的
GPIO_ResetBits(GPIOA, GPIO_Pin_0);
Delay_ms(500);
GPIO_SetBits(GPIOA, GPIO_Pin_0);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
Delay_ms(500);
4. 函数GPIO_Write
做流水灯的代码里用过,如下👇
while (1)
//端口数据寄存器是一个16位的数,每一位都对应着一个端口(IO口)
//~是因为这里采用的是低电平的时候等才能亮,所以要取反
GPIO_Write(GPIOA, ~0x0001); //0000 0000 0000 0001
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0002); //0000 0000 0000 0010
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0004); //0000 0000 0000 0100
Delay_ms(100);
//也可以采用一行语句,效果是一样的
GPIO_Write(GPIOA, ~0x0001|~0x0002|~0x0004); //0000 0000 0000 0111
Delay_ms(100);
4. C语言基础补齐(宏定义、数据类型、typedef结构体、枚举)
STM32入门教程-2022持续更新中_江科大自化协 P3-3
讲的非常明白,但一会儿就去吃饭了,简单写写
4.1 宏定义
简单的说,就是取了个外号,常用经常修改的参数,如果用数字来写的话,每次修改都需要频繁的查找,如果用字符串
在前面定义这个参数,那就只需要改动一次就行,并且字符串
也更能增加函数的可读性,如
define Speed 100
//定义Speed这个单词和100等价
4.2 数据类型
4.3 typedef
引用课程的ppt👇
关键字:typedef
用途:将一个比较长的变量类型名换个名字,便于使用
定义typedef:
typedef unsigned char uint8_t;
引用typedef:
uint8_t a; //等效于unsigned char a;
4.4 结构体
类比数组,这是一个可以涵盖多种数据格式的新格式
关键字:struct
用途:数据打包,不同类型变量的集合
定义结构体变量:
structchar x; int y; float z; StructName;
因为结构体变量类型较长,所以通常用typedef更改变量类型名
引用结构体成员:
StructName.x = 'A';
StructName.y = 66;
StructName.z = 1.23;
或
pStructName->x = 'A'; //pStructName为结构体的地址 pStructName->y = 66;
pStructName->z = 1.23;*
4.5 枚举
关键字:enum
用途:定义一个取值受限制的整型变量,用于限制变量取值范围;也被可以认为是宏定义的集合,如果赋给某种枚举类型变量的值不在限制里,会有warning
定义枚举变量:
enumFALSE = 0, TRUE = 1 EnumName;
因为枚举变量类型较长,所以通常用typedef更改变量类型名
引用枚举成员:
EnumName = FALSE;
EnumName = TRUE;
以上是关于stm32入门第二天环境搭建RCC时钟GPIO闪烁实验与有源蜂鸣器实验的主要内容,如果未能解决你的问题,请参考以下文章
stm32入门第二天环境搭建RCC时钟GPIO闪烁实验与有源蜂鸣器实验
MDK,关于 STM32F4 配置失败, GPIO, USART 写入值没反应