当前位置: 首页 > article >正文

[STM32]从零开始的STM32 LED教程(小白向)

一、为什么LED会作为第一个例程

        大家可能已经发现了,我们大部分的STM32教程都将LED作为教程中的第一个例程。为什么呢?在我看来,之所以把LED作为教程的第一个例程,因为这个实验能够让新手直观的看到实验现象,在操作GPIO的同时对STM32有更进一步的理解,所以,我也不例外,将STM32点亮一个LED作为第一个教程。这次教程中,我会教大家如何使用之前创建的初始工程来进行GPIO的操作从而点亮一个LED。这次教程涉及到的东西会比较多,我不仅会教大家如何点亮一个LED,并且还会教大家如何下载程序,以及在程序下载时遇到问题应该怎么解决,STM32锁了应该怎么解决。如果你准备好了,那我们就开始吧!

二、需要准备什么?

        在这次的实验中,你需要准备一个STM32的最小开发板,如图中所示,我们既然要学习STM32当然需要一个开发板来观察现象,你可以使用STM32F103C8T6或者STM32F103C6T6,它们的程序基本互通,但是在实际开发中,不同单片机的程序不能直接使用,尽管你下载和运行都没有问题,但这依然是不被允许的。下图所示,就是我们STM32的最小系统板:

你还需要准备一个已经搭建好的STM32F1的标准库开发环境,如果你还不会搭建环境,那么可以参考下面的文章:

STM32标准库环境搭建:[STM32]从零开始的STM32标准库环境搭建(小白向)_添加stm32-CSDN博客

这里我将本次实验能用到的资料已经打包整理到百度网盘,大家自行下载。如果你是新手,我还是强烈建议你下载我给出的资料,虽说这些资料在官网或者网络上都有。但在你刚开始学习的时候,我并不推荐你把太多的精力用花在找资料上:

LED教程资料:https://pan.baidu.com/s/1Wutlt1KYF45n9FTIzAbEBQ?pwd=clxm 
提取码:clxm

当你准备好STM32的最小版和开发环境以后,就可以进行下一步了。

三、编写一个点亮LED的程序

        这里编写程序我会使用两种方式,一种是通过控制寄存器来点亮一个LED,另一种是通过库函数来点亮一个LED。如果你是新手,你可以把寄存器的方式当作一个了解,等你学习了一段时间以后再去深究,这里讲寄存器的控制方式也只是为了教大家怎么去翻阅手册。在后面的开发中,我们有些地方可能会用到寄存器,但是不会作为主要的形式。下面我们来了解一下怎样才能点亮一个LED。为了学习如何点亮一个LED,我们可能需要一点电学知识,如下图,这是我们的一个LED的电气符号,当然,实际的LED不长这样。

我们现在来介绍以下LED的基本概念,LED的全称是“发光二极管”,所以它说白了也是一个二极管,它具有二极管的特性,比如它同样具有“正向导通,反向截止”的特性。也就是说我们给它加上正向电压时,它就会导通,给它加上反向电压时,它就会截止。如图中LED所示,我们规定,左端,也就是三角形大的一端表示正极,右端,也就是三角形指向的并且有一根竖线的一端为负极,所以,如果我们给LED像下图这样加电压,那么它就会导通,LED一旦导通并且电流达到额定值它就会发光:

VCC在这里充当的是我们的电源正极,GND在这里充当的是我们的电源负极,这样一来,LED的正接到了正,负接到了负,它就导通了。我们下面来看看LED截止的电路模型:

这次我们将电源正极接到了LED的负极上,电源负极接到了LED的正极上,这样的LED是不会导通的。以上就是LED通电发光的基本原理了,当然,这些是非常浅显的,如果你想了解更多半导体的知识还请查阅别的文章。

下面是一个LED发光电路的正确模型:

这里我们将电源正极经过一个300欧姆的电阻接到了LED的正极,LED的负极直接接到电源负极。这个电阻被我们叫做限流电阻,它是为了防止LED因为电流过大而烧毁。这也是最常见的LED电路模型。这个电阻在实际的电路设计中也是必须的。

学习了LED的基本知识,下面我们来查看一下我们STM32最小板上的LED接到了哪里,我们应该怎么点亮。可以将我给的资料进行解压,得到以下文件夹,在文件夹中就有一个“最小板原理图.jpg”的文件。

这里要注意的是,如果你的最小板样式和我最开始的一样,那么你就可以使用这张原理图。如果你的最小板不像这样,那你可以找商家要原理图。我们现在将原理图打开,看到LED有关的部分:

被我框出的地方就是整个最小板的LED部分了,我们可以放大一点来分析:

我们首先看到上面的LED,可以观察到这个LED的正极是直接接到了电源的正极,它的负极通过了一个510欧的电阻接到了电源的负极,这里的限流电阻从正极接和从负极接都无所谓。也就是说这个LED在我们通电时它就会亮,这个LED就是我们的电源指示灯。

我们再来看下面的LED,同样的这个LED的正极直接接到了电源的正极,负极通过一个510欧的电阻接到了PC13上,PC13是什么呢?我们在原理图中寻找一下:

是的,PC13是我们芯片上的一个引脚,我们的PC13是一个网络标签,表示这两个地方是连接到一起的。也就是说,我们的LED的负极经过了一个电阻接到了我们的STM32上。我们想让这个LED发光,就必须让STM32的PC13引脚输出一个负极的电压。接下来我们引入电平的概念。在数字电路的TTL电平中,我们规定电源电压在0v-5v,并且我们将高于2.7v的电压称为高电平,低于0.5v的电压称为低电平,我们的STM32就是一个标准的TTL器件,它能够输出TTL电平。在STM32中,如果让引脚输出高电平,那么引脚的电压就等于或者接近电源电压,这里的电源指的是STM32片上供电电源。如果让引脚输出低电平,那么引脚的电压就等或者接近于0。所以我们如果想让这个LED亮起来,我们需要让PC13引脚输出一个接近于0的电压,也就是低电平。

我们可以看到我们的LED就在我们开发板的如下图指示位置:

当我们给开发板通电,我们发现,开发板的电源指示LED亮起,接在STM32 PC13口的LED不亮,我们现在就需要使用代码使这个LED点亮。下面我会使用操作寄存器和使用库函数两种方法来驱动LED。对于新手来说,操作寄存器作为了解即可。下面我们分情况讨论:

1.操作寄存器点亮一个LED

        我们首先要打开我们一开始创建的STM32标准库工程,如果你没有创建完成,可以去看我以前的文章。如果你反复创建失败,也可以打开我给的资料中的工程文件夹,里面有这一次实验会使用到的工程模板,当然也有我编写好的工程。大家如果使用自己已经创建好的工程,可以新建一个文件夹,将原本工程内的文件复制一份到这个文件夹,并且将文件夹命名为本次实验的名字。这里我在桌面上新建一个“LED”的文件夹:

我们将工程模板中的文件都复制过来:

在完成以后,我们在LED的文件夹打开工程。

打开工程以后,我们进入“main.c”就可以开始写程序了。

我们操作寄存器,首先就需要打开我们STM32F1的寄存器手册,手册我放在了本次下载的资料下,如果你想查看,你可以打开“STM32F10xxx参考手册(中文).pdf”文件。我们点亮一个LED只需要使用到3个寄存器。我们首先看到RCC相关的寄存器。我们STM32的GPIOC口被挂载在了APB2总线上,我们看到相关的配置寄存器。

配置GPIOC的时钟我们要使用到“APB2ENR”寄存器。我们可以看到“APB2ENR”的第四位负责了GPIOC的时钟,我们只需要将“APB2ENR”的第四位配置为1即可。

转换为16进制就是“0x00000010”,在程序中就像下面这样写:

RCC->APB2ENR=0x00000010;

我们继续来配置端口模式寄存器,我们下面看到“GPIOx_CRH”寄存器,这个寄存器就用于配置GPIO的模式寄存器。这里的“GPIOx_CRH”是对GPIO口的高八位进行配置,“GPIOx_CRL”是对GPIO端口的低八位进行控制,这里的x在手册中也提到了,是选择哪一个GPIO口。

我们这里要配置GPIOC的输出模式和最大速度,我们就要配置“GPIOx_CRH”寄存器的20-23位。我们将其配置位推挽输出模式,并且最大速度50MHZ。所以这里“GPIOx_CRH”的值我们要配置为“0x00300000”,写在程序中就是:

GPIOC->CRH=0x00300000;

我们将GPIO的时钟和输出寄存器配置好以后,就可以开始控制GPIO输出了,我们这里看到控制GPIO控制输出的寄存器,也就是我们的“GPIOx_ODR”寄存器。

我们只需要将“GPIOx_ODR”寄存器的13位写为0,GPIOC13就能输出低电平了,之前我们看原理图也发现了PC13口只要给低电平,LED就可以亮起,当然,我们也可以直接将整个寄存器写成0,写在程序中如下:

GPIOC->ODR=0x00000000;

至此,我们的STM32寄存器控制LED程序就已经完成了,下面是完整的“main.c”中的程序:

#include "stm32f10x.h"                  

int main(void)
{
	RCC->APB2ENR=0x00000010;
	GPIOC->CRH=0x00300000;
	GPIOC->ODR=0x00000000;
	while(1)
	{
		
	}
}

大家可以将其复制到自己的“main.c”中进行测试。我们将代码编译,不出意外的话应该是零错误,零警告。

大家可以查看hex文件有没有正常生成。如果没有生成可以查看我们之前新建标准库工程的文章,查看如何生成hex文件。这个hex文件我们后续的烧录会使用到,当然,现在我们不讲烧录。我们将下面的标准库的操作方法讲完以后,我们才会讲如何烧录程序。

大家应该也发现了,寄存器控制GPIO口输出电平的方法非常复杂,并且我们在编写寄存器相关程序时,我们需要反复翻阅手册,如果程序没有注释,可读性是非常低的。所以,如果你作为一个新手,我并不推荐你一开始就学习寄存器。我们下面会讲使用标准库进行开发,这是一种非常易用并且高效的开发方式。

2.使用标准库点亮一个LED

        在开始之前,我们仍然需要将原本的工程模板复制一份出来,放在一个单独的文件夹中。这是一种很好的习惯,能够让我们不断累积自己的代码库。现在让我们继续吧,将工程复制完成以后,我们直接打开工程并来到“main.c”文件:

我们使用库函数控制GPIO引脚同样需要先使能引脚的时钟,我们使能GPIOC的时钟可以使用下面的函数进行:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);

这里的“RCC_APB2Periph_GPIOC”就表示了我们要操作GPIO的时钟,后面的“ENABLE”表示使能,这两个都是函数“void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)”的参数。如果你想知道一个函数有哪些参数,你可以右键这个函数,然后点击“Go to.......”

这里有我们函数的简单介绍,以及函数传入参数和返回值的描述:

在我们开发过程中,我们要经常性的去看一个函数的参数和返回值。

当我们打开GPIOC的时钟以后,就可以开始配置GPIOC的模式和输出速度了。我们配置GPIO的模式和输出速度经常会采用“void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)”函数,如果你不知道一个函数的参数,可以把这个函数先写出来,再使用“Go to......”跳转到函数定义去查看参数。

我们可以看到这个函数第一个参数要我们选择要配置哪一个GPIO,第二个要的是“ GPIO_InitTypeDef”类型的一个结构体指针,在很多函数库中都会使用结构体来传递参数,我们一般是先修改结构体内部参数的值再将结构体一次性传入函数。我们可以先使用下面的代码定义一个“ GPIO_InitTypeDef”类型的结构体:

GPIO_InitTypeDef GPIO_InitStructTypeDef;

我们下面开始往结构体中装入参数:

GPIO_InitStructTypeDef.GPIO_Mode =GPIO_Mode_Out_PP;
GPIO_InitStructTypeDef.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructTypeDef.GPIO_Speed = GPIO_Speed_50MHz;

这里我们通过修改结构体成员的方式来往结构体中装入参数,我们将GPIO端口模式配置为推挽输出模式,端口我们选择的13,端口最大速度我们配置为了50MHZ。

当我们准备好结构体以后,就可以使用“GPIO_Init()”函数了。代码如下:

GPIO_Init(GPIOC,&GPIO_InitStructTypeDef);

这里函数的第一个参数为选择的GPIO口,我们选择的GPIOC口,后面要求传入一个结构为类型的指针,所以我们这里要对我们自己创建的结构体取地址。

至此,我们已经将GPIOC的时钟打开,并且已经配置了输出模式和最大速度。我们下面就可以来控制GPIOC13口的电平了。我们可以使用下面的命令将GPIOC13的电平置为低电平:

GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);

这里的参数GPIOC仍然表示我们选择哪一个GPIO口,后面表示我们选择的GPIO口的引脚,最后一个参数表示我们要将这个引脚置高电平还是低电平,这里的“RESET”是一个宏定义,表示低电平。

下面是完整的“main.c”代码:

#include "stm32f10x.h"                  

GPIO_InitTypeDef GPIO_InitStructTypeDef;

int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
	
	GPIO_InitStructTypeDef.GPIO_Mode =GPIO_Mode_Out_PP;
	GPIO_InitStructTypeDef.GPIO_Pin = GPIO_Pin_13;
	GPIO_InitStructTypeDef.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC,&GPIO_InitStructTypeDef);
	
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);
	while(1)
	{
		
	}
}

我们同样将代码编译。应该是没有错误也没有警告的:

在编译出hex文件以后,程序编写和编译的工作就完成了。大家可以发现,虽然标准库开发的语句多了许多,但是每条语句都有自己独特的意思,让我们的代码有迹可循。

四、程序下载与工程测试

        做了上面那么多,我们总算是可以开始下载程序了,下载程序这个地方有很多坑,有时候也会下载不成功。下面我会教大家使用ST-Link下载程序和使用串口下载程序。这两种程序下载方式都有自己的优缺点,我会详细说明。下面我们分情况讨论:

1.使用ST-Link下载程序

        下面我来给大家讲解如何使用ST-Link给STM32下载程序,这种下载方式也是作为我们STM32非常常见的一种下载方式。在这种下载方式下,你需要拥有一个ST-Link下载器用于下载程序,目前价格在10块左右建议大家买贵一点的ST-Link,这样可以避免很多因为硬件引起的不能下载的问题,下面我们将ST-Link按照下面的方式进行连接:

这里注意我们的ST-Link有两排排针对应了两排名字,左边一列的名字对应的是上面的排针,右边一列的名字对应的是下面的排针,我们要用的接口一般都在下面的排针。确定好以后,我们将“SWCLK”“SWDIO”“3.3V”“GND”连接起来,有时“SWCLK”也会直接写成“CLK”,“3.3V”可能会写成“3V3”。这些引脚的表述方式不同,但是都表示的是同一个引脚。大家在连接的时候需要注意,不要将VCC和GND接反了,一定要多检查几遍再上电。在连接好上电以后我们的电源指示灯会亮起,如果你上电以后,电源指示灯没有亮起,你要马上将其从电脑上拔出并且检查接线是否正确。

当你正确上电以后,STM32的最小系统板的电源指示灯会亮起,我们就可以准备开始下载程序了。

我们回到keil中,点击魔术棒:

随后点击“Debug”:

我们将这里的下载器改成“ST-Link”

在换好了以后,我们点击右边的“Settings”:

我们可以看到这里已经出现了ST-Link的ID:

这里需要注意的是,只有出现ST-Link的ID以后才算连接成功了,如果没有ID,表示接线或者驱动有错误。这里还请大家自己检查,如果你怀疑驱动有错误,你可以将ST-Link插在电脑上,然后不接任何外围设备,随后打开我给的资料中的“ST-Link驱动”文件夹,

这里的驱动资料由正点原子整理,里面也有驱动更新的教程,大家跟着教程自行安装或者更新ST-Link的驱动。如果在安装完驱动以后keil中仍然找不到ST-Link的ID,就可以考虑一下接线是不是有问题,如果接线也没有问题并且驱动已经正确安装,那么就需要考虑检查一下是不是ST-Link本身的问题。如果你ST-Link一直识别不到,那么就需要考虑一下使用串口下载程序。

当你的ST-Link正确识别以后,我们可以点击这个窗口中的“Flash Download”:

如果你这里不像我一样有一个下载协议,那么你就需要自己点击“Add”添加一个下载协议。完成以后点击确定即可。

确定以后,后面的窗口都一路确定下来,好了,现在我们就可以开始烧录程序了。

在代码编译以后,我们点击图中所示的烧录按钮:

点击了以后,会输出下面的信息:

如果你的ST-Link像我描述的那样配置正确的话,都是可以烧录成功的。

下面我来教大家如何使用串口烧录程序。

2.使用串口下载程序

        大家可能已经发现了,使用ST-Link烧录程序非常方便,那么,我们为什么还要使用串口来烧录呢?其实串口烧录是针对极少数情况,比如我们的ST-Link无法烧录,或者是我们的芯片锁了,这种时候,就需要使用串口进行烧录。我们要使用串口下载程序,我们首先需要一个USB转TTL电平的转换模块,我这里使用的是CH340这也是目前比较常见的USB转TTL模块,其次我们还需要给自己的电脑安装一个CH340的驱动,这样我们电脑才能够识别:

我们首先打开我给的资料,内部有一个文件夹名为“串口下载”打开看到以下文件和文件夹:

我们首先进入“CH340驱动”文件夹:

点击“SETUP.EXE”启动安装程序:

在这个安装程序中,不管你以前有没有安装过,都先点击卸载,再点击安装。如图所示已经安装成功了:

我们再驱动安装成功以后直接关掉这个页面即可。如果在你安装完驱动以后,在后面的步骤中依然找不到CH340,你可以考虑进入错误处理办法那个文件夹,将CH341的驱动压缩包解压并安装CH341的驱动

下面我们来连接STM32与串口,我们需要按照PA10连接串口的TX,PA9连接串口的RX,VCC连接VCC,GND连接GND的方式进行连接。大家注意不要将正负接反或者将数据线接反。再连接好以后,将CH340插在电脑上,观察电源指示灯是否亮起,如果电源指示灯不亮你需要马上拔出随后检查接线是否正确。

我们要使用串口给STM32下载程序,我们需要进入STM32的“系统存储器”模式,我们可以通过切换跳线帽的方式切换STM32的模式,就是图中的:

我们将BOOT0跳到1,就进入“系统存储器”模式了,在这期间,我们的BOOT1不动。再跳线帽跳过去以后,重新给STM32上电,就成功进入“系统存储器”模式了。重新上电这个步骤是必须的。

我们再连接好串口线,并且已经将BOOT0的跳线帽跳到1的时候就可以开始使用串口下载程序了。我们打开“串口下载”文件夹中的“FlyMcu.exe”:

我们进来以后,先点击搜索串口:

点击了“搜索串口”以后,这里应该不会有响应,我们再点击旁边的“Port”,我们选择我们的CH340这个串口:

如果你这里没有CH340串口,你就需要考虑一下,是不是340应该问题。

在选择好CH340以后,我们就可以点击“读硬件信息”:

我们可以看到这里已经读取到了硬件信息和芯片的ID号。

我们在“联机下载程序文件”处选择我们的编译后的hex文件。

选择好以后点击“开始编程”,小等一会儿就可以看到编程成功了:

这个时候我们将原本BOOT0跳回0;随后再上电,我们的LED应该就可以亮起了。

五、结语

        如果你是一个新手,点亮一个LED这个初始例程对你来说是非常复杂的,本次教程的内容也是相当的多,大家自行吸收。感谢大家观看!


http://www.kler.cn/a/289342.html

相关文章:

  • Python 连接 Redis 进行增删改查(CRUD)操作
  • 微服务架构面试内容整理-API 网关-Gateway
  • jmeter常用配置元件介绍总结之后置处理器
  • JQuery封装的ajax
  • C++,STL 054(24.11.13)
  • 事件循环 -- 资源总结(浏览器进程模型、事件循环机制、练习题)
  • 第十周:机器学习笔记
  • 微信小程序代码 app.json文件详细介绍
  • Apifox使用学习
  • 【华为OD】2024D卷——剩余银饰的重量
  • [CISCN2019 华东南赛区]Web111
  • Java面向对象与继承
  • 【C++】手动实现队列的封装(C++)
  • 基于纠错码的哈希函数构造方案
  • 977.有序数组的平方
  • 边缘计算工业网关可以为工业企业生产提供哪些价值应用?天拓四方
  • 如何禁用USB存储设备|禁用USB储存和连接手机的方法有哪些?深度解析,四招搞定!
  • Kafka:浅谈对Kafka的认识
  • spring之bean和配置相关注解
  • 论文解读:Prompt-aligned Gradient for Prompt Tuning
  • 论文《Improving your graph neural networks:A High-Frequency Booster》笔记
  • 构造+模拟,CF 873D - Merge Sort
  • 水平垂直居中的方式
  • Nginx - Rewirte
  • 【GPT】Coze使用开放平台接口-【5】API 调用
  • 15、Django Admin添加自定义字段功能