资讯详情

STM32学习——GPIO应用之跑马灯+蜂鸣器实验

GPIO应用——跑马灯 蜂鸣器实验

使用跑马灯和蜂鸣器的实验 GPIO 通用推拉输出模式 GPIO 最简单的基本功能。

1

1.1

如图所示,跑马灯使用 LED 只有 DS0(红灯)和 DS两个(绿灯),DS0 接 PB5,DS1 接 PE5image-20210619093448900

LED 它是一种发光二极管,由于是二极管,具有二极管正向导通、反向截止的特点。DS0 正极通过电阻R909 连接电源正极(即 VCC_3V三、负极连接 PB5,注意 LED0 是网络标号,网络标号相同,原理图表示相连。这个 R909 我们通常称之为限流电阻,因为 LED 灯亮时有导电流,不能太大,太大容易烧坏 LED 因此,我们通过串联一个来减少导通时的电流,根据电阻的电阻值 LED 可灵活选择不同类型。

根据二极管的单向导通特性,如果我们给它 PB5 设置高输出电平(3).3V),那么 DS0 不要点亮,但是如果给的话 PB5 由于正向压降,设置输出低电平,DS0 导通,所以点亮发光。

综上所述,本例的电路原理图,

1.2

首先,我们需要重建bsp_led.c和bsp_led.h文件

接下来我们来看看 bsp_led.h 的程序构成

#ifndef _BSP_LED_H #define _BSP_LED_H  #include "sys.h"  #define RCC_LED_ALL (LED0_GPIO_CLK | LED1_GPIO_CLK) //定义两个LED灯的端口时钟  #define LED0_GPIO_PIN GPIO_Pin_5 //LED0引脚号 #define LED0_PIN_ID 5 //LED0引脚序号 #define LED0_GPIO_PORT GPIOB //LED0端口号 #define LED0_GPIO_CLK RCC_APB2Periph_GPIOB //LED0时钟 #define LED0_FUN_OUT PBout //LED0端口输出配置  #define LED1_GPIO_PIN GPIO_Pin_5 //LED1引脚号 #define LED1_PIN_ID 5 //LED1引脚序号 #define LED1_GPIO_PORT GPIOE //LED1端口号 #define LED1_GPIO_CLK RCC_APB2Periph_GPIOE //LED1时钟 #define LED1_FUN_OUT PEout //LED1端口输出配置  #define LED0 LED0_FUN_OUT(LED0_PIN_ID) //定义LED的输出 #define LED1 LED1_FUN_OUT(LED0_PIN_ID)  //函数声明 void bsp_InitLed(void); void bsp_LedOn(uint8_t _on); void bsp_LedOff(uint8_t _off); void bsp_LedToggle(uint8_t _no); uint8_t bsp_IsLedOn(uint8_t _no);  #
        
         endif
        
/***************************** (END OF FILE) *********************************/

时钟,引脚和端口全部采用宏定义的方式,主要是方便以后程序修改,后面的例子都采用这种方式来实现。在讲解这个文件构成前,我们先看一下该头文件包含的 sys.h 头文件的构成,这对我们了解 bsp_led.h 和 bsp_led.c 至关重要,====构成如下所示。

#ifndef __SYS_H
#define __SYS_H 
#include "stm32f10x.h"
/* ********************************************************************************************************* * * 模块名称 : sys模块 * 文件名称 : sys.h * 说 明 : 这是所有驱动h文件需要包含的h文件,需要在头文件中包含,实现位带操作 * ********************************************************************************************************* */															    

#define WSNEP_V01
//#define TDL_02

/* 检查是否定义了开发板型号 */
#if !defined (WSNEP_V01) && !defined (TDL_02)
	#error "Please define the board model : TDL_02 or WSNEP_V01"
#endif


//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) 
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) 
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C 
#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C 
#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C 
#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C 
#define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C 
#define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C 
#define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C 

#define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808 
#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08 
#define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008 
#define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408 
#define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808 
#define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08 
#define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08 
 
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出 
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入 

#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出 
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入 

#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出 
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入 

#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出 
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入 

#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出 
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入

#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出 
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入

#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出 
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入


#endif

该头文件包含里 stm32f10x.h 的头文件,这个头文件是 ST 官方提供的,里面主要STM32F10x 系列的寄存器定义,这和 51 单片机里的 reg52.h 类似。文件中定义了 WSNEP_V01,这里定义的是开发板的型号,我们可以通过定义不同的开发板型号,。这是一个提高程序可移植性的思想。

有了 sys.h 里的代码,我们就可以像 51 单片机一样操作 STM32 的 IO 口了,比如我们调用 PBout(5)=1 是设置了 PB5 输出为高电平。

在简要的分析了 sys.h 的代码后,我们回到 bsp_led.h 文件里。注意这里将GPIO 端口,GPIO 引脚号,以及 GPIO 端口时钟进行了封装。其中 GPIO_CLK 宏是“RCC_APB2Periph_GPIOB”是 STM32 标准库里用来定义 GPIO 端口时钟相关的宏,它的作用与“GPIO_Pin_x”这类宏类似。LED0_FUN_OUT 定义的是 sys 里面的 PBout,以后我们还会用到输入函数,那么将使用 XXX_FUN_IN,配置对应的端口 Pxin,x 对应的是 GPIO 端 口中的 A~G。注意这里的 LED0_PIN_ID 是表示的端口序号。另外将 LED 操作函数也做了一个封装,#define LED0 LED0_FUN_OUT(LED0_PIN_ID),经过这些宏定义操作后,我们就可以进行进一步的操作了。

注意在 bsp_led.h 头文件最后是将 c 文件的函数做一个函数申明。

接下来我们看一下在 bsp_led.c 文件里怎么使用这些宏定义。先看一下 bsp_InitLed 函数

在这个函数中我们讲解一下对====

  1. 首先我们通过 GPIO_InitTypeDef 定义一个结构体 GPIO_InitStructure。
  2. 通过 RCC_APB2PeriphClock 打开 GPIO 端口时钟。
  3. 给 GPIO_ InitStructure 里的 GPIO_Speed、GPIO_Mode、GPIO_Pin 成员赋值
  4. 通过调用 GPIO_Init 对结构体进行初始化。
  5. 设置端口初始电平,这里使用的函数是 bsp_LedOff
void bsp_InitLed(void)
{ 
        
	GPIO_InitTypeDef GPIO_InitStructure;
	//使能时钟
	RCC_APB2PeriphClockCmd(RCC_LED_ALL, ENABLE);
	//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);
	bsp_LedOff(1);		//初始化led为关闭状态
	bsp_LedOff(2);
	//LED0
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//设置速度
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	//设置输出方式(复用开漏输出 )
	GPIO_InitStructure.GPIO_Pin = LED0_GPIO_PIN;		//设置端口号
	GPIO_Init(LED0_GPIO_PORT,&GPIO_InitStructure);		//初始化配置
	//LED1
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN;
	GPIO_Init(LED1_GPIO_PORT,&GPIO_InitStructure);
	
}

接下来看一下 bsp_LedOn 函数,此函数实现点亮 LED 灯,这里提供了两种实现方法,一种是寄存器,一种是位带的方式。

void bsp_LedOn(uint8_t _on)
{ 
        
	
	if(_on==1)
	{ 
        
		LED0 = 0;
// GPIO_ResetBits(LED0_GPIO_PORT,LED0_GPIO_PIN);
	}
	else if(_on==2)
	{ 
        
		LED1 = 0;
// GPIO_ResetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);
	}
}

bsp_LedOff 函数实现熄灭 LED 灯,和点亮 LED 灯函数类似,

void bsp_LedOff(uint8_t _off)
{ 
        
	
	if(_off==1)
	{ 
        
		LED0 = 1;
// GPIO_SetBits(LED0_GPIO_PORT,LED0_GPIO_PIN);
	}
	else if(_off==2)
	{ 
        
		LED1 = 0;
// GPIO_SetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);
	}
}

main.c 主函数

int main(void)
{ 
        
	/* ST固件库中的启动文件已经执行了 SystemInit() 函数,该函数在 system_stm32f10x.c 文件,主要功能是 配置CPU系统的时钟 */
	bsp_Init();		/* 硬件初始化 */

	while(1)
	{ 
        
		bsp_BeepOn();			//打开蜂鸣器
		bsp_LedToggle(1);		//LED0翻转
		delay_ms(1000);			//延时1000ms
		bsp_BeepOff();			//关闭蜂鸣器
		bsp_LedToggle(2);		//LED1翻转
		delay_ms(1000);			//延时1000ms
		
	}
}

在 main 函数里有两个函数没见过,它们是 bsp_Init()和 delay_ms(),这两个函数在 bsp.c文件里

先了解一下 bsp_Init 函数

void bsp_Init(void)
{ 
        
	/* 由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。 启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。 系统时钟缺省配置为72MHz,如果需要更改,可以修改 system_stm32f10x.c 文件 */

	/* 优先级分组设置为2 */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	bsp_InitLed();		/* 配置LED的GPIO端口 */
	bsp_InitBeep();		/* 配置Beep的GPIO端口 */
	
	bsp_InitTimer();	/* 初始化系统滴答定时器 (此函数会开中断) */
}

bsp_Init 函数是按需更改的,其中下面两条语句是固定。

//优先级分组

//初始化系统滴答定时器。函数实体在 bsp_timer.c 里

bsp_InitLed 函数之前在 bsp_led.c 部分已经讲解过了。这里直接调用进行 LED 灯端口和模式的初始化。

delay_ms 函数从函数名可以看出这是延时毫秒的函数,可以直接调用

2.蜂鸣器实验

1.1

如图所示跑马灯使用的 LED 只有 DS0(红灯)和 DS1(绿灯)两个,DS0 接 PB5,DS1 接 PE5)

蜂鸣器也是使用的 GPIO 的输出功能,这里相当于进一步熟悉一下 STM32 的 IO 端口的使用。注意一下,这里使用了 NPN 三极管,实际上使用的是三极管导通和截止的功能,对 于图中的接法,

2.2软件设计

bsp_beep.h 文件

#ifndef _BSP_BEEP_H
#define _BSP_BEEP_H
#include "sys.h"

#define RCC_ALL_BEEP (BEEP_GPIO_CLK) //beep时钟
	
#define BEEP_GPIO_PIN GPIO_Pin_11 //beep引脚号
#define BEEP_PIN_ID 11 //beep引脚序号
#define BEEP_GPIO_PORT GPIOG //beep端口号
#define BEEP_GPIO_CLK RCC_APB2Periph_GPIOG //beep时钟
#define BEEP_FUN_OUT PGout //beep输出端口配置函数
//#define LED0_FUN_IN PBin //beep输入端口配置函数
//


//IO操作函数
#define BEEP BEEP_FUN_OUT( BEEP_PIN_ID )

/*函数声明*/
void bsp_InitBeep(void);
void bsp_BeepOn(void);
void bsp_BeepOff(void);
void bsp_BeepToggle(void);
uint8_t	bsp_IsBeepOn(void);

#endif
/***************************** (END OF FILE) *********************************/

bsp_beep.c 文件

#include "bsp.h"
/******************************************************************************* * 函数名 :bsp_InitBeep * 函数功能 :配置有源蜂鸣器相关的 GPIO, 该函数被 bsp_Init()调用 * 输入 : 无 * 输出 : 无 *******************************************************************************/
void bsp_InitBeep(void)
{ 
        
	//定义一个结构体变量
	GPIO_InitTypeDef GPIO_InitStructure;
	//打开GPIO时钟
	RCC_APB2PeriphClockCmd(RCC_ALL_BEEP,ENABLE );
    //设置输出速度
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	//设置输出模式为开漏输出
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	//
	GPIO_InitStructure.GPIO_Pin = BEEP_GPIO_PIN;
	//
	GPIO_Init( BEEP_GPIO_PORT , &GPIO_InitStructure);
		
}
/******************************************************************************* * 函数名 :bsp_BeepOn() * 函数功能 :开启蜂鸣器 * 输入 : 无 * 输出 : 无 *******************************************************************************/
void bsp_BeepOn()
{ 
        
	//beep引脚给高电平,蜂鸣器工作
	//方法一
	//BEEP_GPIO_PORT->BSRR=BEEP_GPIO_PIN
	//方法二
	BEEP=1;			
}
/******************************************************************************* * 函数名 :bsp_BeepOff() * 函数功能 :开启蜂鸣器 * 输入 : 无 * 输出 : 无 *******************************************************************************/
void bsp_BeepOff()
{ 
        
	//BEEP_GPIO_PORT->BSRR=BEEP_GPIO_PIN
	BEEP=0;
}
/******************************************************************************* * 函数名 :bsp_BeepToggle() * 函数功能 :蜂鸣器翻转函数 * 输入 : 无 * 输出 : 无 *******************************************************************************/
void bsp_BeepToggle()
{ 
        
	BEEP_GPIO_PORT->ODR^=BEEP_GPIO_PIN;
}

/******************************************************************************* * 函数名 :bsp_IsBeepOn() * 函数功能 :判断蜂鸣器是否鸣叫 * 输入 : 无 * 输出 : 1表示鸣叫,0表示静音 *******************************************************************************/
uint8_t	bsp_IsBeepOn()
{ 
        
	if((BEEP_GPIO_PORT->ODR&BEEP_GPIO_PIN)==BEEP_GPIO_PIN)
	{ 
        
		return 1;
	}
	return 0;	
}
/***************************** (END OF FILE) *********************************/

主函数

int main(void)
{ 
        
    /* ST固件库中的启动文件已经执行了 SystemInit() 函数,该函数在 system_stm32f10x.c 文件,主要功能是 配置CPU系统的时钟 */
    bsp_Init();		/* 硬件初始化 */

    while(1)
    { 
        
        bsp_BeepOn();			//打开蜂鸣器
        bsp_LedToggle(1);		//LED0翻转
        delay_ms(1000);			//延时1000ms
        bsp_BeepOff();			//关闭蜂鸣器
        bsp_LedToggle(2);		//LED1翻转
        delay_ms(1000);			//延时1000ms

    }
}

标签: bsp62三极管

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台