类似树莓派、龙芯智龙这类mini开发板上的Linux系统,一般都提供了类似Arduino操作引脚电路、探测的功能,统称GPIO接口(General-purpose input/output,通用目的输入输出),但是使用上却涉及稍复杂的Linux内核概念。不同于Arduino,直接将物理硬件暴露给用户进行编程和操作,Linux系统必须通过一个叫“驱动”的程序将物理硬件进行封装,然后把其包装好的接口按照linux文件系统的方式提供给用户进行操作,用户操作硬件的时候必须通过这个文件系统进行输入输出,也就是所谓的“用户态编程”。总结起来就是3种方式:
- 内核编程,将源代码跟linux源码放在一起编译,将编译好的操作系统安装到目标机子(开发板)上
- 内核模块编程,编译成.ko文件,通过安装驱动的方式把编译好的文件放在系统内核中
- 用户态编程,编译成普通可执行文件,通过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之间变化,说明程序成功了。
内核模块编程:
参考:
- 【Linux】【Kernel】一个简单的内核模块例子
- 编写一个简单的内核模块程序Hello World!
- Linux GPIO用户空间操作
- Linux GPIO 使用示例(带中断、内核模块编程、用户态编程)
- 【龙印】龙芯1c的gpio输出高低电平的linux驱动(自定义内核驱动、安装、与用户态编程)
- 勤为本的封装代码系列:A、【龙芯1c库】封装gpio接口和使用示例;B、【龙芯1c库】封装硬件I2C接口和使用示例;