STM32學習筆記(1)——LED和蜂鳴器


閱讀前提示: 我們使用的板子是正點原子的ALIENTEK精英STM32F103。本文使用固件庫進行編程,因為使用固件庫編程較為方便,且閱讀程序也較易理解。

零、GPIO簡介及其庫函數

1. GPIO簡介

7組IO口(具體地址可見頭文件stm32f10x.h): GPIOA ~ GPIOG。每組IO口可控制7個寄存器,這7個寄存器可控制一組GPIO的16個IO口:

  • GPIOx_CRL:端口配置低寄存器
  • GPIOx_CRH:端口配置高寄存器
  • GPIOx_IDR:端口輸入寄存器
  • GPIOx_ODR:端口輸出寄存器
  • GPIOx_BSRR:端口位設置/清除寄存器
  • GPIOx_BRR:端口位清除寄存器
  • GPIOx_LCKR:端口配置鎖存寄存器

16個管腳(GPIO_Pin)(位於頭文件stm32f10x_gpio.h): GPIO_Pin_0 ~ GPIO_Pin_15,若想全部選中則GPIO_Pin_All。

4種輸入模式(GPIO_Mode)(位於頭文件stm32f10x_gpio.h):

  • 浮空輸入(GPIO_Mode_IN_FLOATING)
  • 上拉輸入(GPIO_Mode_IPU)
  • 下拉輸入(GPIO_Mode_IPD)
  • 模擬輸入(GPIO_Mode_AIN)

4種輸出模式(GPIO_Mode)(位於頭文件stm32f10x_gpio.h):

  • 開漏輸出( GPIO_Mode_Out_OD)
  • 復用開漏輸出(GPIO_Mode_AF_OD)
  • 推挽輸出(GPIO_Mode_Out_PP)
  • 復用推挽輸出(GPIO_Mode_AF_PP)

3種最大輸出速度(GPIO_Speed)(位於頭文件stm32f10x_gpio.h):

  • GPIO_Speed_2MHz
  • GPIO_Speed_10MHz
  • GPIO_Speed_50MHz

簡要介紹常用的輸出模式:

推挽輸出:
可以輸出強高低電平,連接數字器件。

開漏輸出:
只可以輸出強低電平,高電平得靠外部電阻拉高。輸出端相當於三極管的集電極. 要得到高電平狀態需要上拉電阻才行. 適合於做電流型的驅動,其吸收電流的能力相對強(一般20mA以內)

GPIO結構體定義(位於頭文件stm32f10x_gpio.h):

typedef struct
{
  uint16_t GPIO_Pin;             /* 設置初始化管腳 */

  GPIOSpeed_TypeDef GPIO_Speed;  /* 設置輸入或輸出速度 */

  GPIOMode_TypeDef GPIO_Mode;    /* 設置輸入或輸出模式 */
}GPIO_InitTypeDef;

2. 與GPIO有關的幾個常用庫函數

(1)初始化函數:

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);

作用:初始化一個或者多個IO口(同一組)的工作方式和速度。該函數主要是操作GPIO_CRL(CRH)寄存器,在上拉或者下拉的時候有設置BSRR或者BRR寄存器。

(2)讀取輸入電平函數

讀取某個GPIO的輸入電平(實際操作的是GPIOx_IDR寄存器):

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

讀取某組GPIO的輸入電平(實際操作的是GPIOx_IDR寄存器):

uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);

(3)讀取輸出電平函數

讀取某個GPIO的輸出電平(實際操作的是GPIOx_ODR寄存器):

uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

讀取某組GPIO的輸出電平(實際操作的是GPIOx_ODR寄存器):

uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);

(4)設置輸出電平函數

設置某個IO口輸出為高電平(實際操作BSRR寄存器):

void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

設置某個IO口輸出為低電平(實際操作的BRR寄存器):

void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

不常用的兩個函數:

void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
/* 這兩個函數不常用,也是用來設置IO口輸出電平 */

(5)初始化GPIO口的一般步驟

我們以一段程序為例來說明初始化GPIO口的幾個步驟。

/* 1.定義初始化GPIO結構體 */
GPIO_InitTypeDef GPIO_InitStructure;

/* 2.開啟GPIO外設的時鍾 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

/* 3.設置為推挽輸出模式 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

/* 4.設置輸出速度為50MHz*/
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

/* 5.選擇管腳為5 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;

/* 6.進行初始化操作 */
GPIO_Init(GPIOB, &GPIO_InitStructure);

一、LED跑馬燈的實現

本程序實現了兩個LED輪流點亮及熄滅的效果。

有關LED的電路圖如下所示:

從電路圖中可知,當輸出IO口電平為低電平時,LED燈亮;當輸出IO口電平為高電平時,LED燈滅。

從LED電路圖可知,LED0接在PB5,LED1接在PE5。選擇的輸出模式:推挽輸出。

程序如下(本程序包含3個源文件,其中delay.h為正點原子資料盤內自帶的頭文件,亦可使用51單片機常用的簡易延時函數,即循環延時法):

/* =====main.c===== */
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"

int main(void)
{
	delay_init();
	LED_Init();
	
	while(1)
	{
		GPIO_ResetBits(GPIOB, GPIO_Pin_5);
		GPIO_SetBits(GPIOE, GPIO_Pin_5);
		delay_ms(500);
		
		GPIO_SetBits(GPIOB, GPIO_Pin_5);
		GPIO_ResetBits(GPIOE, GPIO_Pin_5);
		delay_ms(500);
	}
}


/* =====led.h===== */
//這樣的宏定義是為了防止led.c內的函數被重復聲明
#ifndef __LED_H
#define __LED_H

void LED_Init(void);

#endif


/* =====led.c===== */
#include "led.h"
#include "stm32f10x.h"

//當函數參數為空時,寫上void是很不錯的習慣
void LED_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	/* 開啟使能IO口時鍾 */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
	//也可以寫成:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOB, ENABLE);
	// “|”為或運算符
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_SetBits(GPIOB, GPIO_Pin_5);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
	GPIO_Init(GPIOE, &GPIO_InitStructure);
	GPIO_SetBits(GPIOE, GPIO_Pin_5);
	
}

二、蜂鳴器循環響滅

有關蜂鳴器的電路圖如下所示:

從電路圖中可知,當輸出IO口電平為低電平時,三極管處於截止狀態,蜂鳴器不響;當輸出IO口電平為高電平時,三極管處於放大狀態,蜂鳴器響。BEEP接在PB8。

程序如下:

/* =====main.c===== */
#include "stm32f10x.h"
#include "delay.h"
#include "beep.h"

int main(void)
{	
	Beep_Init();
	delay_init();
	while(1)
	{
		GPIO_SetBits(GPIOB, GPIO_Pin_8);
		delay_ms(500);
		GPIO_ResetBits(GPIOB, GPIO_Pin_8);
		delay_ms(500);
	}
}


/* =====beep.h===== */
#ifndef __BEEP_H
#define __BEEP_H

void Beep_Init(void);

#endif


/* =====beep.c===== */
#include "stm32f10x.h"
#include "beep.h"

void Beep_Init()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_ResetBits(GPIOB, GPIO_Pin_8);
}

三、蜂鳴器和LED燈循環

本程序實現了蜂鳴器與兩個LED輪流工作的效果。前500ms,LED1和BEEP工作,后500ms,僅LED0工作。

為方便程序閱讀,我們將設置高低電平的函數封裝成宏。程序如下:

/* =====main.c===== */
#include "stm32f10x.h"
#include "delay.h"
#include "beep.h"
#include "led.h"

int main(void)
{	
	LED_Init();
	Beep_Init();
	delay_init();
	while(1)
	{
		BEEP_ON;
		LED0_OFF;
		LED1_ON;
		delay_ms(500);
		
		BEEP_OFF;
		LED0_ON;
		LED1_OFF;
		delay_ms(500);
	}
}


/* =====led.h===== */
#ifndef __LED_H
#define __LED_H

#define LED0_OFF GPIO_SetBits(GPIOB, GPIO_Pin_5)
#define LED0_ON GPIO_ResetBits(GPIOB, GPIO_Pin_5)
#define LED1_OFF GPIO_SetBits(GPIOE, GPIO_Pin_5)
#define LED1_ON GPIO_ResetBits(GPIOE, GPIO_Pin_5)

void LED_Init(void);

#endif


/* =====led.c===== */
#include "stm32f10x.h"
#include "led.h"

void LED_Init()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_Init(GPIOE, &GPIO_InitStructure);
	
	LED0_OFF;
	LED1_OFF;
}


/* =====beep.h===== */
#ifndef __BEEP_H
#define __BEEP_H

#define BEEP_ON GPIO_SetBits(GPIOB, GPIO_Pin_8)
#define BEEP_OFF GPIO_ResetBits(GPIOB, GPIO_Pin_8)

void Beep_Init(void);

#endif



/* =====beep.c===== */
#include "stm32f10x.h"
#include "beep.h"

void Beep_Init()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	BEEP_OFF;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM