前言:  

      这里我们接着上一次的LK32T102 单片机 操作GPIO实现流水灯(1)来继续深入学习LK32T102 单片机的GPIO口操作。这里我们为大家讲解一下GPIO口 如何实现(主板按钮 与 矩阵按钮)按键扫描和蜂鸣器的启动与停止

一、蜂鸣器

        由这张原理图我们可以知道蜂鸣器的IO口是PA12,所以我们就可以直接通过对这个IO口置0或者置1来达到操作蜂鸣器开启与关闭。

h610 bios蜂鸣器_c语言

<BEEP.h>

#ifndef __BEEP_H
#define __BEEP_H	

#include <SC32F5832.h>
#include <GPIO.h>

#define BUZ_TGL 		PA_OUT_TOGGLE(12)		//翻转蜂鸣器

#define BUZ_OFF 		PA_OUT_HIGH(12)	//PA12输出高电平 关闭蜂鸣器
#define BUZ_ON 			PA_OUT_LOW(12)	//PA12输出低电平 开启蜂鸣器


void BUZ_init(void);	//蜂鸣器初始化

#endif

<BEEP.c>

#include <SC32F5832.h>
#include <DevInit.h>
#include "delay.h"
#include <LED.h>
#include <GPIO.h>
#include <BEEP.h>


/***************************************************************
						蜂鸣器初始化
****************************************************************/
void BUZ_init(void)     
{
	//蜂鸣器 -> PA12   初始化IO口
	GPIO_AF_SEL(DIGITAL, PA, 12, 0);  
	//使能蜂鸣器接口为输出
  PA_OUT_ENABLE(12);	
	//关蜂鸣器
	buzzer_off;
}

<Devlint.c>

#include <SC32F5832.h>
#include <DevInit.h>
#include "delay.h"
#include "CLK.h"
#include <LED.h>
#include <KEY.h>
#include <BEEP.h>
#include <OLED.h>
#include "ULN2003.h"
#include "HC_SR501.h"
#include "GY302.h"
#include "smg_4.h"
#include <DS2.h>

/***************************************************************
						系统初始化
****************************************************************/
void Device_Init()
{
	//-- 时钟 初始化 --//
	SysCLK_Init();			// 系统时钟初始化
	
	//-- 元器件 初始化 --//
    BUZ_init();    // 蜂鸣器 初始化
}

<main.c>

/* Includes ------------------------------------------------------------------*/
#include <SC32F5832.h>
#include <DevInit.h>
#include "delay.h"
#include <GPIO.h>
#include <LED.h>
#include <BEEP.h>
#include <KEY.h>
#include <OLED.h>
#include "ULN2003.h"
#include "HC_SR501.h"
#include "GY302.h"
#include "keybroad4x4.h"
#include "LCD12864.h"

int main()
{

	delay_ms(100);	    //延时100ms	
	Device_Init();	//系统初始化,我将 蜂鸣器初始化函数 放在了这里面
    while(1)
    {
        BUZ_ON;
        delay_ms(1000);
        BUZ_OFF;
        delay_ms(1000);    // 蜂鸣器以1HZ 一响一停
    } 
}

二、主控板按钮

四个主按钮(S2、S3、S4、S5),S1为复位按钮不需要我们进行操作。操作主按钮的方式与51单片机的操作方法大致相同。使用 if 函数 对主按钮来进行按键扫描,在按键扫描函数过后加入按键功能。由下图可知,主控按钮分别对应这PA0、PA1、PA10、PA11这四个IO口。

h610 bios蜂鸣器_开发语言_02

 <key.h>

#ifndef __KEY_H
#define __KEY_H	 

#include <SC32F5832.h>
#include <GPIO.h>

#define S2	((Key_TrgValue >> 0) & 0x01)
#define S3	((Key_TrgValue >> 1) & 0x01)
#define S4	((Key_TrgValue >> 10) & 0x01)
#define S5	((Key_TrgValue >> 11) & 0x01)

void KEY_init(void);	//主板按键初始化
void Key_ReadSta_Task(void);	//主板按键扫描
void Key_Ctrl(void);	//主板按键控制

#endif

<key.c>

#include <SC32F5832.h>
#include <DevInit.h>
#include <KEY.h>
#include "delay.h" 
#include <LED.h>
#include <BEEP.h>

uint16_t Key_TrgValue;
uint16_t Key_ContValue;

/***************************************************************
						主板按键初始化
****************************************************************/
void KEY_init(void)
{
	//按键 PA0 -> S2 PA1 -> S3 PA10 -> S4 PA11 -> SB5
	GPIO_AF_SEL(DIGITAL, PA, 0, 0);       // 按键S2
	GPIO_AF_SEL(DIGITAL, PA, 1, 0);       // 按键S3
	GPIO_AF_SEL(DIGITAL, PA, 10, 0);      // 按键S4
	GPIO_AF_SEL(DIGITAL, PA, 11, 0);      // 按键S5
	
	//按键端口配置 浮空
	GPIO_PUPD_SEL(PUPD_PU, PA, 0 );
	GPIO_PUPD_SEL(PUPD_PU, PA, 1 );
	GPIO_PUPD_SEL(PUPD_PU, PA, 10 );
	GPIO_PUPD_SEL(PUPD_PU, PA, 11 );
	
	//IO口输入使能	
	PA_OUT_DISABLE(0);	  
	PA_OUT_DISABLE(1);	  
	PA_OUT_DISABLE(10);	 
	PA_OUT_DISABLE(11);

}

/***************************************************************
						主板按键控制函数
****************************************************************/
void Key_Ctrl(void)
{
	Key_ReadSta_Task();
	
	if(S2 == 1)	
	{
		LED_TGL(0);    // 按下LED1在 亮与灭 之间切换
	}
		
	if(S3 == 1)	
	{
		BUZ_TGL;        // 按下蜂鸣器 在 响与不响 之间切换
	}

	if(S4 == 1)
	{
		LED_TGL(2);
		LED_TGL(3);    // 按下LED3、LED4在 亮与灭 之间切换
	}

	if(S5 == 1)
	{
		LED_TGL(4);    
		LED_TGL(5);
		LED_TGL(6);    // 按下LED5、LED6、LED7在 亮与灭 之间切换
	}	
}

/***************************************************************
						主板按键S2、S3、s4、s5扫描
****************************************************************/
void Key_ReadSta_Task(void)
{	
	uint16_t ReadKey_Data = 0; 
	
	ReadKey_Data = (PA -> PIN) ^ 0x0c03;//读取按键输入数据
	ReadKey_Data &= 0x0c03;		//将原键值取反
	Key_TrgValue = ReadKey_Data & ( ReadKey_Data ^ Key_ContValue );	//保存键值
	Key_ContValue = ReadKey_Data;		//保存键值作为按键松开标志
}

<Devlint.c>

#include <SC32F5832.h>
#include <DevInit.h>
#include "delay.h"
#include "CLK.h"
#include <LED.h>
#include <KEY.h>
#include <BEEP.h>
#include <OLED.h>
#include "ULN2003.h"
#include "HC_SR501.h"
#include "GY302.h"
#include "smg_4.h"
#include <DS2.h>

/***************************************************************
						系统初始化
****************************************************************/
void Device_Init()
{
	//-- 时钟 初始化 --//
	SysCLK_Init();			// 系统时钟初始化
	
	//-- 元器件 初始化 --//
    KEY_init();             // 按键 初始化
	LED_init();				// LED 初始化
    BUZ_init();             // 蜂鸣器 初始化
}

<main.c>

/* Includes ------------------------------------------------------------------*/
#include <SC32F5832.h>
#include <DevInit.h>
#include "delay.h"
#include <GPIO.h>
#include <LED.h>
#include <BEEP.h>
#include <KEY.h>
#include <OLED.h>
#include "ULN2003.h"
#include "HC_SR501.h"
#include "GY302.h"
#include "keybroad4x4.h"
#include "LCD12864.h"

int main()
{
    delay_ms(100);	    //延时100ms	
	Device_Init();	//系统初始化
    while(1)
    {
        Key_Ctrl(); 
    }
}

三、矩阵按键

4x4的点阵,所以我们采用的是行、列扫描的方式,这里为四行的IO口置1,四列的IO口置0;当没有按键按下时, 四行的IO检测出来就全是高电平;如果有按键按下,那个按键所处的哪一行的IO口就会变为高电平。然后再反过来四行的IO口置0,四列的IO口置1,当没有按键按下时, 四列的IO检测出来就全是高电平;如果有按键按下,那个按键所处的哪一列的IO口就会变为高电平。这样我们相当于知道了x、y的坐标,这样我们就可以直接 知道那个按键被按下。

h610 bios蜂鸣器_h610 bios蜂鸣器_03

<keybroad.c>

/*
上拉输入:有上拉电阻
                                按键未按下时端口接高电平,即高电平 1   状态---3.3v
                                按键按下时端口接低电平,即低电平 0  状态-------0
下拉输入:有下拉电阻
                                 按键未按下时端口接低电平,即低电平 0  状态---0v
                                 按键按下时端口接高电平,即高电平  1  状态------3.3v
*/
	
	
/**
* 4*4矩阵键盘接线说明
*	PB8 	-> 	R1		//row
*	PB9 	-> 	R2
*	PB10 	-> 	R3
*	PB11 	-> 	R4

*	PB12 	-> 	C1		//column
*	PB13 	-> 	C2
*	PB14 	-> 	C3
*	PB15 	-> 	C4
*/
	
#include <SC32F5832.h>
#include <DevInit.h>
#include "LED.h"
#include "BEEP.h"
#include "keybroad4x4.h"
#include "LCD12864.h"    
 

//采用翻转扫描的方法( PE口的高8位 )
//程序放在定时器中断函数中 10ms扫描一次

#define PORTE PB -> PIN	//读PB口引脚电压
u8 key = 22;

uint8_t key_scanf()
{
	uint8_t row  = 0;
	uint8_t column = 0;
	uint8_t key_value = 0;
	uint8_t tmp = 0;
	static uint8_t count = 0;
	
	/*------------- PB 高8位端口配置 -------------*/
	PB->OUTEN|=0XFF00;		//高8位 输出使能
	
	PB->OUT &= 0X00FF;		//低8位(H)
	PB->OUT |= 0XF000;		//高8位:低4(L),高4(H)
		
	//GPIOE 高8位端口 高4位为 上拉输入
	PB -> OUTEN &= 0X0FFF;//高8位:低4位(输入使能)
	GPIO_PUPD_SEL(PUPD_PU, PB, 12 );
	GPIO_PUPD_SEL(PUPD_PU, PB, 13 );
	GPIO_PUPD_SEL(PUPD_PU, PB, 14 );
	GPIO_PUPD_SEL(PUPD_PU, PB, 15 );

	
	tmp = PORTE>>8;
	
	if(tmp != 0XF0)
	{
		if(count < 2)
		{
			count ++;
		}
	}
	else
	{
		count = 0;
	}
	
	if(count == 2)
	{
		column = tmp & 0XF0;
		
		/*------------- PB 高8位端口配置 -------------*/
		PB->OUTEN|=0XFF00;		//高8位 输出使能
		
		PB->OUT &= 0X00FF;		//低8位(H)
		PB->OUT |= 0X0F00;		//高8位:低4(H),高4(L)
		
		//GPIOE 高8位端口 高4位为 上拉输入
		PB -> OUTEN &= 0XF0FF;//高8位:低4位(输入使能)
		GPIO_PUPD_SEL(PUPD_PU, PB, 8 );
		GPIO_PUPD_SEL(PUPD_PU, PB, 9 );
		GPIO_PUPD_SEL(PUPD_PU, PB, 10 );
		GPIO_PUPD_SEL(PUPD_PU, PB, 11 );
		
		row = (PORTE>>8) & 0X0F;
		
		switch(column|row)
		{
			//按键对应的码表 可根据需求调整返回值 
			case 0XEE:
				key_value = 1; 	//keyboard 1
				break;
			case 0XDE: 
				key_value = 2; 	//keyboard 2
				break;	
			case 0XBE:
				key_value = 3;	//keyboard 3
				break;                
			case 0X7E:
				key_value = 4; //keyboard A
				break;                                              
			case 0XED:
				key_value = 5;	//keyboard 4
				break;
			case 0XDD: 
				key_value = 6; 	//keyboard 5 
				break;
			case 0XBD:
				key_value = 7; 	//keyboard 6
				break;
			case 0X7D:
				key_value = 8; //keyboard B
				break;                                  
			case 0XEB: 
				key_value = 9; 	//keyboard 7
				break;
			case 0XDB:
				key_value = 10;	//keyboard 8
				break;
			case 0XBB:
				key_value = 11;	//keyboard 9
				break;
			case 0X7B:
				key_value = 12;	//keyboard C
				break;                                    
			case 0XE7:
				key_value = 13;	//keyboard *
			break;
			case 0XD7:
				key_value = 14; 	//keyboard 0
				break;
			case 0XB7:
				key_value = 15;	//keyboard #
			break;
			case 0X77:
				key_value = 16; //keyboard D
				break;
			
			default:  
				break;     
		}
	}
	
	if((PORTE &0xff00) == 0XF000)
	{
		count = 0;
	}
	
	return key_value;
}


void Key4x4(void)
{
	uint16_t i = 0;
	i = key_scanf();
	
	switch (i)
	{
		case 1 :
			LED_TGL(1);
			break;
		
		case 2:
			LED_TGL(0);
			break;
		
		case 3:
			LED_TGL(2);
			break;
		
		case 4 :
			LED_TGL(3);
			break;
		
		case 5:
			LED_TGL(4);
			break;
		
		case 6:
			LED_TGL(5);
			break;
		
		case 7:
			LED_TGL(6);
			break;
		
		case 8:
			LED_TGL(7);
			break;
		
		case 9:
			BUZ_TGL;
			break;
		
		case 10:
			;
			break;
		
		case 11:
			;
			break;
		
		case 12:
			;
			break;
		
		case 13:
			;
			break;
		
		case 14:
			;
			break;
		
		case 15:
			;
			break;
		
		case 16:
			;
			break;
	}	
}

        这里我就给了1-9的按键赋予了功能,之后的没有赋予功能的按键,我们就用空语句。

<keybroad.h>

#ifndef _keybroad4x4_h_
#define _keybroad4x4_h_

#include <SC32F5832.h>
#include <DevInit.h>

uint8_t key_scanf(void);    // 按钮扫描 函数
void Key4x4(void);    // 按键功能 函数

#endif

<main.c>

/* Includes ------------------------------------------------------------------*/
#include <SC32F5832.h>
#include <DevInit.h>
#include "delay.h"
#include <GPIO.h>
#include <LED.h>
#include <BEEP.h>
#include <KEY.h>
#include <OLED.h>
#include "ULN2003.h"
#include "HC_SR501.h"
#include "GY302.h"
#include "keybroad4x4.h"
#include "LCD12864.h"


int main()
{
    delay_ms(100);	    //延时100ms	
	Device_Init();	//系统初始化
    while(1)
    {
        Key4x4();    // 按钮功能 函数
    }
}