类似树莓派、龙芯智龙这类mini开发板上的Linux系统,一般都提供了类似Arduino操作引脚电路、探测的功能,统称GPIO接口(General-purpose input/output,通用目的输入输出),但是使用上却涉及稍复杂的Linux内核概念。不同于Arduino,直接将物理硬件暴露给用户进行编程和操作,Linux系统必须通过一个叫“驱动”的程序将物理硬件进行封装,然后把其包装好的接口按照linux文件系统的方式提供给用户进行操作,用户操作硬件的时候必须通过这个文件系统进行输入输出,也就是所谓的“用户态编程”。总结起来就是3种方式:

  1. 内核编程,将源代码跟linux源码放在一起编译,将编译好的操作系统安装到目标机子(开发板)上
  2. 内核模块编程,编译成.ko文件,通过安装驱动的方式把编译好的文件放在系统内核中
  3. 用户态编程,编译成普通可执行文件,通过fopen等操作文件的方式,打开/sys/class/gpio/下面的用户态接口(或者/dev下面自己编译的内核驱动接口),像读写文件一样操作电路。

闪烁led灯

(用户态编程,此时龙芯智龙V2上的LED对应的GPIO口为51号)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(void){
	FILE *p=NULL;
	int i=0;
	int port=51;

	p = fopen("/sys/class/gpio/export","w");
	fprintf(p,"%d",port);
	fclose(p);

	p = fopen("/sys/class/gpio/gpio51/direction","w");
	fprintf(p,"out");
	fclose(p);

	for(i=0;i<100;i++){
		p = fopen("/sys/class/gpio/gpio51/value","w");
		fprintf(p,"%d",1);
		sleep(1);
		fclose(p);

		p = fopen("/sys/class/gpio/gpio51/value","w");
		fprintf(p,"%d",0);
		sleep(1);
		fclose(p);
	}
	p = fopen("/sys/class/gpio/unexport","w");
	fprintf(p,"%d",port);
	fclose(p);
	return 0;
}

在VMware虚拟机安装的Kylin Ubuntu上通过交叉编译工具进行编译:

mipsel-linux-gcc led51.c -o led51_mips

将编译好的led51_mips可执行文件考到u盘,通过u盘考到智龙主板上,远程链接智龙并进入智龙的linux系统,输入./led51_mips运行该可执行文件,可以看到智龙主板上5颗led灯在不停地闪烁,说明程序成功。

按键接收和控制代码

(用户态编程,此时龙芯智龙V2上的S3按键对应的GPIO口为92号):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(void){
	FILE *p=NULL;
	char i[100]={0,};
	p = fopen("/sys/class/gpio/export","w");
	fprintf(p,"%d",92);
	fclose(p);
	p = fopen("/sys/class/gpio/gpio92/direction","w");
	fprintf(p,"in");  //配置成输入
	fclose(p);
	while(1){
		//以只读方式打开
		p = fopen("/sys/class/gpio/gpio92/value","r");
		//使文件读写定位到0位置
		fseek(p , 0 , 0);
		#if 0
		//将文件内容输出到存储器i中,注意要以字符串的方式,否则会出错
		fscanf(p,"%s",i);
		#else
		//从文件中读出数据到存储器i中
		fread(i , 1, 1 ,p);
		#endif
		//以字符的方式将读到的值打印出
		printf("key = %c \r\n",i[0]);
		sleep(1);
		//注意这里必须要关闭,然后再次读时再重新打开,这样只面的内容才会更新
		fclose(p);
	}
	return 0;
}

在VMware虚拟机安装的Kylin Ubuntu上通过交叉编译工具进行编译:

mipsel-linux-gcc button92.c -o button92_mips

将编译好的button92_mips可执行文件考到u盘,通过u盘考到智龙主板上,远程链接智龙并进入智龙的linux系统,输入./button92_mips运行该可执行文件,可以看到程序在不断地打印按钮的状态,我们按下智龙主板上的按键,就会看到按钮的状态会在1、0之间变化,说明程序成功了。

内核模块编程:

参考:

  1. 【Linux】【Kernel】一个简单的内核模块例子
  2. 编写一个简单的内核模块程序Hello World!
  3. Linux GPIO用户空间操作
  4. Linux GPIO 使用示例(带中断、内核模块编程、用户态编程)
  5. 【龙印】龙芯1c的gpio输出高低电平的linux驱动(自定义内核驱动、安装、与用户态编程)
  6. 勤为本的封装代码系列:A、【龙芯1c库】封装gpio接口和使用示例;B、【龙芯1c库】封装硬件I2C接口和使用示例
05-14 19:02