++🎩 欢迎来到技术探索的奇幻世界👨💻++
++📜 个人主页++ :@一伦明悦-CSDN博客
++✍🏻 作者简介++ : C++软件开发、Python机器学习爱好者
++🗣️++ ++互动与支持++: 💬评论 👍🏻点赞 📂收藏 👀关注+
++如果文章有所帮助,欢迎留下您宝贵的评论,++
++点赞加收藏支持我,点击关注,一起进步!++
前言
STM32是一系列由STMicroelectronics开发的32位ARM Cortex-M微控制器系列,广泛应用于嵌入式系统中。它们提供了丰富的外设和性能,适用于各种应用领域,包括工业控制、汽车、消费电子等。STM32系列有多个产品系列,每个系列针对不同的应用需求提供了多种型号和配置选项。要对STM32有一个全面的总结,可以涵盖其主要特点、产品系列、应用领域、开发工具和生态系统等方面的信息。
代码实现资源链接
正文
01-LED灯1实现
当想要在STM32单片机上实现LED灯的闪烁时,可以遵循以下步骤:
初始化GPIO引脚:首先,需要初始化用于连接LED的GPIO引脚。这包括设置引脚的模式(输入/输出)、速度、上拉/下拉等。
配置定时器(Timer):使用一个定时器来生成定期的中断,以便控制LED的闪烁频率。可以选择适当的定时器和预分频器来生成适当的时钟频率。
编写中断服务程序(ISR):在定时器中断服务程序中,可以切换LED的状态,从而使其闪烁。可以在每次中断时切换LED的状态,或者根据需要计算适当的间隔。
编写主程序:在主程序中初始化所有必要的硬件和变量,并启动定时器。然后,可以让主程序进入一个无限循环,在循环中等待定时器中断。
编译和下载程序:最后,将程序编译为可执行文件,并通过调试器将其下载到STM32单片机中进行测试。
LED灯1实现
LED1.h文件:
这段.h文件是LED模块的头文件,用于声明LED相关的函数和变量。让我解释一下:
-
#ifndef __LED_H
和#define __LED_H
:这是头文件保护措施,确保在同一编译单元中只包含一次该头文件内容,防止重复定义。 -
void LED1_Init(void);
:这是LED1初始化函数的声明,告诉编译器该函数的存在和接口。 -
#endif
:结束头文件的定义。
这个头文件的作用是在其他源文件中包含它后,可以调用LED1_Init函数进行LED的初始化。
cpp
#ifndef __LED_H
#define __LED_H
void LED1_Init(void);
#endif
LED1.cpp文件:这段代码是用于在STM32F10x系列单片机上初始化一个LED(Light Emitting Diode)的函数。详细解释如下:
-
#include "stm32f10x.h"
:这行代码包含了STM32F10x系列的设备头文件,其中包含了该系列单片机的寄存器定义和常量声明等信息。 -
void LED1_Init(void)
:这是一个无返回值的函数,用于初始化LED。 -
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
:这行代码用于使能GPIOA的时钟。在STM32中,访问GPIO需要先使能相应的时钟。 -
GPIO_InitTypeDef GPIO_InitStructure;
:定义了一个结构体变量GPIO_InitStructure
,用于配置GPIO初始化参数。 -
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
:将GPIOA的引脚1配置为推挽输出模式。在这种模式下,GPIO引脚可以提供高电平和低电平输出。 -
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
:选择了GPIOA的引脚1作为LED连接的引脚。 -
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
:配置了GPIO的输出速度为50MHz。 -
GPIO_Init(GPIOA, &GPIO_InitStructure);
:根据上述配置初始化GPIOA的引脚1。 -
在注释中提到了两种驱动方式:
GPIO_ResetBits(GPIOA, GPIO_Pin_1);
:将GPIOA的引脚1输出低电平,LED熄灭。GPIO_SetBits(GPIOA, GPIO_Pin_1);
:将GPIOA的引脚1输出高电平,LED点亮。
这段代码的作用是初始化一个LED连接的GPIO引脚,配置为推挽输出模式,并设置输出速度为50MHz。
cpp
#include "stm32f10x.h" // Device header
void LED1_Init(void)
{
// 1、开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
// 2、调用Init函数
// 2-1、需要先进行结构体的定义
GPIO_InitTypeDef GPIO_InitStructure;
// 数据信号的推挽输出,这个时候STM32对高低电平拥有绝对的控制权,此时LED灯长脚插在PA0口,短脚插在负极,高电平驱动也可以闪烁
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 变成了OD就成了开漏模式,就无法高电平驱动了
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ; // 选择Pin_0是因为用的是GPIOA的0号引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 输出速度
GPIO_Init(GPIOA,&GPIO_InitStructure);
// 3、设置高电平,LED灯熄灭
//GPIO_ResetBits(GPIOA,GPIO_Pin_1);
//GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
02-LED灯2实现
LED灯2的实现如下:
LED2.h文件
这段.h文件是LED2模块的头文件,用于声明LED2相关的函数和变量。解释如下:
-
#ifndef __LED2_H
和#define __LED2_H
:这是头文件保护措施,确保在同一编译单元中只包含一次该头文件内容,防止重复定义。 -
void LED2_Init(void);
:这是LED2初始化函数的声明,告诉编译器该函数的存在和接口。 -
#endif
:结束头文件的定义。
这个头文件的作用是在其他源文件中包含它后,可以调用LED2_Init函数进行LED2的初始化。
cpp
#ifndef __LED2_H
#define __LED2_H
void LED2_Init(void);
#endif
LED2.cpp文件:这段代码是用于在STM32F10x系列单片机上初始化另一个LED的函数。解释如下:
-
#include "stm32f10x.h"
:同样是包含了STM32F10x系列的设备头文件,以便使用相关的寄存器定义和常量声明。 -
void LED2_Init(void)
:这是另一个无返回值的函数,用于初始化第二个LED。 -
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
:这行代码用于使能GPIOB的时钟,因为第二个LED连接在GPIOB上。 -
GPIO_InitTypeDef GPIO_InitStructure;
:定义了一个新的结构体变量GPIO_InitStructure
,用于配置GPIOB的初始化参数。 -
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
:同样将GPIOB的引脚1配置为推挽输出模式。 -
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
:选择了GPIOB的引脚1作为第二个LED连接的引脚。 -
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
:配置了GPIO的输出速度为50MHz。 -
GPIO_Init(GPIOB, &GPIO_InitStructure);
:根据上述配置初始化GPIOB的引脚1。
这段代码的作用与之前的LED1初始化函数类似,是初始化另一个LED连接的GPIO引脚,配置为推挽输出模式,并设置输出速度为50MHz。
cpp
#include "stm32f10x.h" // Device header
void LED2_Init(void)
{
// 1、开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
// 2、调用Init函数
// 2-1、需要先进行结构体的定义
GPIO_InitTypeDef GPIO_InitStructure;
// 数据信号的推挽输出,这个时候STM32对高低电平拥有绝对的控制权,此时LED灯长脚插在PA0口,短脚插在负极,高电平驱动也可以闪烁
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 变成了OD就成了开漏模式,就无法高电平驱动了
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ; // 选择Pin_0是因为用的是GPIOA的0号引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 输出速度
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
03-延时函数实现
Delay的实现如下:
Delay.h文件
这个.h
文件定义了三个延时函数的声明,分别是Delay_us
、Delay_ms
和Delay_s
,用于提供微秒级、毫秒级和秒级的延时功能。这些声明可以让其他源文件包含这个头文件后直接调用这些函数,而不需要知道函数的具体实现细节。同时,文件开头使用了#ifndef
和#define
宏,以及#endif
来实现头文件保护,确保在同一编译单元中只包含一次该头文件内容,防止重复定义。
cpp
#ifndef __DELAY_H
#define __DELAY_H
void Delay_us(uint32_t us); // 微秒延时
void Delay_ms(uint32_t ms); // 毫秒延时
void Delay_s(uint32_t s); // 秒延时
#endif
Delay.cpp文件:这段代码提供了三个延时函数:Delay_us
、Delay_ms
和Delay_s
,分别用于提供微秒级、毫秒级和秒级的延时。下面分别解释这三个函数:
-
void Delay_us(uint32_t xus)
:这个函数用于提供微秒级的延时。它使用了STM32的系统滴答(SysTick)定时器来实现延时。xus
参数是要延时的微秒数,通过乘以72(STM32的系统时钟频率,HCLK,假设为72MHz)来计算出SysTick定时器的重装载值。然后设置SysTick定时器的时钟源为HCLK,启动定时器,等待定时器计数到0,最后关闭定时器。 -
void Delay_ms(uint32_t xms)
:这个函数用于提供毫秒级的延时。它通过调用Delay_us
函数来实现,每次调用Delay_us
函数延时1000微秒,即1毫秒,通过xms
参数指定的次数来控制总的延时毫秒数。 -
void Delay_s(uint32_t xs)
:这个函数用于提供秒级的延时。它通过调用Delay_ms
函数来实现,每次调用Delay_ms
函数延时1000毫秒,即1秒,通过xs
参数指定的次数来控制总的延时秒数。
这三个延时函数都可以在STM32的开发中用于控制程序的执行流程,实现特定的延时效果。
cpp
#include "stm32f10x.h"
/**
* @brief 微秒级延时
* @param xus 延时时长,范围:0~233015
* @retval 无
*/
void Delay_us(uint32_t xus)
{
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
}
/**
* @brief 毫秒级延时
* @param xms 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_ms(uint32_t xms)
{
while(xms--)
{
Delay_us(1000);
}
}
/**
* @brief 秒级延时
* @param xs 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_s(uint32_t xs)
{
while(xs--)
{
Delay_ms(1000);
}
}
04-主函数实现
主函数实现代码如下:
这段主函数代码主要完成了以下几个任务:
包含了必要的头文件,如STM32F10x系列的设备头文件、延时函数头文件、LED1和LED2的头文件。
在main函数中调用了LED1_Init和LED2_Init函数,分别初始化了两个LED的引脚。
进入一个无限循环(while(1)),在循环中实现了LED1和LED2的闪烁效果:
a. 首先点亮LED1,延时1000ms,然后熄灭LED1,延时1000ms,实现LED1每秒闪烁一次的效果。
b. 接着点亮LED2,延时500ms,然后熄灭LED2,延时500ms,实现LED2每0.5秒闪烁一次的效果。
这样,主函数完成了对两个LED灯的初始化和控制,使它们交替闪烁。
cpp
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "LED2.h"
int main(void){
LED1_Init();
LED2_Init();
// 4、设置低电平,LED灯亮起
// GPIO_ResetBits(GPIOA,GPIO_Pin_1);
// 5、也可以GPIO_WriteBit()函数设置高低电平
// 前两个参数和Set和Reset一样,第三个参数用于清除端口值,和设置端口值
// 如果参数=Bit_RESET,清除端口值,设置为低电平,灯亮;反之参数=Bit_SET,为高电平,灯灭
// GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);
// 6、若是需要实现LED灯闪烁的命令,就需要在While死循环中进行一些设置
while(1){
// 点亮 两个函数都可以
// GPIO_ResetBits(GPIOA,GPIO_Pin_0);
// Delay_ms(500); // 延时函数直接调用即可
// GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
// GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)0); // 0为低电平
// 7、这里加延时函数
// Delay_ms(500);
// 熄灭
// GPIO_SetBits(GPIOA,GPIO_Pin_0);
// Delay_ms(500);
// GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET); 如果这里想要直接使用自己定义的参数代替第三个参数,
// GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)1); // 1为高电平
// (BitAction)0 需要加
// Delay_ms(500);
GPIO_SetBits(GPIOA,GPIO_Pin_1);
Delay_ms(1000);
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
Delay_ms(1000);
GPIO_SetBits(GPIOB,GPIO_Pin_1);
Delay_ms(500);
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
Delay_ms(500);
}
}
总结
实现LED灯闪烁的核心在于控制GPIO引脚的高低电平状态和添加适当的延时。在STM32上,通过操作寄存器来控制GPIO引脚状态,然后利用延时函数来控制LED的亮灭间隔。
总结如下步骤:
包含必要的头文件,如STM32的设备头文件和延时函数头文件。
初始化LED的GPIO引脚,可以通过调用初始化函数实现。
进入一个无限循环,通常使用
while(1)
。在循环中,通过操作GPIO引脚的寄存器,设置LED引脚的状态,从而控制LED的亮灭。
在LED状态改变后,添加适当的延时,以控制LED的亮灭间隔。
循环执行步骤4和步骤5,实现LED的闪烁效果。
这样,通过简单的C语言代码,就可以在STM32上实现LED的闪烁功能。