嵌入式开发十四:按键输入实验

       前面两个实验,我们介绍了 STM32F4 的 IO 口作为输出的使用,这一次,我们将向大家介绍如何使用 STM32F4 的 IO 口作为输入用。我们将利用板载的 4 个按键,来控制板载的两个 LED 的亮灭和蜂鸣器。通过本次的学习,你将了解到 STM32F4 的 IO 口作为输入口 的使用方法。

目录

一、实现的功能

二、 按键与输入数据寄存器介绍

2.1独立按键简介

2.2 GPIO 端口输入数据寄存器(IDR)

三、硬件设计

四、 程序设计

4.1创建工程模板

4.2工程中创建对应的文件

4.3添加文件路径

4.4添加相应的外设固件库和所需文件

​4.5程序流程图

4.5.1 编写LED0和LED1初始化函数驱动代码

4.5.2  编写Beep蜂鸣器初始化函数

4.5.3 编写按键初始化函数

4.5.4 编写按键扫描函数

4.5.5 编写延时函数

4.5.6  程序主函数

五、下载验证


一、实现的功能

         通过探索者 STM32F4 开发板上载有的 4 个按钮(KEY_UP、 KEY0、KEY1 和 KEY2),来控制板上的 2 个 LED(DS0 和 DS1)和蜂鸣器,其中 KEY_UP 控 制蜂鸣器,按一次叫,再按一次停;KEY2 控制 DS0,按一次亮,再按一次灭;KEY1 控制 DS1, 效果同 KEY2;KEY0 则同时控制 DS0 和 DS1,按一次,他们的状态就翻转一次。

二、 按键与输入数据寄存器介绍

2.1独立按键简介

        按键是一种电子开关,使用时轻轻按开关按钮就可使开关接通,当松开手时, 开关断开。我们开发板上使用的按键及内部简易图如下图所示:

       按键管脚两端距离长的表示默认是导通状态,距离短的默认是断开状态,如 果按键按下,初始导通状态变为断开,初始断开状态变为导通。几乎每个开发板都会板载有独立按键,因为按键用处很多。常态下,独立按键是断开的, 按下的时候才闭合。每个独立按键会单独占用一个 IO 口,通过 IO 口的高低电平判断按键的状态。但是按键在闭合和断开的时候,都存在抖动现象,即按键在闭合时不会马上就稳定的连接, 断开时也不会马上断开。这是机械触点,无法避免。通常的按键所用开关为机械弹性开关, 当机械触点断开 、闭合时,电压信号 如下图所示:

       由于机械点的弹性作用,按键开关在闭合时不会马上稳定的接通,在断开时也不会一下子断开,因而在闭合和断开的瞬间均伴随着一连串的抖动。抖动时间的长短由按键的机械特性决定的,一般为 5ms 到 10ms。按键稳定闭合时间的长短则由操作人员的按键动作决定的,一般为零点几秒至数秒。按键抖动会引起按键被误读多次。为了确保 CPU 对按键的一次闭合仅作一次处理(即采样稳定闭合阶段),必须进行消抖。 消抖方法分为硬件消抖和软件消抖,我们常用软件的方法消抖。

  1. 软件消抖:方法很多,最简单的是延时消抖。检测到按键按下后,一般进行 10ms 延时,用于跳过抖动的时间段,如果消抖效果不好可以调整这个 10ms 延时,因为不同类 型的按键抖动时间可能有偏差。待延时过后再检测读取按键状态,如果没有按下,那我们就判断这是抖动或者干扰造成的;如果按键还是按下状态,那么我们就认为这是按键真的按下了。对按键释放的判断同理。
  2. 硬件消抖:利用 RC 电路的电容充放电特性来对抖动产生的电压毛刺进行平滑出来,从而实现消抖,但是成本会更高一点,本着能省则省的原则,我们推荐使用软件消抖即可。

2.2 GPIO 端口输入数据寄存器(IDR)

       本实验我们将会用到 GPIO 端口输入数据寄存器,下面来介绍一下。 该寄存器用于存储 GPIOx 的输入状态,它连接到施密特触发器上,IO 口外部的电平信号经过触发器后,模拟信号就被转化成 0 和 1 这样的数字信号,并存储到该寄存器中。寄存器描述如图所示。

该寄存器低 16 位有效,分别对应每一组 GPIO 的 16 个引脚。当 CPU 访问该寄存器,如果对应的某位为 0(IDRy=0),则说明该 IO 口输入的是低电平,如果是 1(IDRy=1),则表示输入的是高电平,y=0~15。对于我们使用固件库编程,STM32F4 的 IO 口做输入使用的时候,是通过调用函数 GPIO_ReadInputDataBit()来读取 IO 口的状态的,也就是读取该寄存器的值。

三、硬件设计

本实验用到的硬件资源有:

LED0和LED1 以及蜂鸣器和 STM32F4 的连接在前面都已经分别介绍了,独立按键硬件部分的原理图,如图所示,在探索者 STM32F4 开发板上的按键KEY_UP 连接在 PA0 上, KEY0 连接在 PE4 上、KEY1 连接在 PE3 上、KEY2 连接在 PE2 上。如图 8.2.1 所示:

这里需要注意的是:

     KEY0、KEY1 和 KEY2 是低电平有效的,而 KEY_UP 是高电平有效的,并且外部都没有上下拉电阻,所以,需要在 STM32F4 内部设置上下拉。 这里的有效指的是:按键按下时,它是处于高电平还是低电平,很明显,从按键的原理图可知,对于KEY0、KEY1 和 KEY2 ,当按键按下时,GPIO 引脚的输入状态为低电平(按键所在的电路不通,引脚接地)。因此,他们是低电平有效,并且,我们在设置这三个端口模式时,应该上拉,默认是高电平,当按键按下,是低电平,这样便可以检测按键是否按下;对于KEY_UP,当按键被按下的时候,引脚的输入状态为高电平 ,(按键所在的电路导通,引脚接到电源)。因此,他们是高电平有效,并且,我们在设置这个端口模式时,应该下拉,默认是低电平,当按键按下,是高电平,这样便可以检测按键是否按下;总结:只要我们检测引脚的输入电平,即可判断按键是否被按下。 

四、 程序设计

4.1创建工程模板

     直接复制创建好的库函数模板, 在此模板上进行程序开发。将复制过来的模板文件夹重新命名为“实验三:按键输入实验 ”。打开此文件夹,在Project目录下新建一个文件夹,命名为:MyKey,用于存放按键的驱动程序,因为本次实验涉及到LED、Beep因此,同样需要建立和前两个实验一样的文件夹,存放对应的驱动程序。创建好后,目录如下所示:

4.2工程中创建对应的文件

      在工程下创建对应的文件夹,同时新建对应的源文件和头文件,创建好后如下图所示:


4.3添加文件路径

       要想工程在编译阶段能够找到创建的文件,必须要加入文件路径,详细步骤之前已经介绍过,路径添加完毕后,如下图所示:

4.4添加相应的外设固件库和所需文件

     本次实验并没有用到额外的外设,我们就是通过STM32F407上的GPIOF口作为输入口和输出口,输出高电平,蜂鸣器发声,输出低电平,蜂鸣器不发声(IO口驱动蜂鸣器);输出低电平,LED灯点亮,输出低电平,LED灯熄灭;输入高低电平可判断按键是否被按下。


4.5程序流程图

         程序流程图能帮助我们更好的理解一个工程的功能和实现的过程,对学习和设计工程有很好的主导作用。本实验的程序流程图如下:

4.5.1 编写LED0和LED1初始化函数驱动代码

      由于后面我们需要利用按键来控制实现不同的功能,KEY2 控制 DS0,按一次亮,再按一次灭;KEY1 控制 DS1, 效果同 KEY2;KEY0 则同时控制 DS0 和 DS1,按一次,他们的状态就翻转一次。所以我们必须要首先对它们进行初始化,设置PF9和PF10的GPIO口的端口模式。这与我们之前跑马灯实验初始化函数相同。

在 myled.h文件夹下编写如下代码:

#ifndef __MYLED_H
#define __MYLED_H

void LED_Init(void);  //LED初始化函数

#endif

在 myled.c文件夹下编写如下代码:

#include "stm32f4xx.h"                  // Device header
#include "myled.h"


void LED_Init(void)
{
    //第一步:使能GPIOF两个口的时钟 
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能 GPIOF 时钟
	
   //第二步:GPIOF9,F10 初始化设置
   GPIO_InitTypeDef GPIO_InitStructure;
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;//LED0 和 LED1 对应 IO 口
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
   GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化 GPIO

   //第三步:设置灯的初始状态
   GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);//GPIOF9,F10 设置高电平,灯灭

}

4.5.2  编写Beep蜂鸣器初始化函数

      由于后面我们需要利用按键来控制实现不同的功能,其中 KEY_UP 控 制蜂鸣器,按一次叫,再按一次停;所以我们必须要首先对它们进行初始化,设置PF8的GPIO口的端口模式.

在 mybeep.h文件夹下编写如下代码:

#ifndef __MYBEEP_H__
#define __MYBEEP_H__

void BEEP_Init(void);   //蜂鸣器初始化函数

#endif

在 mybeep.c文件夹下编写如下代码:

#include "stm32f4xx.h"                  // Device header
#include "mybeep.h"

void BEEP_Init(void)
{
	//第一步:开启时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能 GPIOF 时钟
    //第二步:初始化蜂鸣器对应引脚 GPIOF8
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
    GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化 GPIO
	
    GPIO_ResetBits(GPIOF,GPIO_Pin_8); //蜂鸣器对应引脚 GPIOF8 拉低,此时不会发声(初始状态)
    
}

4.5.3 编写按键初始化函数

      我们后面需要检测按键是否被按下,从而执行不同的操作,实现不同的功能,通过上面查看原理图我们知道,有四个按键,在探索者 STM32F4 开发板上的按键KEY_UP 连接在 PA0 上, KEY0 连接在 PE4 上、KEY1 连接在 PE3 上、KEY2 连接在 PE2 上。此时GPIO口需要用作输入口,通过检测对应GPIO口的高低电平(通过标准库函数读取即可),从而判断按键是否被按下,因此,我们首先需要对按键进行初始化;

在 mykey.h文件夹下编写如下代码:

#ifndef __MYKEY_H__
#define __MYKEY_H__
#include <stdint.h>

//对按键操作函数做了下面的定义
#define KEY0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) //PE4
#define KEY1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) //PE3 
#define KEY2 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2) //PE2
#define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) //PA0


//按键进行宏定义增加程序可读性
#define KEY0_PRES 1
#define KEY1_PRES 2
#define KEY2_PRES 3
#define WKUP_PRES 4


void KEY_Init(void);//按键初始化函数
uint8_t KEY_Scan(uint8_t mode); //按键扫描函数


#endif

      需要注意的是:为提高代码的可读性,为了后续对按键进行便捷的操作,我们为按键操作函数做了下面的定义,此外我对按键的键值同样使用了宏定义。

//对按键操作函数做了下面的定义
#define KEY0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) //PE4
#define KEY1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) //PE3 
#define KEY2 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2) //PE2
#define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) //PA0

     通过这种方式,我们后面直接使用KEY0、KEY1、KEY2、WK_UP相当于调用相应端口读取电平函数,KEY0、KEY1、KEY2和WK_UP分别是读取对应按键状态的宏定义。用GPIO_ReadInputDataBit() 函数实现,该函数的返回值就是 IO 口的状态,返回值是枚举类型,取值 0 或者 1。看起来更加直观。

//按键进行宏定义增加程序可读性
#define KEY0_PRES 1
#define KEY1_PRES 2
#define KEY2_PRES 3
#define WKUP_PRES 4

    KEY0_PRES、KEY1_PRES、KEY2_PRES 和 WKUP_PRES 则是按键对应的四个键值宏定 义标识符。同样使得代码更加直观,而不是数字1 2 3 4 ,直接代表按键。

 在 mykey.c文件夹下编写如下代码:

      KEY_Init()函数用来初始化按键的端口及时钟。要知道按键是否按下,就需要读取按键所对应的 IO 口电平状态,因此我们需要把 GPIO 配置为输入模式,并且需要把 KEY_UP 按键对应的GPIOA_Pin_0设置为下拉模式,其他几个GPIO口,PE4、  PE3、  PE2需要设置为上拉模式,前面我们分析过。

#include "stm32f4xx.h"                  // Device header
#include "mykey.h"
#include "mydelay.h"

//按键初始化函数:四个按键对应4个GPIO口
void KEY_Init(void)
{
	//第一步:开启时钟,使能 GPIOA,GPIOE 时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
	
	//第二步:设置端口模式  
	//step1.对于PE2、PE3、PE4应设置为输入上拉模式
	GPIO_InitTypeDef Struct;
	Struct.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;//KEY0 KEY1 KEY2 对应引脚
    Struct.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
    Struct.GPIO_Speed = GPIO_Speed_100MHz;//100M
    Struct.GPIO_PuPd = GPIO_PuPd_UP;//上拉,默认高电平
    GPIO_Init(GPIOE, &Struct);//初始化 GPIOE2,3,4
	
	//step2.对于PA0应设置为输入下拉模式
	GPIO_InitTypeDef Struct1;//按键WK_UP 对应引脚 PA0
	Struct1.GPIO_Pin = GPIO_Pin_0;
    Struct1.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
    Struct1.GPIO_Speed = GPIO_Speed_100MHz;//100M
    Struct1.GPIO_PuPd = GPIO_PuPd_DOWN ;//下拉,默认低电平
    GPIO_Init(GPIOA, &Struct1);//初始化 GPIOA0

}

4.5.4 编写按键扫描函数

      要知道哪个按键被按下,就需要编写按键扫描函数

同样在 mykey.c文件夹下编写如下代码:

      mode:   具体含义如下:

  1. 0, 不支持连续按(当按键按下不放时, 只有第一次调用会返回键值, 必须松开以后, 再次按下才会返回其他键值)
  2. 1, 支持连续按(当按键按下不放时, 每次调用该函数都会返回键值)
uint8_t KEY_Scan(uint8_t mode)
{
	static uint8_t key=1;//按键按松开标志
    if(mode)
	{	
		key=1; 
	}	
	
    if(key&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))  //任何一个按键按下
    {
       My_Delay_ms(10);//去抖动
       key=0;      
       if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0)  //按键0被按下
		   return 1;
       else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==0)//按键1被按下
		   return 2;
       else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==0)//按键2被按下
		   return 3;
       else if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1)//按键WK_UP被按下
		   return 4;
    }
	else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==1&&GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==1&&GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==1&&GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==0)
	{
		key=1;
	}		
    return 0;// 无按键按下
}

         key_scan 函数用于扫描这 4 个 IO 口是否有按键按下。key_scan 函数,支持两种扫描方式, 通过 mode 参数来设置。

  1. 当 mode 为 0 的时候,key_scan 函数将不支持连续按,扫描某个按键,该按键按下之后必须要松开,才能第二次触发,否则不会再响应这个按键,这样的好处就是可以防止按一次多次触发,而坏处就是在需要长按的时候比较不合适。
  2. 当 mode 为 1 的时候,函数是支持 连续扫描的,即使按键未松开,在函数内部有 if(mode==1)这条判断语句,因此 key 始终是等于 1 的,所以可以连续扫描按键,当按下某个按键,会一直返回这个按键的键值,这样做的好处是可以很方便实现连按操作。

        有了 mode 这个参数,大家就可以根据自己的需要,选择不同的方式。函数内的 My_Delay_ms(10)即为软件消抖处理,通常延时 10ms 即可。 KEY_Scan 函数还带有一个返回值,如果未有按键按下,返回值即为 0,否则返回值即为对应按键的键值,如 KEY_UP_PRESS、KEY0_PRESS、KEY1_PRESS、KEY2_PRESS,这都是头文件内定义好的宏,方便大家记忆和使用。函数内定义了 一个 static 变量,所以该函数不是一个可重入函数(静态局部变量在函数进行下一次调用时不会重新初始化,直接使用上一次调用函数后的值)。还有一点要注意的就是该函数按键的扫描是有优先级的,因为函数内用了 if...else if...else 格式,所 以最先扫描处理的按键是 KEY_UP,其次是 KEY0,然后是 KEY1,最后是 KEY2。如果需要将其优先级设置一样,那么可以全部用 if 语句。

4.5.5 编写延时函数

  利用系统节拍定时器可以实现精准延时(后期博客详细总结),因此我们实现了三个延时任意时间的函数,后续项目使用直接引入头文件,然后直接调用相应的函数即可。

在 mydelay.h文件夹下编写如下代码:

#ifndef __MYDELAY_H__
#define __MYDELAY_H__
#include <stdint.h>

void My_Delay_us(uint32_t num); //延时任意微秒
void My_Delay_ms(uint32_t num); //延时任意毫秒
void My_Delay_s(uint32_t num);  //延时任意秒

#endif

在 mydelay.c文件夹下编写如下代码: 

#include "stm32f4xx.h"                  // Device header
#include "mydelay.h"
 
 
//延时num微秒
void My_Delay_us(uint32_t num)
{
    while(num--)
    {
        SysTick ->CTRL = (1 << 0);
    
        SysTick ->CTRL &= ~(1<<2);
    
        SysTick ->CTRL &= ~(1<<1);
    
        SysTick ->VAL = 0x0;
    
        SysTick ->LOAD = 21;   //1秒 21000000HZ,1毫秒 21000HZ  1微秒 21 HZ
    
        while(!(SysTick ->CTRL & (1<<16)));
        SysTick ->CTRL = ~(1<<0);
    }
}
 
 
//延时num毫秒,1毫秒等于1000微秒
void My_Delay_ms(uint32_t num)
{
    while(num--)
    {
        My_Delay_us(1000);
    }
}
 
 
//延时num秒,1秒等于1000毫秒
void My_Delay_s(uint32_t num)
{
    while(num--)
    {
        My_Delay_ms(1000);
    }
}

4.5.6  程序主函数
 

      首先是打开外设时钟。接下来调用 led_init 来初始化 LED 灯,调用 beep_init 函数初始化蜂鸣器,调用 key_init 函数初始化按键。最后在无限循环里面扫描获取键值,扫描函数传入的参数值为 0,即 mode=0, 所以这里只对它单次按键操作,将扫描函数返回后的键值保存在变量 key 内,接着用键值判断哪个按键按下,如果有按键按下则翻转相应的灯或翻转蜂鸣器,如果没有按键按下则延时 10ms。编写代码如下:

      这里用到了一个电平翻转函数 GPIO_ToggleBits ();,一个按键被连续按下两次,那么电平便会翻转,从而控制灯的翻转和蜂鸣器的打开和关闭。

#include "stm32f4xx.h"                  // Device header
#include "mykey.h"
#include "mydelay.h"
#include "myled.h"
#include "mybeep.h"


int main(void)
{
	uint8_t  key; //保存键值   
    LED_Init(); //初始化 LED 端口PF9和PF10
    BEEP_Init(); //初始化蜂鸣器端口PF8
    KEY_Init(); //初始化与按键连接的硬件接口
	while(1)
	{
		key=KEY_Scan(0); //得到键值
    if(key)
    { 
	    switch(key)
       { 
		   case WKUP_PRES:            //控制蜂鸣器开和关
		   GPIO_ToggleBits (GPIOF,GPIO_Pin_8);
           break;
		   
           case KEY0_PRES:           //控制 LED0 翻转
		   GPIO_ToggleBits (GPIOF,GPIO_Pin_9);
           break;
		   
           case KEY1_PRES:          //控制 LED1 翻转
		   GPIO_ToggleBits (GPIOF,GPIO_Pin_10);
           break;
		   
           case KEY2_PRES:        //同时控制 LED0,LED1 翻转 
		   GPIO_ToggleBits (GPIOF,GPIO_Pin_9);
		   GPIO_ToggleBits (GPIOF,GPIO_Pin_10);
           break;
       }
    }
  else 
  {
	        My_Delay_ms(10); //延时10ms
		
  }

     }  

}
	

五、下载验证

我们先来看看编译结果,如图所示:

      可以看到 0 错误,0 警告,编译通过接下来,大家就可以下载验证了。这里我们使用 DAP 仿真器下载。下载完之后,运行结果如图所示,可以看到我们可以按 KEY0、KEY1、KEY2 来看看 LED 灯的变化或者按 KEY_UP 看看蜂鸣器的变化,和我们预期的结果一致,符合预期设计。

按键输入

         至此,我们的本次的学习就结束了。学习了 STM32F407 的 IO 作为输入的使用方法, 在前面的 GPIO 输出的基础上又学习了一种 GPIO 使用模式,大家可以回顾前面跑马灯实验介绍的 GPIO 的八种模式类型巩固 GPIO 的知识。

  • 32
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
一、 实验目的 1.了解S3C2410的通用I/0接口 2.掌握I/0功能的复用并熟练的配置,进行编程实验 二、 实验内容 1.在实验箱的CPU 板上点亮LED 灯LED1、LED2,并轮流闪烁! 三、 实验设备 1.EL-ARM-860教学实验箱,PentiumII以上的PC机,仿真调试电缆。 2.PC操作系统WIN98或WIN2000或WINXP,ADS1.2集成开发环境,仿真调试驱动程序。 四、 实验原理 S3C2410 CPU共有117个多功能复用输入输出口,分为8组端口: ·4个16位的I/0端口(PORT C、PORT D、PORT E、PORT G) ·2个11位的I/0端口(PORT B和 PORT H) ·1个8位的I/0端口(PORT F) ·1个23位的I/0端口(PORT A) 这些通用的GPI/0接口,是可配置的,PORTA除功能口外,它们仅用作输出使用,剩下的 PORTB、PORTC、PORTD、PORTE、PORTF、PORTG均可作为输入输出口使用。 配置这些端口,是通过一些寄存器来实现的,这些寄存器均有各自的地址,位长 32位。 往该地址中写入相应的数据,即可实现功能及数据配置。 GPACON (Ox56000000)/ /Port A control GPADAT (Ox56000004) //Port A data GPBCON (Ox56000010)//Port B control GPBDAT (Ox56000014)/ /Port B data GPBUP(Ox56000018)//Pull-up control B GPCCON (Ox56000020)/ /Port C control GPCDAT (Ox56000024)/ /Port C data GPCUP (Ox56000028)//Pull-up control c GPDCON (Ox56000030)//Port D control GPDDAT (Ox56000034) //Port D data GPDUP (Ox56000038)//Pul1-up control D GPECON (Ox56000040)//Port E control GPEDAT (Ox56000044)//Port E data GPEUP(Ox56000048)//Pul1-up control E GPFCON (Ox56000050)//Port F control GPFDAT (Ox56000054)/ /Port F data GPFUP(Ox56000058)//Pull-up control F GPGCON (Ox56000060)/ /Port G control GPGDAT (Ox56000064)//Port G data GPGUP (Ox56000068)//Pul1-up control G GPHCON (Ox56000070)/ /Port H control GPHDAT (Ox56000074)//Port H data GPHUP (Ox56000078)//Pull-up control H 现用G口、H口举例说明。对于G口如表1、表2、表3, 表1 表2 也就是说,在地址Ox0x56000060中,给32位的每一位赋值,那么,在CPU的管脚上就定义了管脚的功能值。当G口某管脚配置成输出端口,则在 PDATG对应的地址中的对应位上,写入1,则该管脚输出为高电平,写入0,则该管脚输出为低电平。若配置为功能管脚,则该管脚变成具体的功能脚。 对于H口见表4、表5、表6、表7 表6 也就是说,在地址Ox56000070中,给32位的每一位赋值,那么,在CPU的管脚上就定义了管脚的功能值。当H口某管脚配置成输入端口,则在 GPHDAT对应的地址中的对应位上,得到1,则该管脚的输入为高电平,得到0,则该管脚的输入为低电平。当H口某管脚配置成输出端口,则在GPGDAT对应的地址中的对应位上,写入1,则该管脚输出为高电平,写入0,则该管脚输出为低电平。若配置为功能管脚,则该管脚变成具体的功能脚。其他端口配置请参见PDF文挡。 在程序中对GPI/0各寄存器的读写实现,是通过给宏赋值实现的。这些宏在2410addr.h中定义;具体如:。 #define rGPACON (* (volatile unsigned *)Ox56000000)(//Port A control #define rGPADAT (*

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未来可期,静待花开~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值