STM32入门学习 第二天

提示:今天是STM32入门学习的第二天,重点学习了GPIO的工作原理,通过库函数、寄存器、位操作来实现跑马灯。


目录

 第一讲 STM32GPIO工作原理

1.GPIO功能描述

2.每组GPIO端口的寄存器

第二讲 库函数——跑马灯

1.初始化

2.手把手写跑马灯实验-库函数

第三讲 寄存器——跑马灯

第四讲 位操作——跑马灯


第一讲 STM32GPIO工作原理

1.GPIO功能描述

每个GPIO端口有两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个32位数据寄存器 (GPIOx_IDR和GPIOx_ODR),一个32位置位/复位寄存器(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。

根据数据手册中列出的每个I/O端口的特定硬件特征, GPIO端口的每个位可以由软件分别配置 成多种模式。

4种输入模式

  • 输入浮空
  • 输入上拉
  • 输入下拉
  • 模拟输入
u 4 种输出模式:
  • 开漏输出
  • 推挽式输出
  • 推挽式复用功能
  • 开漏复用功能

每个I/O端口位可以自由编程,然而I/0端口寄存器必须按32位字被访问(不允许半字或字节访 问)。GPIOx_BSRR和GPIOx_BRR寄存器允许对任何GPIO寄存器的读/更改的独立访问;这 样,在读和更改访问之间产生IRQ时不会发生危险。 下图给出了一个I/O端口位的基本结构

STM32入门学习 第二天_第1张图片

 3种最大翻转速度

STM32入门学习 第二天_第2张图片

 GPIO的输入工作模式1—输入浮空模式

STM32入门学习 第二天_第3张图片

GPIO的输入工作模式2—输入上拉模式

STM32入门学习 第二天_第4张图片

 GPIO的输入工作模式3—输入下拉模式

STM32入门学习 第二天_第5张图片

 GPIO的输入工作模式4—模拟模式

STM32入门学习 第二天_第6张图片

 GPIO的输出工作模式1—开漏输出模式

STM32入门学习 第二天_第7张图片

 GPIO的输出工作模式2—开漏复用输出模式

STM32入门学习 第二天_第8张图片

 GPIO的输出工作模式3—推挽输出模式

STM32入门学习 第二天_第9张图片

 GPIO的输出工作模式4—推挽复用输出模式

STM32入门学习 第二天_第10张图片

推挽输出:可以输出强高低电平,连接数字器件 

开漏输出:只可以输出强低电平,高电平得靠外部电阻拉高。输出端相当于三极管的集电极. 要得到高电平状态需要上拉电阻才行. 适合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内)

2.每组GPIO端口的寄存器

两个32位配置寄存器(GPIOx_CRL GPIOx_CRH)

两个32位数据寄存器 (GPIOx_IDRGPIOx_ODR)

一个32位置位/ 复位寄存器(GPIOx_BSRR)

一个16位复位寄存器(GPIOx_BRR)

一个32位锁定寄存器(GPIOx_LCKR)

每个I/O端口位可以自由编程,然而I/O端口寄存器必须按32位字被访问(不允许半字或字节访问)

例如:STM32F103ZET6:一共有7组IO口,每组IO口有16个IO,一共16X7=112个IO。GPIOA,GPIOB---GPIOG。每组IO口含下面7个寄存器,也就是7个寄存器,一共可以控制一组GPIO的16个IO口。

32位寄存器配置每个IO口要四位,所以只能配置八个IO口,而有十六个IO口,故需要两个端口配置寄存器。CRL控制0—7的IO口,CRH控制8—15个IO口。

2.1 端口配置低寄存器(GPIOx_CRL)

观察使用时先确定MODY是在输出还是输入,若为00则为输入,此时在看CNYF是输入的那个状态,其中10有上拉和下拉是在ODR这个寄存器里面。

STM32入门学习 第二天_第11张图片

STM32入门学习 第二天_第12张图片

2.2 端口配置高寄存器(GPIOx_CRH)

STM32入门学习 第二天_第13张图片

 2.3 端口输入数据寄存器(GPIOx_IDR)

STM32入门学习 第二天_第14张图片

2.4 端口输出数据寄存器(GPIOx_ODR) 

 输出为1则是高电平,输出为0则是低电平。和输出寄存器一样,主要是这个寄存器控制着上拉还是下拉电阻。其中0为下拉1为上拉。

STM32入门学习 第二天_第15张图片

2.5 端口位设置/清除寄存器(GPIOx_BSRR)

STM32入门学习 第二天_第16张图片

2.6 端口位清除寄存器(GPIOx_BRR)

设置那个IO口就是那个IO口。不过经常以这个寄存器清除低位,以2.5那个寄存器清除高位。 

STM32入门学习 第二天_第17张图片

a.端口重映射功能:就是可以把某些功能引脚映射到其他引脚。 比如串口1默认引脚是PA9,PA10可以通过配置重映射映,射到PB6,PB7。作用:方便布线 
端口复用功能:STM32的大部分端口都具有复用功能。所谓复用,就是一些端口不仅仅可以做为通用IO口,还可以复用为一些外设引脚,比如PA9,PA10可以复用为STM32的串口1引脚。作用:最大限度的利用端口资源

第二讲 库函数——跑马灯

GPIO输出方式:推挽输出,可以输出强高低电平。

库函数的介绍:操作IO口必须引入的源文件和头文件。

头文件:stm32f10x_gpio.h

源文件:stm32f10x_gpio.c

1.初始化

重要函数:

1个初始化函数:

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

2个读取输入电平函数:

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);

2个读取输出电平函数:

uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);

4个设置输出电平函数:

void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);输出高

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);

1个初始化函数:此函数调用的时候要输入两个参数,对于第一个参数来说进入是一个结构体里面存放了IO口的七个寄存器,而范围是GPIOA~GPIOG  。第二个参数是来初始化的里面是如下方框里的一个结构体,后面跟着一个指针变量。

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

作用:初始化一个或者多个IO口(同一组)的工作方式和速度。

该函数主要是操作GPIO_CRL(CRH)寄存器,在上拉或者下拉的时候有设置BSRR或者BRR寄存器

GPIOx: GPIOA~GPIOG    

 typedef struct
   {
     uint16_t GPIO_Pin;          //指定那一组中要初始化的IO口         
    GPIOSpeed_TypeDef GPIO_Speed; //设置IO口输出速度
    GPIOMode_TypeDef GPIO_Mode;    //设置工作模式:8种中的一个
   }GPIO_InitTypeDef;

注意:外设(包括GPIO)在使用之前,几乎都要先使能对应的时钟。

GPIO_Init函数初始化样:

     
 GPIO_InitTypeDef  GPIO_InitStructure;
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);	 //根据设定参数初始化GPIOB.5

2个读取输入电平函数:

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

作用:读取某个GPIO的输入电平。实际操作的是GPIOx_IDR寄存器。

例如:GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5);//读取GPIOA.5的输入电平

uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);

作用:读取某组GPIO的输入电平。实际操作的是GPIOx_IDR寄存器。

例如:GPIO_ReadInputData(GPIOA);//读取GPIOA组中所有io口输入电平

4个设置输出电平函数:

void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

作用:设置某个IO口输出为高电平(1)。实际操作BSRR寄存器

void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

作用:设置某个IO口输出为低电平(0)。实际操作的BRR寄存器。

void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);

void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

 这两个函数不常用,也是用来设置IO口输出电平。

2.手把手写跑马灯实验-库函数

使能IO口时钟。调用函数RCC_APB2PeriphColckCmd();

不同的IO组,调用的时钟使能函数不一样。

初始化IO口模式。调用函数GPIO_Init();
操作IO口,输出高低电平。GPIO_SetBits();GPIO_ResetBits();
#include"led.h"
#include"stm32f10x.h"

void LED_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructture;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);//ʹÄÜʱÖÓ
	
	GPIO_InitStructture.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructture.GPIO_Pin=GPIO_Pin_5;
	GPIO_InitStructture.GPIO_Speed=GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOB,&GPIO_InitStructture);
	GPIO_SetBits(GPIOB,GPIO_Pin_5);
	
	GPIO_InitStructture.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructture.GPIO_Pin=GPIO_Pin_5;
	GPIO_InitStructture.GPIO_Speed=GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOE,&GPIO_InitStructture);
	GPIO_SetBits(GPIOE,GPIO_Pin_5);
}
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"


int main(void)
{

delay_init();
LED_Init();

	while(1){
		
		GPIO_SetBits(GPIOB,GPIO_Pin_5);
		GPIO_SetBits(GPIOE,GPIO_Pin_5);
		delay_ms(500);
		
		GPIO_ResetBits(GPIOB,GPIO_Pin_5);
		GPIO_ResetBits(GPIOB,GPIO_Pin_5);
		delay_ms(500);
	}
}

第三讲 寄存器——跑马灯

在了解下GPIO相关的寄存器,在库函数里操作寄存器。

两个32位配置寄存器(GPIOx_CRL ,GPIOx_CRH) ,

两个32位数据寄存器 (GPIOx_IDR和GPIOx_ODR),

一个32位置位/ 复位寄存器(GPIOx_BSRR),

一个16位复位寄存器(GPIOx_BRR),

一个32位锁定寄存器(GPIOx_LCKR)。

手把手写跑马灯实验-寄存器
使能IO口时钟。配置寄存器RCC_APB2ENR。
初始化IO口模式。配置寄存器GPIOx_CRH/CRL
操作IO口,输出高低电平。配置寄存器GPIOX_ODR或者BSRR/BRR。
#include"led.h"
#include"stm32f10x.h"

void LED_Init(void)
{
    RCC->APB2ENR!=1<<3;//寄存器只要第三位,其他不改变
    RCC->APB2ENR!=1<<6;//寄存器第六位

    GPIOB->CRL&=0XFF0FFFFF;//GPIOB.5
    GPIOB->CRL|=0X00300000;//先清零在赋值

    GPIO->ODR=1<<5;


    GPIOB->CRL&=0XFF0FFFFF;//GPIOB.6
    GPIOB->CRL|=0X00300000;//先清零在赋值

    GPIO->ODR=1<<5;    

}
#include"stm32f10x.h"
#include"delay.h"
#include"led.h"

int main(void)
{
delay_init();
LED_Init();

while(1){
GPIOB->|=1<<5;
GPIOE->|=1<<5;
delay_init(500);

GPIOB->ODR=~(1<<5);
delay_init(500);
}
}

第四讲 位操作——跑马灯

位操作:支持了位带 中,有两个区中实现了位带。其中一个是 SRAM 区的最低 1MB 范围,第二个则是片内外设 区的最低 1MB 范围。这两个区中的地址除了可以像普通的 RAM 一样使用外,它们还都有自 己的“位带别名区”,位带别名区把每个比特膨胀成一个 32 位的字。当你通过位带别名区访 问这些字时,就可以达到访问原始比特的目的。

也可以理解成把每个比特膨胀为一个32位的字,当访问这些字的时候就达到了访问比特的目的,比如说BSRR寄存器有32个位,那么可以映射到32个地址上,我们去访问(读--写)32个地址就达到访问32个比特的目的。

STM32入门学习 第二天_第18张图片

STM32入门学习 第二天_第19张图片

 举例如下:

STM32入门学习 第二天_第20张图片

映射关系:

位带区:支持位带操作的地址区

位带别名:对别名地址的访问最终作用到位带区的访问上(注意:这中间有一个地址映射过程)

STM32入门学习 第二天_第21张图片

手把手写跑马灯实验-位带操作。

使能IO口时钟。调用函数RCC_APB2PeriphColckCmd();

初始化IO口模式。调用函数GPIO_Init();

操作IO 口,输出高低电平。 使用位带操作
sys.h里面对GPIO输入输出部分功能实现了位带操作:
#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 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 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 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)  //输入
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
 
 int main(void)
 {	
 
	 delay_init();
	 
	 LED_Init();
	 
	 while(1){
	 
	  PBout(5)=1;
	  PEout(5)=1;

	  delay_ms(500);
		 
	  PBout(5)=0;
	  PEout(5)=0;
		 
	  delay_ms(500);

	 }
	 
 }

第五讲 蜂鸣器实验

1.蜂鸣器简介

蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。 我们使用的开发板板载的蜂鸣器是电磁式的有源蜂鸣器。这里的有源不是指电源的“源”,而是指有没有自带震荡电路,有源蜂鸣器自带了震荡电路, 一通电就会发声;无源蜂鸣器则没有自带震荡电路,必须外部提供 2~5Khz 左右的方波驱动, 才能发声。

STM32 的单个 IO 最大可以提供 25mA 电流(来自数据手册),而蜂鸣器的驱动电流是 30mA 左右,两 者十分相近,但是全盘考虑,STM32 整个芯片的电流,最大也就 150mA,如果用 IO 口直接驱 动蜂鸣器,其他地方用电就得省着点了…所以,我们不用 STM32 的 IO 直接驱动蜂鸣器,而是 通过三极管扩流后再驱动蜂鸣器,这样 STM32 的 IO 只需要提供不到 1mA 的电流就足够了。

2.硬件设计 

1)指示灯 DS0

2)蜂鸣器

STM32入门学习 第二天_第22张图片

 NPN 三极管(S8050)来驱动蜂鸣器,R60 主要用于防止蜂鸣器的误发 声。当 PB.8 输出高电平的时候,蜂鸣器将发声,当 PB.8 输出低电平的时候,蜂鸣器停止发声。

3.软件介绍

#include "beep.h"
//初始化 PB8 为输出口.并使能这个口的时钟 
//LED IO 初始化
void BEEP_Init(void)
{
 GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
 //使能 GPIOB 端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //BEEP-->GPIOB.8 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度为 50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure); //根据参数初始化 GPIOB.8
 GPIO_ResetBits(GPIOB,GPIO_Pin_8); //输出 0,关闭蜂鸣器输出
}

void BEEP_Init(void),该函数的作用就是使能 PORTB 的时钟, 同时配置 PB8 为推挽输出。这里的初始化内容跟跑马灯实验几乎是一样的,这里就不做 深入的讲解。

在 main.c 里面编写如下代码:
#include "sys.h"
#include "delay.h"
#include "led.h" 
#include "beep.h"
//ALIENTEK 战舰 STM32 开发板实验 2
//蜂鸣器实验 
int main(void)
{
delay_init(); //延时函数初始化 
LED_Init(); //初始化与 LED 连接的硬件接口
BEEP_Init(); //初始化蜂鸣器端口
while(1)
{ LED0=0;
BEEP=0; 
delay_ms(300);
LED0=1; 
BEEP=1; 
delay_ms(300);
}
}

第六讲 按键输入实验

1.STM32 IO 口简介

STM32F1 的 IO 口已经有了比较详细的介绍。STM32F1 的 IO 口做输入使用的时候,是通过调用函数 GPIO_ReadInputDataBit()来读取 IO 口的状态的。就可以开始我们的代码编写了。 这一章,我们将通过 ALIENTEK 战舰 STM32 开发板上载有的 4 个按钮(WK_UP、KEY0、 KEY1 和 KEY2),来控制板上的 2 个 LED(DS0 和 DS1)和蜂鸣器,其中 WK_UP 控制蜂鸣器, 按一次叫,再按一次停;KEY2 控制 DS0,按一次亮,再按一次灭;KEY1 控制 DS1,效果同 KEY2;KEY0 则同时控制 DS0 和 DS1,按一次,他们的状态就翻转一次。

2.硬件设计

本实验用到的硬件资源有:

1) 指示灯 DS0、DS1

2) 蜂鸣器

3) 4 个按键:KEY0、KEY1、KEY2、和 WK_UP。 

STM32入门学习 第二天_第23张图片

KEY0、KEY1 和 KEY2 是低电平有效的,而 WK_UP 是高电平有效的, 并且外部都没有上下拉电阻,所以,需要在 STM32 内部设置上下拉。

3.软件设计

按键实验工程引入了 key.c 文件以及头文件 key.h。下面我们首先打开 key.c 文件,代码如下:

#include "key.h"
#include "sys.h" 
#include "delay.h" 
//按键初始化函数
void KEY_Init(void) //IO 初始化
{ 
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|
RCC_APB2Periph_GPIOE,ENABLE); //使能 PORTA,PORTE 时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;//GPIOE.2~4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOE, &GPIO_InitStructure); //初始化 GPIOE2,3,4
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //初始化 WK_UP-->GPIOA.0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 设置成输入,下拉 
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.0
}
//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下;1,KEY0 按下;2,KEY1 按下;3,KEY2 按下 ;4,KEY3 按下 WK_UP
//注意此函数有响应优先级,KEY0>KEY1>KEY2>KEY3!!
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1; //按键按松开标志
if(mode)key_up=1; //支持连按 
if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==1))
{
delay_ms(10); //去抖动
key_up=0;
if(KEY0==0)return KEY0_PRES;
else if(KEY1==0)return KEY1_PRES;
else if(KEY2==0)return KEY2_PRES;
else if(KEY3==1)return WKUP_PRES;
}else if(KEY0==1&&KEY1==1&&KEY2==1&&KEY3==0)key_up=1; 
return 0; // 无按键按下
}

接下来我们看看头文件 key.h 里面的代码: 

#ifndef __KEY_H
#define __KEY_H
#include "sys.h"
#define KEY0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)//读取按键 0
#define KEY1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)//读取按键 1
#define KEY2 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)//读取按键 2 
#define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取按键 3(WK_UP) 
#define KEY0_PRES 1 //KEY0 按下
#define KEY1_PRES 2 //KEY1 按下
#define KEY2_PRES 3 //KEY2 按下
#define WKUP_PRES 4 //WK_UP 按下(即 WK_UP/WK_UP)
void KEY_Init(void); //IO 初始化
u8 KEY_Scan(u8); //按键扫描函数
#endif

位操作也可以:

#define KEY0 PEin(4) //PE4
#define KEY1 PEin(3) //PE3 
#define KEY2 PEin(2) //PE2
#define WK_UP PAin(0) //PA0 WK_UP

主函数:

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "beep.h"
//ALIENTEK 战舰 STM32 开发板实验 3
//按键输入实验 
int main(void)
{

u8 key;
delay_init(); //延时函数初始化 
LED_Init(); //LED 端口初始化
KEY_Init(); //初始化与按键连接的硬件接口
BEEP_Init(); //初始化蜂鸣器端口
LED0=0; //先点亮红灯
while(1)
{
key =KEY_Scan(0); //得到键值
 if(key)
{ switch(t)
{ case WKUP_PRES: //控制蜂鸣器
BEEP=!BEEP;break;
case KEY2_PRES: //控制 LED0 翻转
LED0=!LED0;break;
case KEY1_PRES: //控制 LED1 翻转
LED1=!LED1;break;
case KEY0_PRES: //同时控制 LED0,LED1 翻转
LED0=!LED0;
LED1=!LED1;break;
}
}else delay_ms(10); 
}
}

你可能感兴趣的:(stm32,单片机,学习)