最近准备开始学习stm32,当然51的学习也会一起进行,如开头所讲,希望每天都能有所收获吧!!!菜鸟思维,写的可能会有一点繁琐,但是我觉得学习是要一步一步来的,也希望自己可以把每一点都弄懂,嗯,就是这样
开始学习之前当然要先搭建好学习环境,关于软件的下载以及工程搭建,CSDN上有很多博主写的都很详细,下面给出两篇参考博客,也是我在学习过程中借鉴的博客(博主写的可以说超级详细了):
https://blog.csdn.net/qq_34952376/article/details/81166033
https://blog.csdn.net/ReCclay/article/details/86616210
stm32编程方式有两种:一种是直接操作寄存器,另一种是配置库函数, emmm,感觉大多数情况下还是库函数比较好用,配置寄存器的话要记的东西比较多,感觉我也记不住,哈哈。但是关于寄存器的知识我们还是要了解的,具体知识可以参照《STM32中文参考手册》来学习,下面我们来说说怎么实现LED的配置的。
开始写配置LED的函数之前,我们还是和学习51时一样,需要先看一下原理图,明确一下LED的电路结构:
从原理图上我们可以看到:单片机的各个引脚是通过一个573锁存器和LED相连的,这个573我们在51里也很常见,需要注意的就是只有在使能573的情况下才能实现端口数据的传输,也就是说我们需要把N-LE对应的引脚拉高。
接下来我们找一下红线框部分对应的引脚(emmm,这里和51就不太一样,可以看一下图)
上面分别是J1和J2两个排针,上面的引脚是一一对应的,从开发板上我们也可以看到,这两个排针的对应引脚是用跳线帽连接在一起的(感觉很方便呀)
N-LE对应的是PD2,而D0到D7这八个LED分别对应PC8-PC15
那么LED的配置是配置什么呢?
引脚模式,也可以理解成一种初始化函数,具体步骤是:配置端口时钟(时钟使能),设置引脚号,设置引脚速率,配置端口模式,配置输出数据。
下面我们就按照步骤来一步一步完成LED的配置:
配置端口时钟
明确: STM32的GPIO外设是挂接在APB2总线上的,所以要完成使能我们就需要设置APB2外设时钟使能寄存器,这时候可以查阅手册看一下APB2外设时钟使能寄存器的相关知识:
图上红色线框部分是GPIO外设的相关时钟,而我们从原理图上可以得知,LED配置需要使能的时钟是:GPIOC(IO端口C)和GPIOD(IO端口D)
置1表示使能
下面我们用两种方法来实现一下时钟的使能,也顺便理解比较一下stm32编程的两种方法:
配置寄存器法:
在stm32f10x.h文件(库函数内)中我们可以找到外设时钟使能寄存器的相关定义:
RCC的声明,使用RCC_TypeDef类型指针对RCC端口时钟地址进行强制类型转换,也就是说把RCC_BASE强制转换成一个结构体指针,然后通过宏定义,替换成用RCC表示的,这样我们在结构体中定义的各个变量也就相应的移植到了RCC内部的地址空间。
好了,明确了上面的那些内容,我们就可以进行相应时钟(GPIOD和GPIOC)的使能了,GPIOC和GPIOD分别对应位4和位5,所以我们下面要做的就是让APB2外设时钟使能寄存器的位4和位5置1,看代码:
RCC->APB2ENR |= (1 << 4);//使能GPIOC时钟
RCC->APB2ENR |= (1 << 5);//使能GPIOD时钟
我们上面解释过了RCC是一个结构体指针,APB2ENG是这个结构体内部声明的一个变量,所以在调用时就需要用 “->” 这个符号,下面以使能GPIOC为例解释一下为什么可以实现位4置1:
先来看1 << 4:1用16进制表示出来是:00000001,左移四位变成了00010000;RCC->APB2ENR |= (1 << 4),APB2外设时钟使能寄存器的复位值是00000000,和00010000进行或运算,结果是:00010000,实现了位4置1,并且不改变其它位
注意:位是从0 开始表示的,所以位4实际上就是第5位
调用库函数法:
STM32有着非常好用的库函数,功能很全也很多,其中就有初始化时钟的函数,在stm32f10x_rcc.h文件中可以找到相关定义,然后可以点击函数名按快捷键F12,直接定位到函数体,然后我们就可以明白各个变量的含义了:
第一个变量表示使能哪一个时钟,NewState表示使能(ENABLE)还是不使能(DISABLE)
看代码:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC, ENABLE);//使能GPIOD和GPIOC
/*还可以分开写*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//使能GPIOC
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);//使能GPIOD
设置引脚相关:
引脚号,引脚速率,引脚模式,也就是初始化引脚配置,我们这里就直接用库函数配置的方法来做:
STM32的IO模式(引脚模式)有8种:模拟输入、浮空输入、上拉输入、下拉输入、通用推挽输出、通用开漏输出、复用推挽输出、复用开漏输出,这8种模式比较重要,想要详细了解的话,可以参照下面的博客:
https://blog.csdn.net/techexchangeischeap/article/details/72569999
此外输出模式还包括3种输出速率,emmm,可以想见我们的库函数里对于这一部分肯定也是用结构体封装的。
在stm32f10x_gpio.h文件里我们可以找到相关定义:
在stm32f10x_gpio.h文件里我们可以找到对应的端口引脚定义:
ok,现在我们来写引脚模式配置的部分,以GPIOD(PD2)为例说明:
思想就是:先定义一个GPIO_InitTypeDef类型的结构体变量,然后为这个结构体的各个变量赋值,然后再调用初始化函数
GPIO_InitTypeDef GPIO_InitStructure;//定义一个结构体变量
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//设置引脚号
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;//设置引脚速率10MHZ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//设置为通用推挽输出模式
GPIO_Init(GPIOD, &GPIO_InitStructure);//调用初始化函数,初始化引脚配置
关于初始化函数,在stm32f10x_gpio.h文件里可见定义,还是同样的操作,按快捷键F12,找到对应的函数体:
关于GPIOC相关引脚的配置,在设置引脚号时有技巧:
我们如果一个一个引脚定义的话,需要从PC8定义到PC15,太麻烦了,我们可以把对应的地址相加,得到结果是0xFF00,就实现了这8个引脚号的配置了:
配置输出数据:
说白了就是给我们上面定义的引脚赋一个初值(我们默认上电LED的状态是关闭的,所以这里要把相关引脚拉高),但是要注意LED相关引脚的赋值要在使能573的情况下进行,这里我们可以操作寄存器,也可以操作相应的库函数,emmm,前面对两种方法已经作了比较,这里就不过多说明,我觉得这里操作寄存器比较方便,就说下操作寄存器的方法吧:
这里就又涉及到了一个知识,就是GPIO端口寄存器的结构,读者可以在手册上查找到相关内容,这里我只说一下端口输出数据寄存器(要用到的):
这个部分和RCC时钟配置差不多,思想也是一样的,相关结构体的定义在stm32f10x,h文件里可以找到,下面贴出:
一样的思想,还是强制类型转换,通过宏定义将GPIOA等定义为和GPIO_TypeDef同类型的结构体指针看代码:
GPIOC->ODR |= 0xFF00;//将PC8-PC15引脚拉高
GPIOD->ODR |= (1 << 2);//拉高PD2,使能573
GPIOD->ODR &= ~(1 << 2);//关闭使能
下面是完整代码:
#include "stm32f10x.h"
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC, ENABLE);//使能GPIOD和GPIOC
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//设置引脚号
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;//设置引脚速率10MHZ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//设置为通用推挽输出模式
GPIO_Init(GPIOD, &GPIO_InitStructure);//调用初始化函数,初始化引脚配置
GPIO_InitStructure.GPIO_Pin = 0xFF00;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIOC->ODR |= 0xFF00;//将PC8-PC15引脚拉高
GPIOD->ODR |= (1 << 2);//拉高PD2,使能573
GPIOD->ODR &= ~(1 << 2);//关闭使能
}
完毕~~
emmm,再给一个测试例程吧,实现L1每隔1s闪烁:
#include "stm32f10x.h"
#include "led.h"
u32 TimingDelay = 0;
void Delay_Ms(u32 nTime);
//Main Body
int main(void)
{
SysTick_Config(SystemCoreClock/1000);
LED_Init();
while(1)
{
GPIOC->ODR ^= (1 << 8);
GPIOD->ODR |= (1 << 2);
GPIOD->ODR &= ~(1 << 2);
Delay_Ms(1000);
}
}
void Delay_Ms(u32 nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
解释一下 “GPIOC->ODR ^= (1 << 8);” 介个东东:
^异或符学过51的应该不陌生,很好用,这个异或是按位异或,对每一位都执行操作的,我们每隔1000ms让GPIOC->ODR中的数据和(1 <<8)相异或,也就是实现第8位每隔1s取反,视觉上就是L1每隔1s闪烁了:
GPIOC->ODR初始化数据:11111111
(1 << 8):10000000
按位异或 GPIOC->ODR ^= (1 << 8):01111111
实现了第8位每隔1s取反的操作~~~
上一篇:【STM32】HAL库 STM32CubeMX教程九---ADC
下一篇:STM32——GPIO设置:快速点亮第一个LED灯
推荐阅读最新更新时间:2024-11-12 19:00
设计资源 培训 开发板 精华推荐
- LT1026CN8 稳压转换器的典型应用电路
- 【实测成功】基于arduino UNO的扩展板
- STA333BW 2.1声道高效数字音频系统典型应用
- 【创意PCB】磁悬浮+离线语音磁吸月球灯遥控器
- LT1376CS8 1.5A、500kHz 降压型开关稳压器的典型应用电路
- LT6656AIDC-3.3、3.3V 电压基准作为微功率稳压器的典型应用
- 使用 Analog Devices 的 REF191 的参考设计
- LTC3623IUDD 5Vout、5A 轨至轨同步降压稳压器的典型应用电路
- 小台灯DIY
- NIOS-DEVKIT-1C20,Nios II 开发套件,Cyclone 版为基于 Altera Cyclone 器件开发嵌入式系统提供了一个硬件平台