STM32F103基础教程:使用寄存器控制3×3矩阵键盘和5161AS数码管

1、前言

本篇介绍的是基于STM32——寄存器版本的矩阵键盘控制5161as数码管显示数字的实例。我们赋予每一个按键从1到9的数字,当我们按下对应的数字按键时,程序会检测出被按下的是哪一个按键并在5261as数码管上显示相应的数字。

2、矩阵键盘

(1)原理

为了读取每一个按键的状态,最简单粗暴的方法就是给每一个按键都接一个引脚来读取按键状态。但对于一个3*3的键盘来说,就要占用9个I/O口。所以我们选择矩阵键盘。其本质就是用6条I/O线来进行9个按键的控制。用3条I/O线作为行线,三条I/O线作为列线,将按键放在行列线的交叉点上。当按下按键后对应的行列导通,通过扫描每行每列的方法来确定按键位置。其电路如图所示:

(2)实现方法

按键位置的读取有两种:逐行/逐列扫描行列扫描
本章使用的是逐行/逐列扫描的方法:先将每一列引脚设置为推免输出1(高电平),每一行引脚设置为0(输入下拉),当有按键被按下后行列导通,对应的行读入的引脚状态就会变为1(高电平),这样就确定了按键所在的行。再将行设置为推免输出,列设置为输入下拉用同样的方法读出按键所在的列。这样就确定了按键的具体位置。

3、5161as数码管

(1)原理

5261as数码管分为共阴极和共阳极,本章使用的是共阴极数码管,其原理如图所示:
请添加图片描述
5261as数码管由8个二极管组成一个数字8和一个小数点,这些二极管共用一个阴极。对应的10个引脚,除过两边中间的引脚是共阴极外,其他8个引脚分别控制八个不同位置的二极管,控制关系如图(a)所示。

(2)实现方法

对于共阴极数码管来说,将8个控制二极管的引脚分别接到不同的I/O端口上,两个共阴极的引脚接地。只要设置对应的I/O端口输出高电平,其他为低电平就能显示对应数字。比如要显示数字1,就可以将控制二极管e,f的引脚设置为推免输出高电平,其他为推免输出低电平,就可以只点亮e,f二极管。

4、硬件连接

我选择的键盘I/O接口是PB8-PB13,数码管I/O接口是PA0-PA7。实物连接如图所示:

5、程序设计

1、key.c中主要实现的是矩阵键盘逐行/逐列扫描。具体代码如下:

#include "key.h"
#include "delay.h"
#include "stm32f10x.h"



u8 KEY_Scan(void)
{
    u8 i=0,j=0;//用来记录按键所在的行和列
    RCC->APB2ENR |=1<<3;//使能时钟
    
    GPIOB->CRH&=0XFF000000;
	GPIOB->CRH|=0X00333888;//引脚PB8-PB10输入,PB11-PB13推免输出 
	GPIOB->ODR&=0X00000000;//将PB8-PB10设置为输入下拉
    PBout(11)=1;//PB11-PB13推免输出高电平
    PBout(12)=1;
    PBout(13)=1;
    PBin(8)=0;//初始化PBin的值
    PBin(9)=0;
    PBin(10)=0;
	if(PBin(8)==1||PBin(9)==1||PBin(10)==1)//第一次判断
	{
		delay_ms(10);//去抖动 
		if(PBin(8)==1)//再次判断
        {
            i=1;
        }else if(PBin(9)==1)
        {
            i=2;
        }else if(PBin(10)==1)
        {
            i=3;
        }else{
            return 0;
        }
    }
    
    //同上改变行列引脚状态
    GPIOB->CRH&=0XFF000000;	 
	GPIOB->CRH|=0X00888333; 			 
	GPIOB->ODR&=0X00000000;
    PBout(8)=1;
    PBout(9)=1;
    PBout(10)=1;
    PBin(11)=0;
    PBin(12)=0;
    PBin(13)=0;
	if(PBin(11)==1||PBin(12)==1||PBin(13)==1)
	{
		delay_ms(10);//去抖动 
		if(PBin(11)==1)//行
        {
            j=1;
        }else if(PBin(12)==1)
        {
            j=2;
        }else if(PBin(13)==1)
        {
            j=3;
        }else{
            return 0;
        }
    }
    
    //根据行列判断按键位置
    if(j==1&&i==1)
        return 1;
    else if(j==1&&i==2)
        return 2;
    else if(j==1&&i==3)
        return 3;
    else if(j==2&&i==1)
        return 4;
    else if(j==2&&i==2)
        return 5;
    else if(j==2&&i==3)
        return 6;
    else if(j==3&&i==1)
        return 7;
    else if(j==3&&i==2)
        return 8;
    else if(j==3&&i==3)
        return 9;
    else
        return 0;

}

2、led.c中主要控制5161as数码管各个引脚状态。具体代码如下:

#include "sys.h"   
#include "led.h"

//初始化PA8和PD2为输出口.并使能这两个口的时钟		    
//LED IO初始化

void LED_Init(void)
{
	RCC->APB2ENR|=1<<2;    //使能PORTA时钟	   	  
	GPIOA->CRL&=0X00000000; 
	GPIOA->CRL|=0X33333033;//PA0-7 推挽输出 
    JTAG_Set(SWD_ENABLE);	//关闭JTAG,开启SWD
    GPIOA->ODR&=0X00000000;//全部输出低电平
}

//设置每位数字输出的二极管状态
void LED_1(void)
{
    PAout(1)=0;
    PAout(0)=0;
    PAout(5)=0;
    PAout(6)=0;
    PAout(7)=1;
    PAout(3)=1;
    PAout(4)=0;
}
void LED_2(void)
{
    PAout(1)=1;
    PAout(0)=1;
    PAout(5)=0;
    PAout(6)=1;
    PAout(7)=1;
    PAout(3)=0;
    PAout(4)=1;
}
void LED_3(void)
{
    PAout(1)=1;
    PAout(0)=1;
    PAout(5)=1;
    PAout(6)=1;
    PAout(7)=0;
    PAout(3)=0;
    PAout(4)=1;
}
void LED_4(void)
{
    PAout(1)=0;
    PAout(0)=1;
    PAout(5)=1;
    PAout(6)=0;
    PAout(7)=0;
    PAout(3)=1;
    PAout(4)=1;
}
void LED_5(void)
{
    PAout(1)=1;
    PAout(0)=0;
    PAout(5)=1;
    PAout(6)=1;
    PAout(7)=0;
    PAout(3)=1;
    PAout(4)=1;
}
void LED_6(void)
{
    PAout(1)=1;
    PAout(0)=0;
    PAout(5)=1;
    PAout(6)=1;
    PAout(7)=1;
    PAout(3)=1;
    PAout(4)=1;
}
void LED_7(void)
{
    PAout(1)=1;
    PAout(0)=1;
    PAout(5)=1;
    PAout(6)=0;
    PAout(7)=0;
    PAout(3)=0;
    PAout(4)=0;
}
void LED_8(void)
{
    PAout(1)=1;
    PAout(0)=1;
    PAout(5)=1;
    PAout(6)=1;
    PAout(7)=1;
    PAout(3)=1;
    PAout(4)=1;
}
void LED_9(void)
{
    PAout(1)=1;
    PAout(0)=1;
    PAout(5)=1;
    PAout(6)=1;
    PAout(7)=0;
    PAout(3)=1;
    PAout(4)=1;
}

3、text.c中主要进行按键的判断然后调用led.c中显示数字的代码,并打印在串口中,具体代码如下:

#include "sys.h"
#include "usart.h"		
#include "delay.h"	
#include "key.h" 
#include "led.h" 

int main(void)
{		 
	vu8 t;
	Stm32_Clock_Init(9); 	//系统时钟设置
	delay_init(72);	     	//延时初始化 
    uart_init(72,9600);     //初始化串口通信
    LED_Init();             //初始化端口
    printf("正常进入");
	while(1)
	{
		t=KEY_Scan();		//得到键值
        printf("t的值为:%d\n",t);
		switch(t)
		{				 
			case 1:
                printf("你按下了:1\r\n");//按键数值打印在串口
                LED_1();//显示对应数字
				break;
			case 2:
				printf("你按下了:2\r\n");
                LED_2();
				break;
            case 3:
				printf("你按下了:3\r\n");
                LED_3();
				break;
            case 4:
				printf("你按下了:4\r\n");
                LED_4();
				break;
            case 5:
				printf("你按下了:5\r\n");
                LED_5();
				break;
            case 6:
				printf("你按下了:6\r\n");
                LED_6();
				break;
            case 7:
				printf("你按下了:7\r\n");
                LED_7();
				break;
            case 8:
				printf("你按下了:8\r\n");
                LED_8();
				break;
            case 9:
				printf("你按下了:9\r\n");
                LED_9();
				break;
			default:
                printf("无按键按下\r\n");
				delay_ms(1000);	
                break;
		}
          
	}		 
}

4、对应的头文件中为各个函数的定义,具体代码如下:
key.h:

#ifndef __KEY_H
#define __KEY_H	 
#include "sys.h"

u8 KEY_Scan(void);		//按键扫描函数

#endif

led.h:

#ifndef __LED_H
#define __LED_H	 
#include "sys.h"
  
//LED端口定义
//#define LED_a PAout(1)
//#define LED_b PAout(0)
//#define LED_c PAout(5)
//#define LED_d PAout(6)
//#define LED_e PAout(7)
//#define LED_f PAout(3)
//#define LED_g PAout(4)

void LED_Init(void);	//初始化		 
void LED_1(void);
void LED_2(void);
void LED_3(void);
void LED_4(void);
void LED_5(void);
void LED_6(void);
void LED_7(void);
void LED_8(void);
void LED_9(void);				    
#endif

6、运行结果

1、串口运行结果

2、5161as数码管运行结果

物联沃分享整理
物联沃-IOTWORD物联网 » STM32F103基础教程:使用寄存器控制3×3矩阵键盘和5161AS数码管

发表评论