找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 21709|回复: 58
收起左侧

基于STM32F103的任意I/O口矩阵键盘驱动程序

  [复制链接]
ID:435174 发表于 2019-1-20 22:54 | 显示全部楼层 |阅读模式
本帖最后由 Linux— 于 2019-7-30 23:59 编辑

       网上的矩阵键盘代码非常非常多,但绝大部分都是要连续I/O口的,就比如PA0-PA7、PB3-PB10等等等,这些都要用到一排的连续的单片机引脚。用过STM32单片机的都知道,STM32单片机一排过去连续的引脚的不是很多,就算刚好出现了一排PA0-PA10,可是呢,PA2、PA3串口2要用,PA9、PA10串口1要用,这就显得比较局限。而且市面上的那些很多都是修改引脚要全文上下一处处修改,麻烦且容易错漏。所以如果我矩阵键盘的引脚可以随便定义的话那么是不是就不用愁这个问题了?     所以,这就是我给大家带来的任意可用的I/O的矩阵键盘程序,按键扫描代码直接操纵IO口,得出按键值。用法很简单:先看下图
引脚定义.jpg
我们看到,在key4_4.c中已经用宏定义定义好了矩阵键盘8个引脚的端口、具体引脚和时钟,方便程序的移植和修改。所以这个程序的用法非常简单,且移植性非常非常地高,因为使用者只需要在宏定义中根据实际需要和兴趣爱好修改那8个引脚的端口、具体引脚和时钟就行了,剩下的就不用修改了,且移植到其他程序去就可以直接使用。下面是按键扫描函数,用库函数给IO口设置高低电平,再根据这些引脚电平状态得出按键值,具体请看截图:(//Author:GXNU_LPK_201512700***(广西师范大学电子工程学院2015_LPK)注:此部分按键扫描代码是我熬夜摸索尝试调试出来的,希望不要被认作抄袭或复制,虽然网上可能有雷同的
keyscan1.png keyscan2.png keyscan3.png

当定义存储按键值的变量keyscan类型为unsigned char时,没有按键按下时默认值为255,即keyscan=255,其他类型的默认值可以自己测试。所以可以这么用:

  1. keyscan = Key_Scan();//keyscan为unsigned char 型
  2. if(keyscan != 255)
  3. {
  4.      key_value = keyscan;
  5. }
复制代码


下面是测试结果截图: 测试结果.jpg 键盘和测试结果.jpg

下图是我的硬件平台,用的是STM32F103C8T6最小系统板子
STM32单片机.jpg

代码用C语言编写,已经验证通过,请放心使用,只要修改好了引脚相关信息和不接错接反线都能正常使用的。特别强调的是,移植时你定义的矩阵键盘引脚不能和其他程序或板子设置的硬件冲突,不然可能会出现按键无效或部分按键无效的情况。还有,如果你测试时发现按键值不对应,这是因为你矩阵键盘的PCB布线跟我用的这个不同,自己在程序按键值里面手动修改就好了。
下面是main.c代码
  1. //main.c
  2. #include "key4_4.h"
  3. #include "delay.h"
  4. #include "sys.h"
  5. //平台:STM32F103
  6. //实验名称:不连续I/O矩阵键盘实验  
  7. //Author:GXNU_LPK_201512700***(广西师范大学电子工程学院2015_LPK)
  8. //使用说明:矩阵键盘所用引脚都已经用宏定义定义好了,移植只需根据实际需要在key4_4.c中修改对应的时钟、引脚和端口即可,其余都不用修改。
  9. //矩阵键盘所用的8个引脚可连续可不连续,看实际需要和个人爱好自己定义。
  10. int main(void)
  11. {        
  12.      uart_init(9600);            
  13.      Key_Init();                                 
  14.      delay_init();                                
  15.      printf("不连续I/O口矩阵键盘测试\r\n");
  16.    
  17.   while(1)
  18.   {                        
  19.       Key_Test();               
  20.   }
  21. }


复制代码
下面是usart.c代码
  1. #include "sys.h"
  2. #include "usart.h"         
  3. //////////////////////////////////////////////////////////////////////////////////         
  4. //如果使用ucos,则包括下面的头文件即可.
  5. #if SYSTEM_SUPPORT_UCOS
  6. #include "includes.h"                                        //ucos 使用         
  7. #endif
  8. //////////////////////////////////////////////////////////////////////////////////         
  9. //本程序只供学习使用,未经作者许可,不得用于其它任何用途
  10. //ALIENTEK STM32开发板
  11. //串口1初始化                  
  12. //正点原子@ALIENTEK
  13. //修改日期:2012/8/18
  14. //版本:V1.5
  15. //版权所有,盗版必究。
  16. //Copyright(C) 广州市星翼电子科技有限公司 2009-2019
  17. //All rights reserved
  18. //********************************************************************************
  19. //V1.3修改说明
  20. //支持适应不同频率下的串口波特率设置.
  21. //加入了对printf的支持
  22. //增加了串口接收命令功能.
  23. //修正了printf第一个字符丢失的bug
  24. //V1.4修改说明
  25. //1,修改串口初始化IO的bug
  26. //2,修改了USART_RX_STA,使得串口最大接收字节数为2的14次方
  27. //3,增加了USART_REC_LEN,用于定义串口最大允许接收的字节数(不大于2的14次方)
  28. //4,修改了EN_USART1_RX的使能方式
  29. //V1.5修改说明
  30. //1,增加了对UCOSII的支持
  31. //////////////////////////////////////////////////////////////////////////////////           


  32. //////////////////////////////////////////////////////////////////
  33. //加入以下代码,支持printf函数,而不需要选择use MicroLIB         
  34. #if 1
  35. #pragma import(__use_no_semihosting)            
  36. //标准库需要的支持函数                 
  37. struct __FILE
  38. {
  39.         int handle;

  40. };

  41. FILE __stdout;      
  42. //定义_sys_exit()以避免使用半主机模式   
  43. _sys_exit(int x)
  44. {
  45.         x = x;
  46. }
  47. //重定义fputc函数
  48. int fputc(int ch, FILE *f)
  49. {      
  50.         while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
  51.     USART1->DR = (u8) ch;      
  52.         return ch;
  53. }
  54. #endif

  55. /*使用microLib的方法*/
  56. /*
  57. int fputc(int ch, FILE *f)
  58. {
  59.         USART_SendData(USART1, (uint8_t) ch);

  60.         while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}        
  61.    
  62.     return ch;
  63. }
  64. int GetKey (void)  {

  65.     while (!(USART1->SR & USART_FLAG_RXNE));

  66.     return ((int)(USART1->DR & 0x1FF));
  67. }
  68. */


  69. //串口1中断服务程序
  70. //注意,读取USARTx->SR能避免莫名其妙的错误           
  71. u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
  72. //接收状态
  73. //bit15,        接收完成标志
  74. //bit14,        接收到0x0d
  75. //bit13~0,        接收到的有效字节数目
  76. u16 USART_RX_STA=0;       //接收状态标记         

  77. //初始化IO 串口1
  78. //bound:波特率
  79. void uart_init(u32 bound){
  80.     //GPIO端口设置
  81.     GPIO_InitTypeDef GPIO_InitStructure;
  82.         USART_InitTypeDef USART_InitStructure;
  83.         NVIC_InitTypeDef NVIC_InitStructure;
  84.          
  85.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);        //使能USART1,GPIOA时钟
  86.          USART_DeInit(USART1);  //复位串口1
  87.          //USART1_TX   PA.9
  88.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  89.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  90.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
  91.     GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
  92.    
  93.     //USART1_RX          PA.10
  94.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  95.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  96.     GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA10

  97.    //Usart1 NVIC 配置

  98.     NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  99.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
  100.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                //子优先级3
  101.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
  102.         NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器
  103.   
  104.    //USART 初始化设置

  105.         USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;
  106.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
  107.         USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  108.         USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
  109.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  110.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //收发模式

  111.     USART_Init(USART1, &USART_InitStructure); //初始化串口
  112.     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断
  113.     USART_Cmd(USART1, ENABLE);                    //使能串口

  114. }
  115. #if EN_USART1_RX   //如果使能了接收
  116. void USART1_IRQHandler(void)                        //串口1中断服务程序
  117.         {
  118.         u8 Res;
  119. #ifdef OS_TICKS_PER_SEC                 //如果时钟节拍数定义了,说明要使用ucosII了.
  120.         OSIntEnter();   
  121. #endif
  122.         if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
  123.                 {
  124.                 Res =USART_ReceiveData(USART1);//(USART1->DR);        //读取接收到的数据
  125.                
  126.                 if((USART_RX_STA&0x8000)==0)//接收未完成
  127.                         {
  128.                         if(USART_RX_STA&0x4000)//接收到了0x0d
  129.                                 {
  130.                                 if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
  131.                                 else USART_RX_STA|=0x8000;        //接收完成了
  132.                                 }
  133.                         else //还没收到0X0D
  134.                                 {        
  135.                                 if(Res==0x0d)USART_RX_STA|=0x4000;
  136.                                 else
  137.                                         {
  138.                                         USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
  139.                                         USART_RX_STA++;
  140.                                         if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收         
  141.                                         }                 
  142.                                 }
  143.                         }                    
  144.      }
  145. #ifdef OS_TICKS_PER_SEC                 //如果时钟节拍数定义了,说明要使用ucosII了.
  146.         OSIntExit();                                                                                          
  147. #endif
  148. }
  149. #endif        
复制代码

0.png
剩下的代码请从附件里面下载整个工程查看哟
若黑币不足的话也可以从这里下载:https://download.csdn.net/download/qq_36112455/10929213
全部资料51hei下载地址:
可移植的不连续IO口矩阵键盘(验证通过).7z (214.93 KB, 下载次数: 955)

评分

参与人数 2黑币 +80 收起 理由
谢放 + 30 很给力!
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:144634 发表于 2019-2-22 11:31 | 显示全部楼层
请问下,为什么按照您的程序接好线以后用串口调试软件并不能得到相应的测试结果啊?用的是RCT6的应该也是兼容的吧?
回复

使用道具 举报

ID:435174 发表于 2019-2-23 18:06 来自手机 | 显示全部楼层
Johnny·JH 发表于 2019-2-22 11:31
请问下,为什么按照您的程序接好线以后用串口调试软件并不能得到相应的测试结果啊?用的是RCT6的应该也是兼 ...

是不是接线顺序反了?你把接到PA15的线接到PB9,PB9的线线接到PA15这样,其余线类似调换接线顺序再试下,程序我多次验证过和改过很多不同的IO口都没问题的
回复

使用道具 举报

ID:113485 发表于 2019-3-1 15:25 | 显示全部楼层
Linux— 发表于 2019-2-23 18:06
是不是接线顺序反了?你把接到PA15的线接到PB9,PB9的线线接到PA15这样,其余线类似调换接线顺序再试下, ...

PB9?楼主你没定义PB9
回复

使用道具 举报

ID:378085 发表于 2019-3-12 17:20 | 显示全部楼层
感谢楼主分享,但是我用的调试助手是野火专用的  但是数值依旧没有显示,波特率以及十六进制这块我都修改成和楼主您一样的。是我接线顺序的原因吗
回复

使用道具 举报

ID:435174 发表于 2019-3-15 22:29 | 显示全部楼层
剑影 发表于 2019-3-1 15:25
PB9?楼主你没定义PB9

额,这里我要说声抱歉,由于回复上面那条评论那天时间匆忙没注意看,我上面帖子那里如果仔细看的话会发现第一张图跟第三张图定义的引脚是不同的,第一张没有PB9,第三张图那里是有PB9的,因为我是测试不同的引脚不同时间截或拍的图,这点是我疏忽了,你们知道我想表达的是第一个引脚跟最后一个引脚交换位置,其他引脚也一样这个意思就好啦

评分

参与人数 1黑币 +60 收起 理由
admin + 60 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:435174 发表于 2019-3-15 22:32 | 显示全部楼层
六号啦 发表于 2019-3-12 17:20
感谢楼主分享,但是我用的调试助手是野火专用的  但是数值依旧没有显示,波特率以及十六进制这块我都修改成 ...

那你的“不连续I/O口矩阵键盘测试”这句话能正常显示吗?

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:435174 发表于 2019-3-15 22:37 | 显示全部楼层
六号啦 发表于 2019-3-12 17:20
感谢楼主分享,但是我用的调试助手是野火专用的  但是数值依旧没有显示,波特率以及十六进制这块我都修改成 ...

就算接线顺序反了那结果也就是得不到理想的数值而已,还不至于没显示
回复

使用道具 举报

ID:422431 发表于 2019-3-16 00:11 | 显示全部楼层
是不是接线顺序反了
回复

使用道具 举报

ID:333683 发表于 2019-3-16 15:51 | 显示全部楼层
感谢楼主的分享,用起来感觉非常方便
回复

使用道具 举报

ID:435174 发表于 2019-3-17 09:23 | 显示全部楼层
电子发烧友~ 发表于 2019-3-16 15:51
感谢楼主的分享,用起来感觉非常方便

那是啊,不然这程序的意义何在哈哈哈
回复

使用道具 举报

ID:435174 发表于 2019-3-31 18:19 | 显示全部楼层
下面附上矩阵键盘初始化和按键扫描代码方便大家直接查看:
  1. unsigned char Y1,Y2,Y3,Y4;
  2. void Key_Init(void)
  3. {
  4.    GPIO_InitTypeDef GPIO_InitStructure;   
  5.    RCC_APB2PeriphClockCmd(X1_RCC|X2_RCC|X3_RCC|X4_RCC|Y1_RCC|Y2_RCC|Y3_RCC|Y4_RCC|RCC_APB2Periph_AFIO, ENABLE);
  6.    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
  7.        
  8. /*****************************4行输出*********************************************/
  9.    GPIO_InitStructure.GPIO_Pin =  X1_GPIO_PIN ;
  10.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         
  11.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12.    GPIO_Init(X1_GPIO_PORT, &GPIO_InitStructure);
  13.    
  14.    GPIO_InitStructure.GPIO_Pin =  X2_GPIO_PIN ;
  15.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         
  16.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  17.    GPIO_Init(X2_GPIO_PORT, &GPIO_InitStructure);
  18.    
  19.    GPIO_InitStructure.GPIO_Pin =  X3_GPIO_PIN ;
  20.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         
  21.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  22.    GPIO_Init(X3_GPIO_PORT, &GPIO_InitStructure);
  23.        
  24.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         
  25.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  26.    GPIO_InitStructure.GPIO_Pin = X4_GPIO_PIN ;   
  27.    GPIO_Init(X4_GPIO_PORT, &GPIO_InitStructure);
  28.    
  29. /**************************************4列输入*************************************/
  30.    GPIO_InitStructure.GPIO_Pin =  Y1_GPIO_PIN ;   
  31.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;         
  32.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  33.    GPIO_Init(Y1_GPIO_PORT, &GPIO_InitStructure);       
  34.    
  35.    GPIO_InitStructure.GPIO_Pin =  Y2_GPIO_PIN ;   
  36.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;         
  37.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  38.    GPIO_Init(Y2_GPIO_PORT, &GPIO_InitStructure);       
  39.    
  40.    GPIO_InitStructure.GPIO_Pin =  Y3_GPIO_PIN ;   
  41.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;         
  42.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  43.    GPIO_Init(Y3_GPIO_PORT, &GPIO_InitStructure);       
  44.        
  45.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;         
  46.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  47.    GPIO_InitStructure.GPIO_Pin = Y4_GPIO_PIN;      
  48.    GPIO_Init(Y4_GPIO_PORT, &GPIO_InitStructure);       
  49. }
复制代码
回复

使用道具 举报

ID:435174 发表于 2019-3-31 18:19 | 显示全部楼层
下面是按键扫描代码:
  1. int Key_Scan(void)
  2. {
  3.    uchar KeyVal;
  4.    GPIO_SetBits(X1_GPIO_PORT,X1_GPIO_PIN);  //先让X1输出高
  5.    GPIO_SetBits(X2_GPIO_PORT,X2_GPIO_PIN);  //先让X2输出高
  6.    GPIO_SetBits(X3_GPIO_PORT,X3_GPIO_PIN);  //先让X3输出高
  7.    GPIO_SetBits(X4_GPIO_PORT,X4_GPIO_PIN);  //先让X4输出高


  8.         if((GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN)|GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN)|GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN)|GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN))==0x0000)  
  9.         return -1; //如果X1到X4全为零则没有按键按下  
  10.          else
  11.          {       
  12.             delay_ms(5);    //延时5ms去抖动
  13.          if((GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN)|GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN)|GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN)|GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN))==0x0000)
  14.             return -1;
  15.          }
  16.          
  17.      GPIO_ResetBits(X1_GPIO_PORT,X1_GPIO_PIN);
  18.      GPIO_ResetBits(X2_GPIO_PORT,X2_GPIO_PIN);
  19.      GPIO_ResetBits(X3_GPIO_PORT,X3_GPIO_PIN);
  20.      GPIO_SetBits(X4_GPIO_PORT,X4_GPIO_PIN);
  21.      
  22.     Y1=GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN);Y2=GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN);
  23.     Y3=GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN);Y4=GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN);
  24.      if(Y1==1&&Y2==0&&Y3==0&&Y4==0)
  25.             KeyVal='*';
  26.      if(Y1==0&&Y2==1&&Y3==0&&Y4==0)
  27.             KeyVal=0;
  28.      if(Y1==0&&Y2==0&&Y3==0&&Y4==1)
  29.             KeyVal='D';
  30.      if(Y1==0&&Y2==0&&Y3==1&&Y4==0)
  31.             KeyVal='#';
  32.    
  33.      while(((GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN))|(GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN))|(GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN))|(GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN))) > 0);
  34.     //等待按键释放
  35.      GPIO_SetBits(X1_GPIO_PORT,X1_GPIO_PIN);
  36.      GPIO_ResetBits(X2_GPIO_PORT,X2_GPIO_PIN);
  37.      GPIO_ResetBits(X3_GPIO_PORT,X3_GPIO_PIN);
  38.      GPIO_ResetBits(X4_GPIO_PORT,X4_GPIO_PIN);
  39.    
  40.     Y1=GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN);Y2=GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN);
  41.     Y3=GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN);Y4=GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN);
  42.      if(Y1==1&&Y2==0&&Y3==0&&Y4==0)
  43.             KeyVal=1;
  44.      if(Y1==0&&Y2==1&&Y3==0&&Y4==0)
  45.             KeyVal=2;
  46.      if(Y1==0&&Y2==0&&Y3==1&&Y4==0)
  47.             KeyVal=3;
  48.      if(Y1==0&&Y2==0&&Y3==0&&Y4==1)
  49.             KeyVal='A';
  50.       
  51.       while(((GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN))|(GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN))|(GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN))|(GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN))) > 0);
  52.                

  53.      GPIO_ResetBits(X1_GPIO_PORT,X1_GPIO_PIN);
  54.      GPIO_SetBits(X2_GPIO_PORT,X2_GPIO_PIN);
  55.      GPIO_ResetBits(X3_GPIO_PORT,X3_GPIO_PIN);
  56.      GPIO_ResetBits(X4_GPIO_PORT,X4_GPIO_PIN);
  57.         
  58.      Y1=GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN);Y2=GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN);
  59.      Y3=GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN);Y4=GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN);
  60.      if(Y1==1&&Y2==0&&Y3==0&&Y4==0)
  61.             KeyVal=4;
  62.      if(Y1==0&&Y2==1&&Y3==0&&Y4==0)
  63.             KeyVal=5;
  64.      if(Y1==0&&Y2==0&&Y3==1&&Y4==0)
  65.             KeyVal=6;
  66.      if(Y1==0&&Y2==0&&Y3==0&&Y4==1)
  67.             KeyVal='B';
  68.    
  69.       while(((GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN))|(GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN))|(GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN))|(GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN))) > 0);
  70.                
  71.      GPIO_ResetBits(X1_GPIO_PORT,X1_GPIO_PIN);
  72.      GPIO_ResetBits(X2_GPIO_PORT,X2_GPIO_PIN);
  73.      GPIO_SetBits(X3_GPIO_PORT,X3_GPIO_PIN);
  74.      GPIO_ResetBits(X4_GPIO_PORT,X4_GPIO_PIN);   

  75.      Y1=GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN);Y2=GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN);
  76.      Y3=GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN);Y4=GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN);
  77.      if(Y1==1&&Y2==0&&Y3==0&&Y4==0)
  78.             KeyVal=7;
  79.      if(Y1==0&&Y2==1&&Y3==0&&Y4==0)
  80.             KeyVal=8;
  81.      if(Y1==0&&Y2==0&&Y3==1&&Y4==0)
  82.             KeyVal=9;
  83.      if(Y1==0&&Y2==0&&Y3==0&&Y4==1)
  84.             KeyVal='C';

  85.        while(((GPIO_ReadInputDataBit(Y1_GPIO_PORT,Y1_GPIO_PIN))|(GPIO_ReadInputDataBit(Y2_GPIO_PORT,Y2_GPIO_PIN))|(GPIO_ReadInputDataBit(Y3_GPIO_PORT,Y3_GPIO_PIN))|(GPIO_ReadInputDataBit(Y4_GPIO_PORT,Y4_GPIO_PIN))) > 0);
  86.           
  87.                 return KeyVal;
  88. }

  89. /************************************
  90.         按键表盘为:                1  2  3  A
  91.                                                         4  5  6  B
  92.                                                         7  8  9  C
  93.                                                         *  0  #  D
  94. ************************************/
复制代码
回复

使用道具 举报

ID:573105 发表于 2019-6-27 08:38 | 显示全部楼层
战舰V3好用吗
回复

使用道具 举报

ID:435174 发表于 2019-7-3 12:52 来自手机 | 显示全部楼层
570744034 发表于 2019-6-27 08:38
战舰V3好用吗

STM32F1系列可以直接用(如果按键值不对的话跟接线顺序和键盘PCB布线有关,手动修改一下即可);F4等系列需要在初始化那里改一下
回复

使用道具 举报

ID:585331 发表于 2019-7-16 20:02 | 显示全部楼层
我用的野火的串口调试器,但是只能显示那一行字,没有具体的按键显示,是什么问题呢?
回复

使用道具 举报

ID:435174 发表于 2019-7-16 23:59 | 显示全部楼层
ANNAA 发表于 2019-7-16 20:02
我用的野火的串口调试器,但是只能显示那一行字,没有具体的按键显示,是什么问题呢?

是用我提供的那个工程吗?还是你移植去了其他工程?程序有改动过吗?线接好了没?你可以在主页私信给我,看到的话我会第一时间回复,帮你分析是什么问题
回复

使用道具 举报

ID:282095 发表于 2019-7-17 09:17 | 显示全部楼层
使用GPIO进行调试啊
回复

使用道具 举报

ID:435174 发表于 2019-7-17 23:44 | 显示全部楼层
鹏博士PBs 发表于 2019-7-17 09:17
使用GPIO进行调试啊

嗯啊,在线debug是个好习惯
回复

使用道具 举报

ID:435388 发表于 2019-7-27 11:32 来自手机 | 显示全部楼层
终于调好了,移植到其他的开发版的时候,他定义的引脚可能会和你的板子的设计相碰撞,换个引脚就好,谢谢楼主,很好用
回复

使用道具 举报

ID:435174 发表于 2019-7-27 18:36 | 显示全部楼层
牛逼的小菜鸟 发表于 2019-7-27 11:32
终于调好了,移植到其他的开发版的时候,他定义的引脚可能会和你的板子的设计相碰撞,换个引脚就好,谢谢楼 ...

对的,矩阵键盘定义的引脚不能和其他硬件冲突,那些出现只能串口打印按键没用或者一部分按键有效一部分按键没效的原因多半都是这样。解决方法是把按键引脚改成可用的,没被其他模块或硬件占用的就好了,这也我这个程序的与众不同之处,灵活方便,只需要小小的改动就能达到目的,不像很多市面上的那种要全文上下修改,还容易错漏。
回复

使用道具 举报

ID:110942 发表于 2019-7-27 20:01 | 显示全部楼层
不错,学习了!
回复

使用道具 举报

ID:597942 发表于 2019-8-9 10:05 | 显示全部楼层
Linux— 发表于 2019-7-3 12:52
STM32F1系列可以直接用(如果按键值不对的话跟接线顺序和键盘PCB布线有关,手动修改一下即可);F4等系列需 ...

请问F4要在那里改啊
回复

使用道具 举报

ID:597942 发表于 2019-8-9 10:54 | 显示全部楼层
请问F4要怎么改呢
回复

使用道具 举报

ID:435174 发表于 2019-8-9 23:51 | 显示全部楼层

改void Key_Init(void)这个初始化函数的GPIO设置部分,你编译根据错误提示修改。扫描函数不用改。
回复

使用道具 举报

ID:92181 发表于 2019-11-23 17:34 | 显示全部楼层
感谢楼主的分享,用起来感觉非常方便
回复

使用道具 举报

ID:453484 发表于 2019-11-25 08:37 | 显示全部楼层
有图有真相,不错
回复

使用道具 举报

ID:405123 发表于 2019-12-12 09:58 | 显示全部楼层
本帖最后由 530157193 于 2019-12-12 19:43 编辑

基于STM32F103的任意I/O口矩阵键盘驱动程序  这个程序只有接地才有用 如果我要接带3.3V上拉电阻的矩阵按键耀怎么改啊  能不能再发一个贴- -
回复

使用道具 举报

ID:435174 发表于 2019-12-23 19:45 | 显示全部楼层
530157193 发表于 2019-12-12 09:58
基于STM32F103的任意I/O口矩阵键盘驱动程序  这个程序只有接地才有用 如果我要接带3.3V上拉电阻的矩阵按键 ...

我手上没有带上拉电阻的键盘,这个程序怎么改动只能靠你自己探索了。
回复

使用道具 举报

ID:662414 发表于 2019-12-25 18:35 | 显示全部楼层
超级给力,谢谢楼主
回复

使用道具 举报

ID:435174 发表于 2019-12-26 22:12 | 显示全部楼层
565661340 发表于 2019-12-25 18:35
超级给力,谢谢楼主

好用就好,本就是为了方便大家和方便自己而写的
回复

使用道具 举报

ID:711830 发表于 2020-3-19 22:28 | 显示全部楼层
楼主请问一下会出现第4行打印不出数据的情况吗?
回复

使用道具 举报

ID:712484 发表于 2020-3-20 19:26 | 显示全部楼层
用起来感觉非常方便
回复

使用道具 举报

ID:435174 发表于 2020-3-20 20:11 | 显示全部楼层
yw秃头了 发表于 2020-3-19 22:28
楼主请问一下会出现第4行打印不出数据的情况吗?

我的不会。你第四行的按键值打印不出可能是第四行相关的那个IO跟其它硬件或软件冲突了,检查下。
回复

使用道具 举报

ID:146041 发表于 2020-4-2 20:12 | 显示全部楼层
程序很好,已移植成功
回复

使用道具 举报

ID:435174 发表于 2020-4-2 22:53 | 显示全部楼层
撼地神牛雨 发表于 2020-4-2 20:12
程序很好,已移植成功

哈哈哈,厉害。我也一直在用。兄弟觉得好用的话可以把帖子分享给你周边的人哦
回复

使用道具 举报

ID:614378 发表于 2020-5-14 11:22 | 显示全部楼层
很有用,以后键盘扫面就用这个程序了,谢谢
回复

使用道具 举报

ID:435174 发表于 2020-5-14 22:23 | 显示全部楼层
18990289759 发表于 2020-5-14 11:22
很有用,以后键盘扫面就用这个程序了,谢谢

可以
回复

使用道具 举报

ID:338614 发表于 2020-6-8 00:07 | 显示全部楼层
请问楼主怎么输入多位啊?
回复

使用道具 举报

ID:338614 发表于 2020-6-8 00:09 | 显示全部楼层
请问楼主,这个程序怎么写才能输入多位数据啊?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表