首先感谢葱花鱼的分享http://www.openedv.com/posts/list/1722.htm
下面是4*4矩阵键盘的思路:为了获取矩阵键盘的输入,并尽量少占用CPU,我的想法是将键盘上的A键作为扫面触发键,当按下A键时产生中断,然后在中断函数中启动键盘扫描。
选择B[7:0]作为矩阵键盘的引脚
B[3:0]为行,B[7:4]为列
初始时,以键盘上的A作为中断源,B[7]输出低电平,B[0]产生中断时,开启扫描
注意:由于中断线默认对应的是PORTA,这里需要进行中断线重映射,将中断线有PORTA指向PORTB
AFIO->EXTICR[0] &= 0xfffffff0;
AFIO->EXTICR[0] |= 0x00000001;
这一点我也是看了很久的手册才搞明白啊~
下面贴出代码
//matrixKey.c
#include"stm32f10x_lib.h"
#include"matrixKey.h"
#include "delay.h"
#include "usart.h"
#include "LED.h"
#include "sys.h"
u8 trg;
u8 cont = 0;
u8 keyData;
void keyRead(){
keyData = (PBin(4)+2*PBin(5)+4*PBin(6)+8*PBin(7))^0xf;
trg = keyData&(keyData^cont);
cont = keyData;
}
void MatrixKey_Init(){
//PB123输出
RCC->APB2ENR |=1<<3;//enable clock of PORTB
GPIOB->CRL &= 0xffff0000;
GPIOB->CRL |= 0x00003333;//PB0推挽输出
GPIOB->ODR |= 1<<0;//PB0上拉
GPIOB->ODR |= 1<<1;
GPIOB->ODR |= 1<<2;
GPIOB->ODR |= 1<<3;
//PB4567输入
GPIOB->CRL &= 0x0000ffff;
GPIOB->CRL |= 0x88880000;
GPIOB->ODR |= 1<<4;
GPIOB->ODR |= 1<<5;
GPIOB->ODR |= 1<<6;
GPIOB->ODR |= 1<<7;//上拉
}
//矩阵扫面函数
u16 MatrixKey_Scan(){
GPIOB->ODR |= 1<<0;//PB0上拉
GPIOB->ODR |= 1<<1;
GPIOB->ODR |= 1<<2;
GPIOB->ODR |= 1<<3;
//PB0下拉
GPIOB->ODR &= ~(1<<0);
if (M4 == 0 || M5 ==0 || M6 == 0 || M7 ==0)
{
//delay_ms(10);//消抖
keyRead();
if (trg == 0x1)
{
return 0;
}
else if(trg == 0x2)
{
return (1*4);
}else if (trg == 0x4)
{
return (2*4);
}else if (trg ==0x8)
{
return 3*4;
}
}
//开始扫描下一行
GPIOB->ODR |= 1<<0;//PB0上拉
GPIOB->ODR |= 1<<1;
GPIOB->ODR |= 1<<2;
GPIOB->ODR |= 1<<3;
//PB1下拉
GPIOB->ODR &= ~(1<<1);
if (M4 == 0 || M5 ==0 || M6 == 0 || M7 ==0 )
{
//delay_ms(10);//消抖
keyRead();
if (trg == 0x1)
{
return 1;
}
else if(trg == 0x2)
{
return (1+1*4);
}else if (trg == 0x4)
{
return (1+2*4);
}else if (trg == 0x8)
{
return (1+3*4);
}
}
//扫描第三行
GPIOB->ODR |= 1<<0;//PB0上拉
GPIOB->ODR |= 1<<1;
GPIOB->ODR |= 1<<2;
GPIOB->ODR |= 1<<3;
//PB2下拉
GPIOB->ODR &= ~(1<<2);
if (M4 == 0 || M5 ==0 || M6 == 0 || M7 ==0)
{
//delay_ms(10);//消抖
keyRead();
if (trg == 0x1)
{
return 2;
}
else if(trg == 0x2)
{
return (2+1*4);
}else if (trg == 0x4)
{
return (2+2*4);
}else if (trg == 0x8)
{
return (2+3*4);
}
}
//扫描第四行
GPIOB->ODR |= 1<<0;//PB0上拉
GPIOB->ODR |= 1<<1;
GPIOB->ODR |= 1<<2;
GPIOB->ODR |= 1<<3;
//PB3下拉
GPIOB->ODR &= ~(1<<3);
if (M4 == 0 || M5 ==0 || M6 == 0 || M7 ==0 )
{
//delay_ms(10);//消抖
keyRead();
if (trg == 0x1)
{
return 3;
}else if(trg == 0x2)
{
return (3+1*4);
}else if (trg == 0x4)
{
return (3+2*4);
}else if (trg == 0x8)
{
return (3+3*4);
}
}
return 16;
}
//matrixKey.h
#ifndef __MATRIX_H
#define __MATRIX_H
#include"sys.h"
#define M4 PBin(4)
#define M5 PBin(5)
#define M6 PBin(6)
#define M7 PBin(7)
#include "exti.h"
#define KeyA PBout(0)
//给一个列口输出低电平,对应的行口为中断
//当按下改建,中断产生时进行矩阵扫描
void MatrixKey_Init(void);//矩阵键盘初始化
u16 MatrixKey_Scan(void);//获取键值
void keyRead(void);
#endif
//extiB.c
#include "extiB.h"
#include "stm32f10x_lib.h"
#include "sys.h"
#include"delay.h"
#include"led.h"
#include "matrixKey.h"
#include "usart.h"
void ExtiB_Init(){
//PB7输出低电平
RCC->APB2ENR |=1<<3;//enable clock of PORTB
GPIOB->CRL &= 0x0fffffff;
GPIOB->CRL |= 0x30000000;//PB7推挽输出 m默认下拉
GPIOB->ODR &= ~(1<<7);
//PB0中断输入
GPIOB->CRL &= 0xfffffff0;
GPIOB->CRL |= 0x00000008;
GPIOB->ODR |= 1<<0;//上拉
Ex_NVIC_Config(GPIO_B,0,1);//下降沿触发
MY_NVIC_Init(2,2,EXTI0_IRQChannel,1);//抢占2,子优先级2,组2
//将中断线有PA0映射到PB0
//GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);
//AFIO->EXTICR[0 >> 0x02] &= ~(0x0F << 0x04);
//AFIO->EXTICR[0 >> 0x02] |= 0x01;
AFIO->EXTICR[0] &= 0xfffffff0;
AFIO->EXTICR[0] |= 0x00000001;
}
//中断处理函数
void EXTI0_IRQHandler(){
u16 i = 0;
u16 key;
LED0 = !LED0;
delay_ms(10);//消抖
if (PBin(0) == 0)
{
printf("please input the number:\t");
MatrixKey_Init();
//按键扫描5s
while (1)
{
key = MatrixKey_Scan();
if (key <16)
{
printf("%d",key);
}
i++;
if (i ==500 )
{
i = 0;
break;
}
delay_ms(10);
}
}
ExtiB_Init();
}
//extiB.h
#ifndef __EXTIB_H
#define __EXTIB_H
#include "sys.h"
void ExtiB_Init(void);
#endif
//main.c
//中断输入实验实验
#include "stm32f10x_lib.h"
#include"delay.h"
#include "sys.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "matrixKey.h"
void My_System_Init(void);
int main(){
//GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);
My_System_Init();
while (1)
{
printf("OK\n");
delay_ms(1000);
}
}
void My_System_Init(){
Stm32_Clock_Init(9);
uart_init(72,9600);
LED_Init();
delay_init(72);
//EXTIX_Init();
//KEY_Init();
ExtiB_Init();
}
|