STM32之LED配置

希望每天都能有所收获鸭~


最近准备开始学习stm32,当然51的学习也会一起进行,如开头所讲,希望每天都能有所收获吧!!!菜鸟思维,写的可能会有一点繁琐,但是我觉得学习是要一步一步来的,也希望自己可以把每一点都弄懂,嗯,就是这样


开始学习之前当然要先搭建好学习环境,关于软件的下载以及工程搭建,CSDN上有很多博主写的都很详细,下面给出两篇参考博客,也是我在学习过程中借鉴的博客(博主写的可以说超级详细了):


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编程的两种方法:
  1. 配置寄存器法:
    在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位

  1. 调用库函数法:
    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取反的操作~~~

  • 8
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ReRrain

觉得写的不错,不妨请我喝杯~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值