历史上的今天
返回首页

历史上的今天

今天是:2024年08月27日(星期二)

正在发生

2020年08月27日 | STM32之LED配置

2020-08-27 来源:eefocus

最近准备开始学习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编程的两种方法:

  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取反的操作~~~

推荐阅读

史海拾趣

Alpha (Taiwan)公司的发展小趣事

Alpha (Taiwan)公司自创立之初,便致力于电子技术的研发与创新。面对日益激烈的市场竞争,公司不断投入资金,引进先进设备,吸引了一批优秀的研发人才。这些人才凭借深厚的专业知识和敏锐的市场洞察力,成功开发出一系列具有竞争力的电子产品,如高性能的芯片、精密的传感器等。这些产品的推出,不仅提升了公司的市场地位,也为公司的快速发展奠定了坚实基础。

Avel Lindberg公司的发展小趣事

面对全球环保意识的日益增强,Alpha (Taiwan)公司积极响应号召,致力于绿色电子产品的研发和生产。公司投入大量资金研发环保材料和技术,成功推出了一系列绿色环保电子产品。这些产品不仅具有优异的性能,而且在使用过程中对环境的影响较小,符合现代社会的环保理念。此外,公司还积极参与环保公益活动,宣传环保知识,推动电子行业的绿色发展。

Anderson Power公司的发展小趣事

随着全球电子市场的不断扩大,Alpha (Taiwan)公司积极寻求国际合作,拓宽市场渠道。公司与多家国际知名电子企业建立了战略合作关系,共同研发新产品,开拓新市场。此外,公司还积极参加国际电子展会,展示公司的最新技术和产品,吸引更多的潜在客户。这些国际合作的开展,不仅提升了公司的国际影响力,也为公司的长远发展注入了新的动力。

BH Electronics公司的发展小趣事

近年来,随着环保意识的提高,BH Electronics积极响应国家绿色发展的号召,开始了绿色转型之路。公司加大了对环保技术的研发和应用力度,推出了一系列绿色环保产品。同时,BH Electronics还优化了生产流程,减少了能源消耗和废物排放。这些举措不仅提升了公司的环保形象,也为公司的可持续发展注入了新的动力。

这五个故事只是BH Electronics发展历程中的一部分,但它们却生动地展现了这家公司在电子行业中的崛起之路。从初创时期的筚路蓝缕,到技术创新的突破;从国际化战略的拓展,到品质管理的提升;再到绿色发展的转型,BH Electronics始终保持着敏锐的市场洞察力和不懈的创新精神。正是这些因素的共同作用,使得BH Electronics能够在激烈的市场竞争中脱颖而出,成为电子行业中的佼佼者。

东通电子公司的发展小趣事

东通电子深知人才是企业发展的关键因素。因此,公司一直致力于引进和培养人才,建立了一支高素质、专业化的团队。公司现有员工550人,其中技术人员31人,质量管理人员27人,研发团队12人。这些人才为公司的发展提供了有力的支持,也为公司的技术创新和品质提升奠定了基础。

以上是关于东通电子在电子行业中发展起来的相关故事概述。这些故事展示了东通电子在品质、技术创新、生产规模、环保和人才建设等方面的努力和成就。

Falco Electronics公司的发展小趣事

随着公司的发展,Falco Electronics开始积极拓展市场。公司不仅在国内市场取得了显著成绩,还积极开拓国际市场。同时,Falco Electronics还与其他行业领军企业开展战略合作,共同开发新产品、拓展新市场。这些合作不仅为公司带来了更多的商机,也提升了公司在行业内的地位和影响力。

问答坊 | AI 解惑

Verilog HDL 高级数字设计源码

Verilog HDL 高级数字设计源码…

查看全部问答>

初学者咨询,用dsp做东西需要哪些装备啊?

各位高手指点一下,我需要用dsp做东西,介绍一下工作流程及其需要哪些软硬件,谢了啊…

查看全部问答>

有偿求助,MCP2510驱动

内核为Linux2.6.8.1 CPU为S3C2410 价格好说 联系QQ:195550435…

查看全部问答>

常见的信息终端有哪些?

常见的信息终端有哪些? 请大侠们告知?…

查看全部问答>

6410串口COM2,3都不通?

友坚的UT-6410的开发板,GPIO通过驱动初始化后都已经写寄存器配置成串口模式了,但COM2,3用串口调试助手发送都没有信号,更不用说接受了,我用自发自收23脚相连,也没信号,请大侠帮忙看看怎么回事?…

查看全部问答>

[请问] 如何在VxWorks下开发IEEE 1394转PCI卡的驱动

转接卡用了三个芯片:TSB41AB3,M4LV -10VC -12VI和TSB12LV26,看着PCI和IEEE 1394的协议,就是不知道如何下手写这种转接卡的驱动,很郁闷,还请高手多多指点,谢谢!…

查看全部问答>

关于avr的晶振问题

本人初学avr,型号是atmega16,今天在做实验时遇到了一个问题 本人是照着叶大鹏的《十天学会avr单片机》视频学习的,他里面用到了一个延时函数,delay(),他延时的时间是delay(500),我也跟着他写了一个同样的函数,参数也是500,但是惊奇的发 ...…

查看全部问答>

基于载波通信的油井井底参数采集系统设计

基于载波通信的油井井底参数采集系统设计,这样的毕业设计该怎么做啊 大神们给个思路吧…

查看全部问答>

感受指尖的科技:Atmel触摸技术展现如何变革消费产品

触摸技术是智能手机“发家致富”的灵魂, 触摸技术是消费电子与人连接的重要环节, 触摸技术似乎走到了一个瓶颈,其实它的发展从未停止, 触摸技术又一直在我们身边,让我们享受指尖的科技。 先来看看几个最新的触摸技术实践! 以maXTouch驱 ...…

查看全部问答>