stm32F103状态机矩阵键盘

发布者:火箭飞人最新更新时间:2018-06-22 来源: eefocus关键字:stm32F103  状态机  矩阵键盘 手机看文章 扫描二维码
随时随地手机看文章

矩阵键盘程序,作为麦知club小车项目的一部分,从IAR状态机应用修改而来。

IAR7.4+STM32CUBEMX调试通过。

键盘行4,列3,每条线都有10K上拉电阻。改到4×4矩阵也很容易。

行线设置为 输入,针脚为浮空; 列线设置为开漏输出。


不支持长按和组合键,主要是我不会改。

在OS中使用20ms任务周期调用。


以下贴出代码。

keypad.h

/* 

* Name: keypad.h 

*/  

#ifndef KEYPAD_H  

#define KEYPAD_H  

  

#include "stm32f1xx_hal.h"  

#include "pinname.h"  

  

#define PORT_KEY GPIOD  

#define COLS (GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6)  

  

// 读pin  

//#define In(GPIO_Pin) (PORT_KEY->IDR & GPIO_Pin)  

#define In(GPIO_Pin) HAL_GPIO_ReadPin(PORT_KEY, GPIO_Pin)  

// 写1到Pin  

//#define High(GPIO_Pin) PORT_KEY->BSRR = GPIO_Pin  

#define High(GPIO_Pin) HAL_GPIO_WritePin(PORT_KEY, GPIO_Pin, GPIO_PIN_SET)  

// 写0到Pin  

//#define Low(GPIO_Pin) PORT_KEY->BSRR = (uint32_t)GPIO_Pin << 16   

#define Low(GPIO_Pin) HAL_GPIO_WritePin(PORT_KEY, GPIO_Pin, GPIO_PIN_RESET)  

  

/*  

*  0  1  2   3 

*  4  5  6   7 

*  8  9  10  11 

*  12 13 14  15 

*/  

  

typedef enum {  

    Key_Up = 0x02,  

    Key_Left = 0x03,  

    Key_Right = 0x04,  

    Key_Down = 0x08,  

    Key_On =  0x09,  

    Key_Mode = 0x0a,  

    Key_None = 0xFF  

} KeyPressed;  

      

static const int row_count = 4;  

static const int col_count = 3;  

  

uint16_t bus_out(void);  

  

void Keypad(void);  

char AnyKey(void);  

char SameKey(void);  

char ScanKey(void);  

void FindKey(void);  

void ClearKey(void);  

void Read(void);  

/** Start the keypad interrupt routines */  

void Start(void);  

/** Stop the keypad interrupt routines */  

void Stop(void);  

void Cols_out(uint16_t v);  

void Scan_Keyboard(void);  

KeyPressed getKey(void);  

#endif // KEYPAD_H  


keypad.c

/* 

* Name: keypad.cpp 

*/  

  

#include "keypad.h"  

  

// State:  

char KeyState;  

// Bit pattern after each scan:  

char KeyCode;  

// Output value from the virtual 74HC922:  

KeyPressed KeyValue;  

// KeyDown is set if key is down:  

char KeyDown;  

// KeyNew is set every time a new key is down:  

char KeyNew;  

// 映射表  

char KeyTable[12][2];    

// Pin of Row  

uint16_t _rows[] = {KEYx0, KEYx1, KEYx2, KEYx3};  

uint16_t _cols[] = {KEYy0, KEYy1, KEYy2};  

  

//构造函数  

void Keypad(void)  

{  

       

   Stop();     

   KeyState = 0; // 按键状态初始 0  

}  

  

  

//扫描键盘  

void Scan_Keyboard(void){  

switch (KeyState) {  

  case 0: {  

  if (AnyKey()) {      

    char scankey = ScanKey();  

    if (scankey != 0xff)  

        KeyCode = scankey;  

      

    KeyState = 1;  

  }  

    

  break;  

  }  

  case 1: {  

  if (SameKey()) {  

    FindKey();  

    KeyState = 2;    

  }  

  else   

    KeyState = 0;  

    

  break;  

  }  

  case 2: {  

    if (SameKey()) {  

    }  

    else   

      KeyState = 3;  

      

    break;  

    }  

  case 3: {  

    if (SameKey()) {  

      KeyState = 2;  

    }  

    else {  

      ClearKey();  

      KeyState = 0;  

    }  

      

    break;  

   }  

  }  

// func end  

}  

  

// 有键按下  

char AnyKey(void) {  

 //Start();  //拉低  

   

 int r = -1;  

 for (r = 0; r < row_count; r++) {  

     if (In(_rows[r]) == 0)  // In macro  

         break;    

 }  

   

 //Stop();  //恢复  

   

 if (!(0 <= r && r < row_count))  

    return 0;  

 else  

    return 1;  

}  

  

// 键按下, 键值相同  

char SameKey(void) {  

    

  // char KeyCode_new = KeyCode;  

  char KeyCode_new = ScanKey();  

  if (KeyCode == KeyCode_new)    

    return 1;  

  else  

    return 0;  

}  

  

// 扫描键  

char ScanKey(void) {  

  

 /* 行扫描 */  

    int r = -1;  

    for (r = 0; r < row_count; r++) {  

        if (In(_rows[r]) == 0)  // In macro  

            break;  

    }  

  

    /* 若没有找到有效行,返回 */  

    if (!(0 <= r && r < row_count)) {  

      return 0xff;  

          

    }  

  

    /* 列扫描,找出行上哪个被拉低 */  

    int c = -1;  

    for (c = 0; c < col_count; c++) {  

        // 轮流输出列线  

        Cols_out(~(1 << c));  

          

        if (In(_rows[r]) == 0)  // In macro  

            break;  

    }  

  

    /* 给所有的列重新充电 */  

    Start();  

  

    /* 若没有找到有效列,返回 */  

    if (!(0 <= c && c < col_count))  

        return 0xff;  

  

    return r * col_count + c;  

   

}  

  

// FindKey compares KeyCode to values in KeyTable.  

// If match, KeyValue, KeyDown and KeyNew are updated.  

void FindKey(void) {  

 KeyValue = (KeyPressed)KeyCode;  

 KeyDown = 1;  

 KeyNew = 1;  

}  

  

  

void ClearKey(void) {  

 KeyDown = 0;  

}  

  

KeyPressed getKey(void) {  

  if(KeyNew)  

  {  

    KeyNew = 0;  

    return KeyValue;  

  }  

  else  

    return Key_None;  

}  

  

void Start(void)  

{  

    /* 列输出0, 拉低行 */  

    PORT_KEY->BRR = COLS;  

}  

  

void Stop(void)  

{  

    /* 列输出1,使行不被拉低 */  

    PORT_KEY->BSRR = COLS;  

}  

  

// cols bus output  

void Cols_out(uint16_t v)  

{  

  if ((v & 0x01) > 0) //0b001  

    High(_cols[0]);  

  else  

    Low(_cols[0]);  

    

  if ((v & 0x02) > 0) //0b010  

    High(_cols[1]);  

  else  

    Low(_cols[1]);  

    

  if ((v & 0x04) > 0) //0b100  

    High(_cols[2]);  

  else  

    Low(_cols[2]);  

                                             

}  


按键操作可以改到寄存器操作,提高速度。

使用mbed写,会更省事,可惜VBT6的RAM太少。



关键字:stm32F103  状态机  矩阵键盘 引用地址:stm32F103状态机矩阵键盘

上一篇:STM32串口接收发送子程序
下一篇:关于STM32驱动DS1302的一点思考

推荐阅读最新更新时间:2024-03-16 16:06

STM32F103学习笔记三 串口通信
1、串口通信背景知识 1.1、 设备之间的通信方式 并行通信 串行通信 传输原理 数据各个位同时传输 数据按位顺序传输 优点 速度快 占用引脚资源少 缺点 占用引脚资源多 速度相对较慢 1.2、 串行通信分类 1.2.1、按照通信方式,分为: 同步通信:带时钟同步信号传输。比如:SPI,I²C通信接口 异步通信:不带时钟同步信号。比如:UART(通用异步收发器),单总线 1.2.2、按照数据传送方向,分为: 单工:数据传输只支持数据在一个方向上传输; 半双工:允许数据在两个方向上传输。但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;它不需要独立的接收端和发送端,两者可以合并一起使用一个端口。 全
[单片机]
<font color='red'>STM32F103</font>学习笔记三 串口通信
怎样用ArduinoIDE对STM32F103C8T6进行编程
STM32F103C8T6板 - 也称为Blue Pill - 是ARM Cortex的开发板M3微控制器。它看起来与Arduino Nano非常相似,但它包含更多功能。 在本文中,我将向您展示如何使用Arduino IDE设置STM32并向您展示如何直接来自USB UART模块的程序。 STM32概述“Blue Pill” 如果你看看这个2美元的微控制器,您看到的第一件事就是它的跳线引脚,用于使用默认的USART引导加载程序。板上还有一个微型USB端口,但遗憾的是它不能用于编程,因为它没有相关的引导加载程序。 与官方的Arduino板相比,这些板非常便宜,而且硬件是开源的。除了微控制器外,该板还可以容纳两个晶体振荡器
[单片机]
怎样用ArduinoIDE对<font color='red'>STM32F103</font>C8T6进行编程
STM32f103-实例睡眠模式的唤醒
main.c /***************************************************************************/ // environment : writ by Chen maolin in 2010/9/23 on Kiel 4.0 // finktion : about a projiect to setup EXTI // hardware optimization : // update : 2010/9/26 陈茂林 /*************************************************
[单片机]
51单片机矩阵键盘与8051连接设计
众所周知,51单片机一般的键盘检测原理为非编码键盘检测,没有专门用来产生键编码号或键值的电路芯片;而我们使用的电脑键盘为编码键盘,通过编码电路芯片为每个按键产生一个编码号,可以通过串行总线把键值传输给电脑。在进行矩阵键盘检测时,书本或老师一般教的都是扫描检测,即一行一行地检测或者一列一列地检测,代码繁琐复杂,且缺点很多(例如执行效率较低)。 举例电路: 矩阵键盘与8051连接如上图所示,首先,令P3=0x0f,检测P30、P31、P32、P33哪一行被按下,将此时P3的值存入寄存器1。然后,令P3=0xf0 | 寄存器1,检测P34、P35、P36、P37哪一列被按下,将此时P3的值存入寄存器2。最后,把寄存器1的值和寄存
[单片机]
51单片机<font color='red'>矩阵键盘</font>与8051连接设计
STM32F103x的USB多路数据采集系统设计
   引 言   目前,在工业和许多其他场合依然使用基于PCI板卡、ISA板卡的数据采集系统,价格昂贵、接插不方便。USB(Universal Serial Bus,通用串行总线)是计算机上的一种新型接口技术,它使得计算机和外部设备的连接十分方便。USB具有高效、快速、价格低廉、体积小和支持热拔插等优点,使其成为数据采集系统设计的新宠儿。然而当前的USB数据采集设备大多采用的是专门的USB接口芯片,而且根据不同的需求,需要外扩一定数量的A/D 转换芯片,使得接口非常复杂,增加了系统的开发难度,进而对系统的稳定性产生影响。本设计采用意法半导体公司开发的基于Cortex-M3内核的新型32 位微控制器STM32F103x作为主控芯片
[单片机]
STM32F103单片机学习笔记(2):外部中断
对于STM32的中断首先需要用到的文件是startup_stm32f10x_hd.s和stm32f10x_it.c这两个文件,其中startup_stm32f10x_hd.s是启动文件,stm32f10x_it.c是中断响应函数。对于外部中断,它的过程是外部的IO口监测到电平的变化,触发外部中断,所以它又涉及到3个库文件,stm32f10x_gpio.c、stm32f10x_exti.c和misc.c,misc.c包含中断库,stm32f10x_exti.c是外部的IO口中断,stm32f10x_gpio.c是IO口的配置。还有一个我们上一篇中说的所有的外设都要用到的库文件时钟stm32f10x_rcc.c。 一、启动文件 说
[单片机]
<font color='red'>STM32F103</font>单片机学习笔记(2):外部中断
4×4矩阵键盘,控制数码管显示
题目要求: 两个数码管显示0-59秒的秒表。一矩阵键盘,输入0-F。 当A键按下后,进入修改时间状态,此时在分别按下0-9中的任意两个数,数码管时间更改。 如按下09,数码管此时显示09。 再按下A键,数码管从09继续跑。 写出C语言程序,端口随便接。 问题关键是如何实现A按下后,数码管秒数的改变。麻烦行家帮帮忙。非常感谢。 悬赏分:100 | 解决时间:2011-3-11 16:55 //======================================= 最佳答案: 下列程序已经调好,按键显示电路可见: http://hi.baidu.com/%D7%F6%B6%F8%C2%DB%B5%C0/blog/item/ef
[单片机]
4×4<font color='red'>矩阵键盘</font>,控制数码管显示
基于stm32f103zet6的FAT16文件系统学习0(读SD卡扇区)
SD卡已经看了两天了,主要是因为测试出来的卡容量不对,所以一直找原因,最终还是发现了,总比不过是单位上面出现了问题,或许是之前没有接触到SD的缘故吧,所以对其中的一些寄存器很不了解,一切都是重新开始,对照这寄存器手册,理解程序,修改程序。一步步还是总结一下! 首先关于SD卡的协议是有必要了解的,我今天花了一上午的课堂时间来理解这个SD卡的协议,就是基于这个文档的,这个文档很适合入门SD协议的(个人认为)。 http://download.csdn.net/detail/king_bingge/5218183 初识SD之后,就可以开始正式学习SD卡了! 一、要使用SD卡,那么首先肯定得对SD卡进行初始化,那么如何进行初始化呢?(命
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved