前言:
这里我们接着上一次的LK32T102 单片机 操作GPIO实现流水灯(1)来继续深入学习LK32T102 单片机的GPIO口操作。这里我们为大家讲解一下GPIO口 如何实现(主板按钮 与 矩阵按钮)按键扫描和蜂鸣器的启动与停止。
一、蜂鸣器
由这张原理图我们可以知道蜂鸣器的IO口是PA12,所以我们就可以直接通过对这个IO口置0或者置1来达到操作蜂鸣器开启与关闭。
<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口。
<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的坐标,这样我们就可以直接 知道那个按键被按下。
<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(); // 按钮功能 函数
}
}