1.目的
本次STM32实验希望通过扫描式按键对LED灯进行控制。这种方式需要CPU不断扫描用户是否按下按键,效率较低。
下一篇的中断式按键效率较高。
2.按键电路
查看电路原理图我们可以发现有S1,S2,S3三个按键,它们都是左端接GPIO口,右端接地,可以根据这个电路特性写按键的控制代码。
3.程序源代码
led.h源代码更新:
相对于之前的LED控制的代码,这次的代码在led.h添加了宏定义LED_REV用于控制LED灯的翻转(如果LED灯开始是关闭状态,执行LED_REV后点亮;如果LED灯开始为点亮状态,执行LED_REV后关闭)。
#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"
#define ON 0
#define OFF 1
#define LED2(a) if(a) GPIO_SetBits( GPIOE, GPIO_Pin_5 ); else GPIO_ResetBits( GPIOE, GPIO_Pin_5 )
#define LED3(a) if(a) GPIO_SetBits( GPIOB, GPIO_Pin_5 ); else GPIO_ResetBits( GPIOB, GPIO_Pin_5 )
//新添加的代码
#define LED2_REV GPIO_WriteBit(GPIOE, GPIO_Pin_5, (BitAction)(1-(GPIO_ReadOutputDataBit(GPIOE, GPIO_Pin_5))))
#define LED3_REV GPIO_WriteBit(GPIOB, GPIO_Pin_5, (BitAction)(1-(GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_5))))
void LED_Init(void);
#endif
key.h源代码:
#ifndef __KEY_H
#define __KEY_H
#include "stm32f10x.h"
//用宏定义表示开关的开闭状态
#define KEY_ON 0
#define KEY_OFF 1
//按键初始化函数
void KEY_Init(void);
//不精确延时函数
void Delay( __IO u32 nCount );
//三个按键的扫描函数
uint8_t Key1_Scan( void );
uint8_t Key2_Scan( void );
uint8_t Key3_Scan( void );
#endif
key.c源代码:
#include "stm32f10x.h"
#include "key.h"
//通过循环产生一个延时
void Delay( __IO u32 nCount )
{
for( ; nCount > 0; --nCount );
}
/**********************************************
按键初始化函数,与普通GPIO口初始化类似。
但是输入输出方式使用上拉输入,速率也不一样。
**********************************************/
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOE, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init( GPIOE, &GPIO_InitStructure );
}
/*******************************************************
按键S1的扫描函数。
在检测到S1处于按下状态时,先通过延时去除抖动。
当再次检测到S1按键处于按下状态时,则认为用户按下了S1。
如果while循环检测到用户释放按键,那么返回KEY_ON。
*******************************************************/
uint8_t Key1_Scan( void )
{
if( GPIO_ReadInputDataBit( GPIOE, GPIO_Pin_4 ) == KEY_ON )
{
Delay(10000);
if( GPIO_ReadInputDataBit( GPIOE, GPIO_Pin_4 ) == KEY_ON )
{
while( GPIO_ReadInputDataBit( GPIOE, GPIO_Pin_4 ) == KEY_ON );
return KEY_ON;
}
else return KEY_OFF;
}
else return KEY_OFF;
}
uint8_t Key2_Scan( void )
{
if( GPIO_ReadInputDataBit( GPIOE, GPIO_Pin_3 ) == KEY_ON )
{
Delay(10000);
if( GPIO_ReadInputDataBit( GPIOE, GPIO_Pin_3 ) == KEY_ON )
{
while( GPIO_ReadInputDataBit( GPIOE, GPIO_Pin_3 ) == KEY_ON );
return KEY_ON;
}
else return KEY_OFF;
}
else return KEY_OFF;
}
uint8_t Key3_Scan( void )
{
if( GPIO_ReadInputDataBit( GPIOE, GPIO_Pin_2 ) == KEY_ON )
{
Delay(10000);
if( GPIO_ReadInputDataBit( GPIOE, GPIO_Pin_2 ) == KEY_ON )
{
while( GPIO_ReadInputDataBit( GPIOE, GPIO_Pin_2 ) == KEY_ON );
return KEY_ON;
}
else return KEY_OFF;
}
else return KEY_OFF;
}
主函数main.c源代码:
#include "stm32f10x.h"
#include "led.h"
#include "key.h"
/******************************************
当按下S1时LED2翻转。当按下S2时LED3翻转。
当按下S3时LED2和LED3同时翻转。
******************************************/
int main(void)
{
LED_Init();
KEY_Init();
while(1)
{
if( Key1_Scan() == KEY_ON )
{
LED2_REV;
}
if( Key2_Scan() == KEY_ON )
{
LED3_REV;
}
if( Key3_Scan() == KEY_ON )
{
LED2_REV;
LED3_REV;
}
}
}