基于STM32的学习之项目01——LED闪烁和LED流水灯

 前言

        学习任何一块开发板的入门第一课就是成为一个合格的“点灯大师”,在基于标准库来进行点亮一个LED灯的过程中,碰到了许多与之前学习单片机不一样的地方,STM32的学习更注重于对计算机系统底层逻辑的学习,比如一些寄存器、时钟信号等等,偏向与最本质的学习,同时将理论知识与实际相结合,在实践过程中不断掌握知识。话不多说接下来记录第一次STM32的学习。

一:创建模板文件

在之前的学习中,自己创建了一个类似于模板的项目,其中包含了支持开发板的标准库和该芯片的支持包,本系列开发都是基于STM32F103ZET6系列进行开发。下图是工程模板

在进行每一个小实验的过程中,我们需要添加另外一个文件夹System用来存放我们需要创建的驱动文件,本实验中需要一个驱动LED的C文件和头文件,在C文件中需要写出LED的启动函数以及其他功能函数;头文件中为函数的申明,便于最后在主程序中调用。

二、System中的文件

01、延时函数的封装(包括三个函数:微秒级延迟,毫秒级延迟,妙计延迟)

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_us(1000);
	}
}

延时函数头文件:

#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

#ifndef在C语言中表示"if not defined",是预处理功能中的条件编译指令。它的作用是判断某个标识符是否已经被定义,如果没有被定义,则执行#ifndef后面的代码,否则就跳过这部分代码。这样可以防止头文件的重复包含和编译,同时也便于程序的调试和移植。

三、Hardware文件中的内容

02、LED封装(本实验开发板中含有两个LED灯,分别为PB5和PE5两个端口)

#include "stm32f10x.h"                  // Device header

void LED_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE	, ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_PP;//推挽输出模式
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_5 ;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
	GPIO_Init(GPIOB , &GPIO_InitStructure);//地址传递,结构体变量名
	GPIO_Init(GPIOE , &GPIO_InitStructure);//地址传递,结构体变量名
	
	//GPIO_SetBits(GPIOB , GPIO_Pin_5); 	   //由于初始化后默认是为低电平(推挽输出模式),LED灯会亮,所以SetBits为了让端口置高,设定为了让LED开始是熄灭的状态
	//GPIO_SetBits(GPIOE , GPIO_Pin_5);	   //同理与上
}

void DSO_ON(void)	//开启LED_DSO灯
{
	GPIO_ResetBits(GPIOB , GPIO_Pin_5);//
}
void DSO_Off(void)
{
	GPIO_SetBits(GPIOB,GPIO_Pin_5);
}
void DSO_Turn(void)//输出端口使得电平翻转
{
	if(GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_5) == 0)//当前端口值输出为0
	{
		GPIO_SetBits(GPIOB, GPIO_Pin_5);//将该端口值置为1;
	}
	else
	{
		GPIO_ResetBits(GPIOB, GPIO_Pin_5);//将该端口置为0
	}
}

void DS1_ON(void)
{
	GPIO_ResetBits(GPIOE,GPIO_Pin_5);
}
void DS1_Off(void)
{
	GPIO_SetBits(GPIOE,GPIO_Pin_5);
}
void DS1_Turn(void)//输出端口使得电平翻转
{
	if(GPIO_ReadOutputDataBit(GPIOE, GPIO_Pin_5) == 0)//当前端口值输出为0
	{
		GPIO_SetBits(GPIOE, GPIO_Pin_5);//将该端口值置为1;
	}
	else
	{
		GPIO_ResetBits(GPIOE, GPIO_Pin_5);//将该端口置为0
	}
}

LED功能函数头文件(DS0对应PB5口的LED灯,DS1对应PE5口的LED灯)

#ifndef _LED_H
#define _LED_H
void LED_Init(void);  // 可以被外部调用
void DSO_ON(void);//DSO打开
void DSO_Off(void);//DSO关闭
void DS1_ON(void);//DS1打开
void DS1_Off(void);//DS1关闭
void DS1_Turn(void);//翻转PE3端口值
void DSO_Turn(void);//翻转PE4端口值
#endif

四、主函数

#include "stm32f10x.h"           // Device header
#include "Delay.h" 
#include "LED.h"
int main(void)
{
	LED_Init();        //启动对应的外设接口,以及相应的参数设置

    while(1)
    {
    
    DSO_ON();   //打开DSO;
    Delay_ms(500);  //延时500毫秒
    DSO_Off();       //关闭DSO
    Delay_ms(500);  //延时500毫秒         
                
    DS1_ON();   //打开DS1;
    Delay_ms(500);  //延时500毫秒
    DS1_Off();       //关闭DS1
    Delay_ms(500);  //延时500毫秒
    
    }

五、总结

1、LED的启动文件中有几个函数,需要学习记录一下:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOX,ENABLE):该函数用于APB2上的外设重置,以便重新启动,通常用于初始化外设时使用,确保外设打开才能进行后续的数据输出。参数RCC_APB2Periph_GPIOX,其中可改变参数X,表示启动的外设端口,从A-G等,第二个参数一般选择ENABLE为使能开启状态。

GPIO_Init(GPIOX , &GPIO_InitStructure):此函数时定义对应的GPIO模块,以及传递InitStructure中的参数值,注意此处为地址传递,故需要取地址符&;

GPIO_InitTypeDef GPIO_InitStructure;//定义一个结构体类型的变量,用于参数的值传递

GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_PP;//设置此处的端口输出模式为推挽输出模式,在此处的低电平与高电平都具有驱动能力。
GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_5 ;//定义具体的引脚号
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;//定义传输速率,一般为50MHz。

GPIO_SetBits(GPIOB , GPIO_Pin_5); //对PB5端口设置为高电平

GPIO_ResetBits(GPIOB , GPIO_Pin_5); //对PB5端口设置为低电平

2、怎么模块化的进行编程

        通过把每一个函数具体的功能函数进行封装为C文件和头文件,然后在主程序中进行调用即可,期间需要明确每一个函数的含义,所以需要在定义函数名时给定一个通俗易懂的函数名,确保自己和别人看懂,最起码自己看的懂。

3、本项目框架

需要把以后所有的实验封装都添加到Hardware文件夹中。

六、实验现象

VID_20240525_162914

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值