一、本章简介
本章以core-G1【STM32F103C8T8】核心板 +Q1 cenozoic开发板 矩阵按键扫描实验 之入门系列4工程为例,介绍STM32关于GPIO的配置方法,将STM32的GPIO设置为输入模式,并使用此来发版上的4*3按键来做矩阵按键扫描。二、实验平台
1、硬件:core-G1核心板、Q1 cenozoic开发板、三根杜邦线
2、编译软件:MDK-RAM Plus V5.26.2.0
3、STM32F10X固件库版本:V3.5
4、仿真器:QQ14A编译调试器
三、版权声明作者:职业劝退师
声明:转载请注明出处。
纠错:1911996023@qq.com
本例程开源资料下载地址:
http://www.enmaking.com/material/ma_AIIIroF9
core-G1【STM32F103C8T8】核心板购买链接:
QQ14A编译调试器购买链接:
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-22623360017.13.407d38d5ciC9zV&id=624413749124
四、实验前提
1、在进行本文步骤前,请先阅读以下章节
1)《Cortex-M3权威指南(中文)》的第一章至第五章章节。
2)《STM32中文参考手册_V10》的第八章节。
2、在进行本文步骤前,请先实现以下章节:
1)MDK5的软件安装。安装教程链接如下
http://www.enmaking.com/article/ar_cXHjU6Uj
2)阅读《core-G1【STM32F103C8T8】核心板 独立按键实验 之入门系列3》文章,链接如下
http://www.enmaking.com/article/ar_0dYRShX2
五、基础知识
当MCU的IO口不够用的情况下,通过矩阵按键扫描,可以减少MCU的IO口使用,节省硬件资源。核心思想为通过三组GPIO全部输出低电平,四组GPIO全部输出高电平。当接收到的数据,四组GPIO不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,三组GPIO输出高电平,四组GPIO输出低电平,然后根据接收到的三组GPIO的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。
六、硬件原理
1、原理图2、由上面三图可知
名称 引脚 控制方法
G1 PA9 设置成推挽输出,置位高电平
R1 PA8 设置成推挽输出,置位高电平
B1 PB15 设置成推挽输出,置位高电平
G2 PB14 设置成推挽输出,置位高电平
R2 PB13 设置成推挽输出,置位高电平
B2 PB12 设置成推挽输出,置位高电平
G3 PB8 设置成推挽输出,置位高电平
R3 PB9 设置成推挽输出,置位高电平
B3 PB4 设置成推挽输出,置位高电平
G4 PA15 设置成推挽输出,置位高电平
R4 PB5 设置成推挽输出,置位高电平
B4 PA4 设置成推挽输出,置位高电平
KL1 PA1 设置成下拉输入
KL2 PA0 设置成下拉输入
KL3 PA2 设置成下拉输入
KL4 PA3 设置成下拉输入
KS1 PB10 设置成上拉输入
KS2 PB1 设置成上拉输入
KS3 PB0 设置成上拉输入
这里我们需要配置引脚有很多,但是大部分都直接和对应的外围设备连接在一起了,现在只需要将下面列出的接口用杜邦线连接在一起就可以了。
Q1 cenozoic开发板
B9 -> B17
B10-> B15
B11-> B14
3、注意事项
1)将core-G1开板上后面的SB1接口断开。
2) Q1 cenozoic开发板上的K13拨码开关的1、3、5向上拨,2、4、6向下拨。
现在我们知道要操作哪些IO口,就可以进行程序编写了。
七、实验步骤
1、编写按键驱动程序。
void KEY_Init_Q1(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC->APB2ENR|=1<<2; //使能PORTB时钟
RCC->APB2ENR|=1<<3; //使能PORTB时钟
RCC->APB2ENR|=1<<4; //使能PORTC时钟
//KL===============================================================
GPIO_InitStructure.GPIO_Pin =
GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
KL1=0;KL2=0;KL3=0;KL4=0;
//KS==============================================================
GPIO_InitStructure.GPIO_Pin =
GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
2、添加有关操作按键的GPIO口宏定义,方便操作和调动。
#define KL1 PAout(1)
#define KL2 PAout(0)
#define KL3 PAout(2)
#define KL4 PAout(3)
#define KS1 PBout(10)
#define KS2 PBout(1)
#define KS3 PBout(0)
#define KL1in PAin(1)
#define KL2in PAin(0)
#define KL3in PAin(2)
#define KL4in PAin(3)
#define KS1in PBin(10)
#define KS2in PBin(1)
#define KS3in PBin(0)
3、将驱动程序添加到自己的工程中4、编写自己的业务代码
void KEY_ScanQ1(void)
{
if(Key_Value==0)
{
if(KS1in==0)
{
delay_ms(10);
if(KS1in==0)
{
IO_reversal();
if(KL1in==0)
{
Key_Value=1;
}
if(KL2in==0)
{
Key_Value=4;
}
if(KL3in==0)
{
Key_Value=7;
}
if(KL4in==0)
{
Key_Value=10;
}
IO_reversal();
return ;
}
}
if(KS2in==0)
{
delay_ms(10);
if(KS2in==0)
{
IO_reversal();
if(KL1in==0)
{
Key_Value=2;
}
if(KL2in==0)
{
Key_Value=5;
}
if(KL3in==0)
{
Key_Value=8;
}
if(KL4in==0)
{
Key_Value=11;
}
IO_reversal();
return ;
}
}
if(KS3in==0)
{
delay_ms(10);
if(KS3in==0)
{
IO_reversal();
if(KL1in==0)
{
Key_Value=3;
}
if(KL2in==0)
{
Key_Value=6;
}
if(KL3in==0)
{
Key_Value=9;
}
if(KL4in==0)
{
Key_Value=12;
}
IO_reversal();
return ;
}
}
}
}
void IO_reversal(void)
{
static u8 flag=0;
GPIO_InitTypeDef GPIO_InitStructure;
if(flag)
{
//KL===============================================================
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
KL1=0;KL2=0;KL3=0;KL4=0;
//KS==============================================================
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
flag=0;
}else
{
//KL===============================================================
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//KS==============================================================
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
KS1=0;KS2=0;KS3=0;
flag=1;
}
}
extern u8 Key_Value;
int main(void)
{
JTAG_Set(1);//ENABLE SWD
delay_init(72);
LED_Init();
KEY_Init_Q1();
while (1)
{
KEY_ScanQ1();
if(Key_Value)
{
if((KS1in==1)&&(KS2in==1)&&(KS3in==1))
{
switch(Key_Value)
{
case 1: R1=~R1;break;
case 2: B1=~B1;break;
case 3: G1=~G1;break;
case 4: R2=~R2;break;
case 5: B2=~B2;break;
case 6: G2=~G2;break;
case 7: R3=~R3;break;
case 8: B3=~B3;break;
case 9: G3=~G3;break;
case 10: R4=~R4;break;
case 11: B4=~B4;break;
case 12: G4=~G4;break;
default:Key_Value=0; break;
}
Key_Value=0;
}
}
}
}
最后编译并将程序烧录到开发版中。
八、注意事项
暂无
九、实验结果
12个按键分别控制4个RGB灯的三种颜色的亮灭,每按下一次按键,灯的状态与原来相反。