zoukankan      html  css  js  c++  java
  • [转载]【Alientek STM32 实验2】按键输入

    原地址,附件下载地址:http://www.openedv.com/posts/list/19.htm

    上一节介绍了STM32的IO口输出,这一节,我们将向大家介绍如何使用STM32的IO口作为输入用。通过本节的学习,你将了解到STM32的IO口作为输入使用的方法。本节分为如下几个小节:

    3.2.1 STM32 IO口简介

    3.2.2 硬件设计

    3.2.3 软件设计

    3.2.1 STM32 IO口简介

    STM32的IO口在上一节已经有了详细的介绍,这里我们不再多说。STM32的IO口做输入使用的时候,是通过读取IDR的内容来读取IO口的状态的。了解了这点,就可以开始我们的代码编写了。

    这一节,我们将通过MiniSTM32板上载有的3个按钮,来控制板上的2个LED,其中KEY0控制DS0,按一次亮,再按一次,就灭。KEY1控制DS1,效果同KEY0。KEY_2(KEY_UP),同时控制DS0和DS1,按一次,他们的状态就翻转一次。

    3.2.2 硬件设计

    该实验所需要的硬件电路在MiniSTM32开发板上都已经连接好了,不需要经过任何设置,直接编写代码就可。LED的连接在上一节已经介绍过了,在MiniSTM32开发板上的按键KEY0是接在PA13上,KEY1是接在PA15上的,WK_UP(KEY2)接在PA0上。如下图所示:

    图3.2.2.1按键与STM32连接原理图

    这里需要注意的是KEY0和KEY1是低电平有效的,而WK_UP是高电平有效的,而且要确认WK_UP按钮与DS18B20的连接是否已经断开,要先断开,否则DS18B20会干扰WK_UP按键!并且KEY0和KEY1连接在与JTAG相关的IO口上,所以在软件编写的时候要先禁用JTAG功能,才能把这两个IO口当成普通IO口使用。这里需要特别说明一下:我们在按键初始化函数里面不仅禁用了JTAG还把SWD也给禁用了,所以在使用的时候要注意,一旦执行了按键初始化函数,你将不能再调试STM32了。要恢复的办法只能设置为ISP模式(B0接V3.3,B1接GND),并刷入其他程序(不会禁用SWD/JTAG的),才能进行硬件调试(需要把B0重新接GND)。
    3.2.3 软件设计

    这里的代码设计,我们还是在之前的基础上继续编写,打开3.1节的TEST工程,然后在HARDWARE文件夹下新建一个KEY文件夹,用来存放与KEY相关的代码。如下图所示:

    图3.2.3.1在HARDWARE下新增KEY文件夹

    然后我们打开USER文件夹下的TEST.Uv2工程,按按钮新建一个文件,然后保存在HARDWARE->KEY文件夹下面,保存为key.c。在该文件中输入如下代码:

    #include <stm32f10x_lib.h>

    #include "key.h"

    #include "delay.h"

    //Mini STM32开发板

    //按键输入 驱动代码

    //正点原子@ALIENTEK

    //2010/5/27

    //按键初始化函数

    //PA0.13.15 设置成输入

    void KEY_Init(void)

    {

    RCC->APB2ENR|=1<<2; //使能PORTA时钟

    RCC->APB2ENR|=1<<0; //开启辅助时钟

    AFIO->MAPR&=0XF8FFFFFF; //清除MAPR的[26:24]

    AFIO->MAPR|=0X04000000; //关闭JTAG

    GPIOA->CRL&=0XFFFFFFF0;//PA0设置成输入

    GPIOA->CRL|=0X00000008;

    GPIOA->CRH&=0X0F0FFFFF;//PA13,15设置成输入

    GPIOA->CRH|=0X80800000;

    GPIOA->ODR|=1<<13; //PA13上拉,PA0默认下拉

    GPIOA->ODR|=1<<15; //PA15上拉

    }

    //按键处理函数

    //返回按键值

    //0,没有任何按键按下

    //1,KEY0按下

    //2,KEY1按下

    //3,KEY2按下

    //注意此函数有响应优先级,KEY0>KEY1>KEY2!!

    u8 KEY_Scan(void)

    {

    static u8 key_up=1;//按键按松开标志

    if(key_up&&(KEY0==0||KEY1==0||KEY2==1))

    {

    delay_ms(10);//去抖动

    key_up=0;

    if(KEY0==0)return 1;

    else if(KEY1==0)return 2;

    else if(KEY2==1)return 3;

    }else if(KEY0==1&&KEY1==1&&KEY2==0)key_up=1;

    return 0;// 无按键按下

    }

    在段代码包含了2个函数,void KEY_Init(void)和u8 KEY_Scan(void),KEY_Init是用来初始化按键输入的IO口的。实现PA0、PA13、PA15的输入设置,这里和上一节的输出配置不同,还有一个JTAG的禁用设置。

    JTAG的禁用,是通过AFIO的MAPR寄存器来配置的。要对复用IO口配置,必须先启用AFIO时钟,AFIO的时钟使能在APB2ENR寄存器里面设置。如下句,就是使能AFIO的时钟:

    RCC->APB2ENR|=1<<0; //开启辅助时钟

    在使能了AFIO时钟之后,我们就可以对AFIO的相关寄存器进行设置了。这里我们要关闭JTAG,与JTAG设置相关的寄存器是AFIO->MAPR寄存器。该寄存器的各位描述如下:

    图3.2.3.2 AFIO->MAPR寄存器各位描述

    其中SWJ_CFG[2:0](AFIO->MAPR[26:24])是与JTAG相关的配置寄存器位,这几位的具体设置以及其对应的描述如下:

    图3.2.3.2 SWJ_CFG位段设置关系

    在这里我们把JTAG和SW口全部禁用了,设置AFIO->MAPR [26:24]为100,如下:

    AFIO->MAPR&=0XF8FFFFFF; //清除MAPR的[26:24]

    AFIO->MAPR|=0X04000000; //关闭JTAG

    以上在设置MAPR的[26:24]位的时候,我们先把这几位清空,然后在置位这几个位。这样,才不会影响之前对AFIO->MAPR的设置。这一点在以后的寄存器配置的时候,大家一定要注意,否则,可能引起之前的配置失效!

    在禁用了JTAG之后,我们再配置PA0、PA13、PA15为输入,其设置与3.1的输出配置差不多,这里不再介绍。

    KEY_Scan函数,则是用来扫描这3个IO口是否有按键按下。这个KEY_Scan函数,扫描某个按键,该按键按下之后必须要松开,才能第二次触发,否则不会再响应这个按键,这样的好处就是可以防止按一次多次触发,而坏处就是在需要长按的时候比较不合适。同时还有一点要注意的就是,该函数的按键扫描是有优先级的,最优先的是KEY0,第二优先的是KEY1,最后是KEY2。该函数有返回值,如果有按键按下,则返回非0值,如果没有或者按键不正确,则返回0。具体怎么实现请参考KEY_Scan的代码。

    保存key.c代码,然后我们按同样的方法,新建一个key.h文件,也保存在KEY文件夹下面。在key.h中输入如下代码:

    #ifndef __KEY_H

    #define __KEY_H

    #include "sys.h"

    //Mini STM32开发板

    //按键输入 驱动代码

    //正点原子@ALIENTEK

    //2010/5/27

    #define KEY0 PAin(13) //PA13

    #define KEY1 PAin(15) //PA15

    #define KEY2 PAin(0) //PA0 WK_UP

    void KEY_Init(void);//IO初始化

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

    #endif

    这段代码里面最关键就是3个宏定义:

    #define KEY0 PAin(13) //PA13

    #define KEY1 PAin(15) //PA15

    #define KEY2 PAin(0) //PA0 WK_UP

    这里使用的是位带操作来实现读取某个IO口的1个位的。同输出一样,我们也有另外一种方法可以实现上面代码的功能,如下:

    #define KEY0 (1<<13) //KEY0 PA13

    #define KEY1 (1<<15) //KEY1 PA15

    #define KEY2 (1<<0) //KEY2 PA0

    #define KEY0_GET() ((GPIOA->IDR&(KEY0))?1:0)//读取按键0

    #define KEY1_GET() ((GPIOA->IDR&(KEY1))?1:0)//读取按键1

    #define KEY2_GET() ((GPIOA->IDR&(KEY2))?1:0)//读取按键2

    通输出一样,我们使用第一种方法,比较简单,看起来也清晰明了,最重要的是修改起来比较方便,后续实例,我们一般都使用第一种方法来实现输入口的读取。而第二种方法则适合在不同编译器之间移植,因为他不依靠其他代码。具体选择哪种,大家可以根据自己的喜好来决定。

    将key.h也保存一下。接着,我们把key.c加入到HARDWARE这个组里面,这一次我们通过双击的方式来增加新的.c文件,双击HARDWARE,找到key.c,加入到HARDWARE里面,如下图所示:

    图3.2.3.3 将key.c加入HARDWARE组下

    可以看到HARDWARE文件夹里面多了一个key.c的文件, 然后还是用老办法把key.h头文件所在的的路径加入到工程里面。回到主界面,在test.c里面编写如下代码:

    #include <stm32f10x_lib.h>

    #include "sys.h"

    #include "usart.h"

    #include "delay.h"

    #include "led.h"

    #include "key.h"

    //Mini STM32开发板范例代码2

    //按键输入实验

    //正点原子@ALIENTEK

    //2010.5.27

    int main(void)

    {

    u8 t;

    Stm32_Clock_Init(9); //系统时钟设置

    delay_init(72); //延时初始化

    LED_Init(); //初始化与LED连接的硬件接口

    KEY_Init(); //初始化与按键连接的硬件接口

    while(1)

    {

    t=KEY_Scan();//得到键值

    if(t)

    {

    switch(t)

    {

    case 1:

    LED0=!LED0;

    break;

    case 2:

    LED1=!LED1;

    break;

    case 3:

    LED0=!LED0;

    LED1=!LED1;

    break;

    }

    }

    }

    }

    注意要将KEY文件夹加入头文件包含路径,不能少,否则编译的时候会报错的哦,呵呵。这段实现代码比较简单,就是实现前面简介所阐述的功能。

    然后按,编译工程,得到结果如下图所示:

    图3.2.3.4 编译结果

    可以看到没有错误,也没有警告。从编译信息可以看出,我们的代码占用FLASH大小为:1792字节(1524+268),所用的SRAM大小为:520个字节。

    这里我们解释一下,编译结果里面的几个数据的意义:

    Code:表示程序所占用FLASH的大小(FLASH)。

    RO-data:表示程序定义的常量(FLASH)。

    RW-data:表示已初始化的全局变量(SRAM)

    ZI-data:表示未初始化的全局变量(SRAM)

    有了这个就可以知道你当前使用的flash和sram大小了,所以,一定要注意的是程序的大小不是.hex文件的大小。

    接下来,我们还是先进行软件仿真,验证一下是否有错误的地方,然后才下载到Mini STM32看看实际运行的结果。

  • 相关阅读:
    网络安全分析
    java实现 洛谷 P1464 Function
    java实现 洛谷 P1464 Function
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1540 机器
    java实现 洛谷 P1540 机器
  • 原文地址:https://www.cnblogs.com/hnrainll/p/1922607.html
Copyright © 2011-2022 走看看