基于STM32控制的智能键盘+程序.docx
《基于STM32控制的智能键盘+程序.docx》由会员分享,可在线阅读,更多相关《基于STM32控制的智能键盘+程序.docx(16页珍藏版)》请在冰豆网上搜索。
基于STM32控制的智能键盘+程序
基于STM32控制的智能键盘
摘要:
本设计选择STM32为核心控制元件,设计了用4个IO口实现4*4矩阵键盘,使用C语言进行编程。
矩阵式键盘提高效率进行按键操作管理有效方法,它可以提高系统准确性,有利于资源的节约,降低对操作者本身素质的要求。
关键词:
STM32矩阵键盘ARM显示电路
1引言
随着21世纪的到来,以前的单个端口连接的按键已经不能满足人们在大型或公共场合的需求。
电子信息行业将是人类社会的高科技行业之一,4*4矩阵键盘设计师当今社会中使用的最广的技术之一。
4*4矩阵式键盘采用STM32为核心,主要由矩阵式键盘电路、显示电路等组成,软件选用C语言编程。
STM32将检测到的按键信号转换成数字量,显示于数码管上。
该系统灵活性强,易于操作,可靠性高,将会有更广阔的开发前景。
2总体设计方案
该智能键盘电路由ARM最小系统,矩阵键盘电路和显示电路组成,在常规的4*4矩阵键盘的基础上,通过改进实现了用4个IO口完成4*4矩阵键盘。
2.1总体设计框图
本电路主要由3大部分电路组成:
矩阵键盘电路、ARM最小系统电路、按键显示电路。
其中ATM最小系统主要由复位电路和时钟电路组成。
电路复位后数码管显示字符“—”表示没有按键,显示电路由STM32的PD0—PD7来控制数码管显示是哪个按键按下。
总体设计方框图,如图1所示。
STM32
复位电路
矩阵键盘电路
时钟电路
按键显示电路
图1总体设计方框图
3智能键盘设计原理分析
3.1STM32复位和时钟电路设计
此电路主要是复位电路和时钟电路两部分,其中复位电路采用按键手动复位和上电自动复位组合,电路如图2(右)所示:
其中14脚为STM32的复位端。
时钟电路如图2(左)所示:
晶振采用的是8MHz和32.786KHz,8MKz分别接STM32的12脚和13脚,32.786KHz分别接STM32的8脚和9脚。
图2STM复位和时钟电路设计
3.2矩阵键盘电路的设计
该电路的四个端子分别接STM32的PB12—PB15,电路如图3所示。
图3矩阵键盘电路
该矩阵键盘电路扫描方法如下:
(1)PB15,PB14,PB13,PB12设置为输入并内部上拉。
程序读取这四个IO口的引脚电平,如果某个IO为低电平,则是该列中相应IO口对应行处的按键按下。
(2)PB15输出低电平,PB14,PB13,PB12设置为输入并内部上拉。
程序读取PB14,PB13,PB12这三个IO口的引脚电平。
如果某个IO为低电平,则是第一列中相应IO口对应行处的按键按下。
(3)PB14输出低电平,PB15,PB13,PB12设置为输入并内部上拉。
程序读取PB15,PB13,PB12这三个IO口的引脚电平。
如果某个IO为低电平,则是第二列中相应IO口对应行处的按键按下。
(4)PB13输出低电平,PB15,PB14,PB12设置为输入并内部上拉。
程序读取PB15,PB14,PB12这三个IO口的引脚电平。
如果某个IO为低电平,则是第三列中相应IO口对应行处的按键按下。
(5)PB12输出低电平,PB15,PB14,PB13设置为输入并内部上拉。
程序读取PB15,PB14,PB13这三个IO口的引脚电平。
如果某个IO为低电平,则是第四列中相应IO口对应行处的按键按下。
3.3按键去抖动
每隔10ms扫描键盘一次,当扫描某个按键按下时,则开始计数,当连续4次扫描(也就是40ms)都是这个按键按下时,说明按键有效。
如果不到四次计数,就采集不到该按键按下,则说明该按键无效。
3.4按键显示电路
本设计采用STM32的IO口PD0—PD7来控制数码管来实时显示按键状态。
当按键有按下时,数码管将显示对应的按键编号“0—F”,对应表示的按键是“SW1—SW16”。
按键显示电路,如图4。
图4按键显示电路
4程序流程图
程序流程图,如图4所示。
图5程序流程图
5总体电路图
总体电路图,如图6所示。
图6总体电路图
5总结与体会
通过这次矩阵键盘的设计,使我对ARM有了更深的理解。
刚开始拿到选题,我先是查找相关资料,从图书馆和网上找到相关的课题,参考借鉴别人的设计,从而理清我们设计的思路。
此次作业设计大致可以分为两部分,电路图部分和程序编程部分,其中最有难度的是程序的编写与调试。
在编写程序的过程中,我遇到了各种各样的问题,没有总体的思路,对程序不知该如何去编写。
我知道知道这个是我的弱点。
在接下来的时间,在ARM编程方面,我得需要加强。
平时多用KeiluVision4在ARM开发板上进行程序调试,多看一些程序,慢慢的积累,提升自己。
参考文献:
[1]彭刚、秦志强等.基于ARMCortex-M3的STM32系列嵌入式微控制器应用实践[M].北京:
电子工业出版社
[2]李宁.基于MDK的STM32处理器开发应用[M].北京航空航天大学出版社,2008.
[3]
[4]
附录:
程序:
/*******************************************************************************
**文件名:
main.c
**版本:
1.0
**工作环境:
RealViewMDK-ARM4.20
**作者:
河南科技学院
**生成日期:
2012-03-20
**功能:
模版程序(用户可以在这里简单说明工程的功能)
**相关文件:
无
**修改日志:
2012-03-20创建文档
/*******************************************************************************
*@函数名称main
*@函数说明主函数
*@输入参数无
*@输出参数无
*@返回参数无
*****************************************************************************/
voidDelay_nus(unsignedlongn)
{
unsignedlongj;
while(n--)
{
j=8;
while(j--);
}
}
voidDelay_nms(unsignedlongn)
{
while(n--)
Delay_nus(1100);
}
voidLed_GPIO_Config(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDefGPIO_InitStructure;
/*开启GPIOA的外设时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
/*选择要控制的GPIOC引脚*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz*/
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
/*调用库函数,初始化GPIOC*/
GPIO_Init(GPIOD,&GPIO_InitStructure);
/*关闭所有led灯*/
GPIO_SetBits(GPIOD,GPIO_Pin_All);
}
voidKey_GPIO_Config(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDefGPIO_InitStructure;
/*开启GPIOC的外设时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
/*选择要控制的GPIOC引脚*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz*/
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
/*调用库函数,初始化GPIOC*/
GPIO_Init(GPIOD,&GPIO_InitStructure);
/*关闭所有led灯*/
GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
}
voidkey_scan(void)
{
//GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)&&
GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)&&
GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)&&
GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)!
=1)
{
Delay_nms(5);
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_12)&&
GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)&&
GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_14)&&
GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_15)!
=1)
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==0)
GPIO_ResetBits(GPIOD,GPIO_Pin_0);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==0)
GPIO_ResetBits(GPIOD,GPIO_Pin_1);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0)
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==0)
GPIO_ResetBits(GPIOB,GPIO_Pin_13);
}
}
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)
&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)
&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)!
=1)
{
Delay_nms(5);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)
&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)
&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)!
=1)
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==0)
GPIO_ResetBits(GPIOB,GPIO_Pin_14);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0)
GPIO_ResetBits(GPIOD,GPIO_Pin_5);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==0)
GPIO_ResetBits(GPIOD,GPIO_Pin_6);
}
}
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_ResetBits(GPIOB,GPIO_Pin_13);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)
&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)
&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)!
=1)
{
Delay_nms(5);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)
&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)
&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)!
=1)
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==0)
GPIO_ResetBits(GPIOD,GPIO_Pin_7);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0)
GPIO_ResetBits(GPIOD,GPIO_Pin_8);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)==0)
GPIO_ResetBits(GPIOD,GPIO_Pin_9);
}
}
GPIO_SetBits(GPIOD,GPIO_Pin_13);
GPIO_ResetBits(GPIOD,GPIO_Pin_14);
if(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_12)
&&GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_13)
&&GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_15)!
=1)
{
Delay_nms(5);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)
&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)
&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)!
=1)
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==0)
GPIO_ResetBits(GPIOD,GPIO_Pin_10);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==0)
GPIO_ResetBits(GPIOD,GPIO_Pin_11);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==0)
GPIO_ResetBits(GPIOD,GPIO_Pin_12);
}
}
GPIO_SetBits(GPIOB,GPIO_Pin_14);
GPIO_ResetBits(GPIOB,GPIO_Pin_15);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)
&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)
&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)!
=1)
{
Delay_nms(5);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)
&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)
&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)!
=1)
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==0)
GPIO_ResetBits(GPIOD,GPIO_Pin_13);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==0)
GPIO_ResetBits(GPIOD,GPIO_Pin_14);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0)
GPIO_ResetBits(GPIOD,GPIO_Pin_15);
}
}
GPIO_SetBits(GPIOB,GPIO_Pin_15);
}
intmain(void)
{
Key_GPIO_Config();
Led_GPIO_Config();
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
/*IWDGcounterclock:
40KHz(LSI)/32=1.25KHz*/
//设置IWDG时钟
IWDG_SetPrescaler(IWDG_Prescaler_256);
/*Setcounterreloadvalueto349*/
//设置定时器重载值
IWDG_SetReload(300);
/*ReloadIWDGcounter*/
//重载IWDG计数器
IWDG_ReloadCounter();
/*EnableIWDG(theLSIoscillatorwillbeenabledbyhardware)*/
//使能IWDG
IWDG_Enable();
while
(1)
{
key_scan();
IWDG_ReloadCounter();
}
}
#ifdefUSE_FULL_ASSERT
/*******************************************************************************
*@函数名称assert_failed
*@函数说明报告在检查参数发生错误时的源文件名和错误行数
*@输入参数file:
源文件名
line:
错误所在行数
*@输出参数无
*@返回参数无
*****************************************************************************/
voidassert_failed(uint8_t*file,uint32_tline)
{
/*用户可以增加自己的代码用于报告错误的文件名和所在行数,
例如:
printf("错误参数值:
文件名%s在%d行\r\n",file,line)*/
/*无限循环*/
while
(1)
{
}
}
#endif
/********************************文件结束*******************************/