(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)

时间:2024-03-30 07:47:47

1.使能LED灯

本次课程主要是了解GPIO的使用,我们查阅了相应的手册资料之后,可以知道板子上的GPIO0连接到的是按键S2,GPIO1连接到的是LED5。如图1-1所示:(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)

图1-1 GPIO的引脚关系

然后查阅手册知道了GPIO的使用流程,GPIO的基地址,寄存器偏移地址,如图1-2和1-3所示:
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)

图1-2 GPIO的基地址
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图1-3 GPIO的寄存器偏移量

使用GPIO,首先要配置GPIOselect寄存器,然后使其的选择输出寄存器,那么配置每一位都是B01,选择寄存器有两个,每一个16位,那么两个选择寄存器的值都要设置为0x5555。如图1-4所示:
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图1-4 设置GPIO的选择寄存器

然后要设置GPIO的引脚输入输出模式,即设置寄存器GPIOOutputEN。如图1-5所示:
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图1-5 设置GPIO的引脚模式
由于GPIO的0和1引脚的对应关系,我们要设置的是从1引脚输入,从0引脚输出,这样可以实现,按键按下以后从输入信号到1引脚,然后从0引脚输出电平到LED引脚,点亮或者熄灭LED灯。因此设置寄存器值为*((unsigned short *)(0x8000d000+0x08)) = 0xfffe;
(0是输出模式,1是输入模式)
引脚的输入输出模式配置好后,就开始往GPIO输出寄存器里面写入数据,使其输出后点亮LED灯。输出寄存器,如图1-6所示:
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图1-6 写GPIO的输出寄存器
由图可以知道,写输出寄存器的值得前提条件就是设置选择寄存器的模式为输出模式。为了点亮LED灯,而且知道LED灯是低电平有效的,于是我们往输出寄存器里面写入数据0xfffe;即点亮GPIO0对应的那个LED5。
分析结束后,开始编写程序led_on.c,在user/scu/下面添加led_on.c,然后编辑,然后修改Makefile文件,执行以下make clean ,再退出到uClinux-dist目录下,然后执行make编译命令,编译完成后在开发板shell里面执行tftp 192.168.0.222 zRomfs,下载新的zRomfs,再重启,可以看见/bin/目录下面出现了led_on 的命令,运行以下,可以看见开发板上面LED5亮了。程序功能实现。程序(见附录1)如图所示:
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图1-7 编写LED应用程序(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图1-8 修改Makefile文件
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图1-9 执行make clean
然后执行make编译命令;
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图1-10 执行make 编译命令
接着查看一下romfs/bin是否有编译出来的命令led_on,如图1-11所示:
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图1-11 查看命令
下载新的zRomfs到开发板上面,重启开发板。
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图1-12 下载zRomfs
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图1-13 重启后查看led_on
然后先检查LED5亮灭情况
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图1-14 查看LED的亮灭情况
然后在LED灭掉的情况下,运行led_on,
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图1-15 运行led_on
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图1-16 再次检查LED
这时候可以发现LED灯被点亮说明,程序使能成功。

2.使能按键功能
使能按键的功能是在第一个实验的基础上添加按键的功能,有上述,可以知道板子上的GPIO0连接到的是按键S2,GPIO1连接到的是LED5。如图2-1所示:
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)

图2-1 GPIO的引脚关系
所以,只需要在配置好前面的寄存器之后,添加按键的功能即可。
首先要配置GPIOselect寄存器,然后使其的选择输出寄存器,那么配置每一位都是B01,选择寄存器有两个,每一个16位,那么两个选择寄存器的值都要设置为0x5555。
然后设置寄存器值为*((unsigned short *)(0x8000d000+0x08)) = 0xfffe; (0是输出模式,1是输入模式)
这样引脚的输入输出模式配置好后,要开始读取GPIO的输入寄存器的值,如果按键按下之后,对应的输入寄存器的对应位会写1,也就是按键按下后会对GPIO口输入一个1,这个1在按键对应的位置也就是GPIO1。识别到按键后,就将LED点亮,再次识别到,就熄灭。这样循环识别,实现按键控制LED的功能。程序led.c(见附录2)如2-2所示:
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图2-2 编写程序led.c
编写程序led.c的流程是,在user/scu/下面添加led.c,然后编辑,然后修改Makefile文件,执行以下make clean ,再退出到uClinux-dist目录下,然后执行make编译命令,编译完成后在开发板shell里面执行tftp 192.168.0.222 zRomfs,下载新的zRomfs,再重启,可以看见/bin/目录下面出现了led 的命令,运行一下,按动按键S2,可以看见开发板上面LED5亮了,再次按动按键S2,可以看见开发板上面LED5灭了。程序功能实现。如图所示:
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图2-3 修改Makefile文件
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图2-4 执行make clean
然后执行make编译命令;
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图2-5 执行make 编译命令

接着查看一下romfs/bin是否有编译出来的命令led,如图2-6所示:
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图2-6 查看命令
下载新的zRomfs到开发板上面,重启开发板。
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图2-7下载zRomfs
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图2-8 重启后查看led
然后先检查LED5亮灭情况
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图1-14 查看LED的亮灭情况
然后在LED灭掉的情况下,运行led,
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图2-9 运行led
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图2-10 再次检查LED
这时候按动S2按键,可以发现LED灯被点亮说明,然后再次按下S2,发现LED熄灭。
(四)嵌入式:GPIO点亮LED,实现按键控制(操作寄存器)
图2-11 再次检查LED

这样就实现了按键的功能。
总结
这次实验学习了GPIO的相关知识,然后自己学着编写了两个简单的操作GPIO的程序,从这两个实验中可以发现,对GPIO的实现,需要了解GPIO的配置过程,相关寄存器的作用以及对寄存器的操作过程,这是很复杂的事,因为要查阅很多的手册,汇总起来,有自己对GPIO的的理解,才能正确使用它的寄存器去配置GPIO,实现相关的功能作用。这次的实验,我们确确实实的触摸到了最底层的硬件寄存器,而不是像以往的编写应网络用程序,又或者是修改内核配置那样,对硬件是隔离开的,这次的实验对我们来说是一次重大的转变,让我们有熟悉了一种开发模式(相对于操作系统提供的API接口函数),那就是直接操作寄存器。
这次实验课的内容不多,却很大的不同,所以多看板子的硬件手册是很重要的。

附录1
#include<stdio.h>
int main()
{
	unsigned short inputval;
	/***设置GPIO模式为输出模式**/
	*((unsigned short *)(0x8000d000+0x00)) = 0x5555;
	*((unsigned short *)(0x8000d000+0x04)) = 0x5555;

	/***设置哪一个引脚输出--最后一个GPIO引脚输出(每一位0是输出模式,1是输入模式)***/
	*((unsigned short *)(0x8000d000+0x08)) = 0xfffe;
	//往GPIO输出寄存器里面写入0bxxxx0--0点亮LED(低电平有效)
	*((unsigned short *)(0x8000d000+0x0c)) = 0xfffe;
	return 0;
}

附录2
#include<stdio.h>
void main()
{
	unsigned short inputval;
	int cnt = 1;
	/***设置GPIO模式为输出模式**/
	*((unsigned short *)(0x8000d000+0x00)) = 0x5555;
	*((unsigned short *)(0x8000d000+0x04)) = 0x5555;

	/***设置哪一个引脚输出--最后一个GPIO引脚输出(每一位0是输出模式,1是输入模式)***/
	*((unsigned short *)(0x8000d000+0x08)) = 0xfffe;
	/*检查输入寄存器的值,如果里面对的值与上0x02,即0bxxxx10,结果是0bxxxx10-即第二位是1,那么说明按键按动
	由于GPIO的0引脚直接与LED相连接,所以配置最后一位GPIO输出信号的值,就可以点亮或者熄灭LED灯
	*/
	while(1)
	{	
		inputval = *((unsigned short *)(0x8000d000+0x10));
		if(((inputval&0x02)==0x02) && cnt)
		{
			*((unsigned short *)(0x8000d000+0x0c)) = (inputval&0xfffe);//往GPIO输出寄存器里面写入0bxxxx0--0点亮LED(低电平有效)
			cnt--;
			
		}
		else if(((inputval&0x02)==0x02) && (!cnt))
		{
			*((unsigned short *)(0x8000d000+0x0c)) = (inputval | 0x0001);//往GPIO输出寄存器里面写入0bxxxx1--1熄灭LED
			cnt++;
		}
	}
}