【stm32入门】第二天环境搭建、RCC时钟、GPIO、闪烁实验与有源蜂鸣器实验

学习参考:STM32入门教程-2022持续更新中_江科大自化协P3-1~3-3
这两天学的稀里糊涂,这里看一点那里看一点,最后什么也没搞明白,为了电赛净选件但却发现最基础的32还没搞太懂,今天难得清闲,把视频重新看了一遍,觉得收获颇丰,遂开始重新记录笔记。
今日收获:LED闪烁实验、有源蜂鸣器实验
电赛倒计17天

  • 开始之前

基础部分全部看完才发现stm32并没有我想象的难,其实流程上和arduino都是一样的,只是自己需要配置的东西变多了,需要很详细的初始化和 使用,而不像arduino那样只需要简单的初始化,但是这也是arduino的弊病,如果想要更改默认的参数会让你感到很迷糊,这可能是stm32做的好的地方。
代码的基础流程:开启时钟👉初始化引脚👉在死循环使用引脚

在平衡车的教学中,范学长直接把各个元件的初始化都包装到其他C文件和.h文件中,修改定义也要到那里去修改,这可能让老手很方便操作和修改,但是让刚入门的我在跳来跳去的过程中感到迷茫,在👆面的教程中,基本上所有代码都是在main函数中写出的,可能不是那么方便管理,但是让我感受到arduino书写代码时候的熟悉感,一种莫名的熟悉感,希望它能帮助我学的更快吧。

一、配置环境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 外设时钟
输入参数 1RCC_AHB2Periph: 门控 AHB 外设时钟
功能描述NewState:指定外设时钟的新状态 。这个参数可以取:ENABLE 或者 DISABLE
输出参数
返回值
先决条件
被调用函数

Table 373.RCC_AHB2Periph 值

RCC_AHB2Periph描述
RCC_APB2Periph_AFIO功能复用 IO 时钟
RCC_APB2Periph_GPIOAGPIOA 时钟
RCC_APB2Periph_GPIOBGPIOB时钟
RCC_APB2Periph_TIM1TIM1 时钟
RCC_APB2Periph_SPI1SPI1 时钟

省略了好多值,用到了再查吧
当某个库函数需要被调用函数为时钟函数时,把他使能就好了,大部分的都需要

三、通用输入/输出(GPIO)

GPIO 库函数常用的筛选

函数名描述
GPIO_Init根据 GPIO_InitStruct 中指定的参数初始化外设 GPIOx 寄存器
GPIO_StructInit把 GPIO_InitStruct 中的每一个参数按缺省值填入
GPIO_ReadInputDataBit读取指定端口管脚的输入
GPIO_ReadInputData读取指定的 GPIO 端口输入
GPIO_ReadOutputDataBit读取指定端口管脚的输出
GPIO_ReadOutputData读取指定的 GPIO 端口输出
GPIO_SetBits设置指定的数据端口位
GPIO_ResetBitsits 清除指定的数据端口位
GPIO_WriteBit设置或者清除指定的数据端口位
GPIO_Write向指定 GPIO 数据端口写入数据
GPIO_PinRemapConfig改变指定管脚的映射(复用其他功能)
GPIO_EXTILineConfig选择 GPIO 管脚用作外部中断线路
具体使用方法参考库函数,只说几个用到的

1. GPIO_Init

函数名GPIO_Init
功能描述根据 GPIO_InitStruct 中指定的参数初始化外设 GPIOx 寄存器
输入参数 1GPIOx:x 可以是 A,B,C,D 或者 E,来选择 GPIO 外设
输入参数 2GPIO_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 数据类型

c语言数据类型

4.3 typedef

引用课程的ppt👇
关键字:typedef
用途:将一个比较长的变量类型名换个名字,便于使用
定义typedef:

typedef unsigned char uint8_t;

引用typedef:

uint8_t a; //等效于unsigned char a;

4.4 结构体

类比数组,这是一个可以涵盖多种数据格式的新格式
关键字:struct
用途:数据打包,不同类型变量的集合
定义结构体变量:

struct{char 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
定义枚举变量:

enum{FALSE = 0, TRUE = 1} EnumName;

因为枚举变量类型较长,所以通常用typedef更改变量类型名
引用枚举成员:

EnumName = FALSE;
EnumName = TRUE;
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值