前提:
硬件支持GPIO的上拉下拉输出和输出,kernel的设备树中没有对管脚多余的控制。管脚的电压由硬件控制,arm只有控制电压的高或低,输入和输出。
原理:
Linux对于底层kernel的GPIO口调用,都是对/sys/class/gpio节点的操作和访问。在Linux指令下,一般用echo和cat进行修改和读取状态。以PE19进行举例//pe19(32*4+19 = 147)
1.注册PE19:echo 147 > /sys/class/gpio/export
2.注销PE19:echo 147 > /sys/class/gpio/unexport
3.将PE19改为输出:echo out > /sys/class/gpio/gpio147/directoin
4.将PE19改为输入:echo in > /sys/class/gpio/gpio147/directoin
5.将PE19输出电压拉低echo 0 > /sys/class/gpio/gpio147/value
6.将PE19输出电压拉高echo 1 > /sys/class/gpio/gpio147/value
代码的实现:
devgpio.h程序:
#ifndef DEV_GPIO
#define DEV_GPIO
#ifdef __cplusplus
extern "C" {
#endif
const char* const SYS_GPIO_PATH = "/sys/class/gpio";
const short GPIO_BUF = 64;
/*
//pe19(32*4+19 = 147)
echo 147 > /sys/class/gpio/export
echo 147 > /sys/class/gpio/unexport
echo out > /sys/class/gpio/gpio147/directoin
echo in > /sys/class/gpio/gpio147/directoin
echo 0 > /sys/class/gpio/gpio147/value
echo 1 > /sys/class/gpio/gpio147/value
*/
/** ExportGpioToUserSpace \功能 注册引脚
*
* \参数 [输入] gpio 引脚号
*
* \返回值 0 成功
* -1 失败
*
*/
int ExportGpioToUserSpace(int gpio);
/** UnexportFromUserSpace \功能 注销引脚
*
* \参数 [输入] gpio 引脚号
*
* \返回值 0 成功
* -1 失败
*
*/
int UnexportFromUserSpace(int gpio);
/** SetGPIODirection \功能 设置引脚方向
*
* \参数 [输入] gpio 引脚号
* \参数 [输入] dir 引脚方向 0:输入 1:输出
*
* \返回值 0 成功
* -1 失败
*
*/
int SetGPIODirection(int gpio, int dir);
/** SetGpioValue \功能 设置引脚值
*
* \参数 [输入] gpio 引脚号
* \参数 [输入] value 引脚值
*
* \返回值 0 成功
* -1 失败
*
*/
int SetGpioValue(int gpio, int value);
/** GetGpioValue \功能 获取引脚值
*
* \参数 [输入] gpio 引脚号
* \参数 [输入/输出] value 输入:缓冲区,输出:引脚值
*
* \返回值 0 成功
* -1 失败
*
*/
int GetGpioValue(int gpio, int *value);
#ifdef __cplusplus
}
#endif
#endif /* __DEV_GPIO__ */
devgpio.cpp程序:
/* 包含的头文件 */
#include <stdio.h> //标准输入输出,如printf、scanf以及文件操作
#include <stdlib.h> //标准库头文件,定义了五种类型、一些宏和通用工具函数
#include <unistd.h> //定义 read write close lseek 等Unix标准函数
#include <sys/types.h> //定义数据类型,如 ssiz e_t off_t 等
#include <sys/stat.h> //文件状态
#include <fcntl.h> //文件控制定义
#include <termios.h> //终端I/O
#include <errno.h> //与全局变量 errno 相关的定义
#include <getopt.h> //处理命令行参数
#include <string.h> //字符串操作
#include <time.h> //时间
#include <sys/select.h> //select函数
#include "devgpio.h"
/*
将GPIO 导入到用户空间 Export GPIO to User Space
*/
int ExportGpioToUserSpace(int gpio)
{
int ret = -1;
int fd;
int len;
char value[GPIO_BUF];
char export_name[GPIO_BUF];
char gpio_name[GPIO_BUF];
printf("gpio: %d",gpio);
sprintf(export_name,"%s/export",SYS_GPIO_PATH);
puts(export_name);
fd = open(export_name,O_WRONLY);
if(fd < 0){
printf("open gpio export err!");
return -1;
}
sprintf(gpio_name,"%s/gpio%d",SYS_GPIO_PATH,gpio);
if(!access(gpio_name,0)){
return -1;
}
len = snprintf(value,sizeof(value),"%d",gpio);
ret = write(fd,value,len);
if(ret < 0){
printf("export write err!");
return -1;
}
close(fd);
return 0;
}
int UnexportFromUserSpace(int gpio)
{
int ret;
int fd;
int len;
char value[GPIO_BUF];
char unexport_name[GPIO_BUF];
sprintf(unexport_name,"%s/unexport",SYS_GPIO_PATH);
puts(unexport_name);
fd = open(unexport_name,O_WRONLY);
if(fd < 0){
printf("open unexport gpio err!");
return -1;
}
len = snprintf(value,sizeof(value),"%d",gpio);
ret = write(fd,value,len);
if(ret < 0){
printf("unexport write err!");
return -1;
}
fsync(fd);
close(fd);
return 0;
}
int SetGPIODirection(int gpio, int dir)
{
int ret = -1;
int fd;
char direction_name[GPIO_BUF];
snprintf(direction_name,sizeof(direction_name),"%s/gpio%d/direction",SYS_GPIO_PATH,gpio);
puts(direction_name);
fd = open(direction_name,O_WRONLY);
if(fd < 0){
printf("open gpio dir err!");
return -1;
}
if(dir){
ret = write(fd,"out",4);
}else{
ret = write(fd,"in",3);
}
if(ret < 0){
printf("SetGPIODirection write err!");
return -1;
}
close(fd);
return 0;
}
int SetGpioValue(int gpio, int value)
{
int ret = -1;
int fd;
char value_name[GPIO_BUF];
snprintf(value_name,sizeof(value_name),"%s/gpio%d/value",SYS_GPIO_PATH,gpio);
puts(value_name);
fd = open(value_name,O_WRONLY);
if(fd < 0){
printf("open gpio value err!");
return -1;
}
if(value){
ret = write(fd,"1",2);
}else{
ret = write(fd,"0",2);
}
if(ret < 0){
printf("SetGpioValue write err!");
return -1;
}
close(fd);
return 0;
}
/*
int *value : 存储返回的值
*/
int GetGpioValue(int gpio, int *value)
{
int ret = -1;
int fd;
char dat;
char value_name[GPIO_BUF];
sprintf(value_name,"%s/gpio%d/value", SYS_GPIO_PATH, gpio);
puts(value_name);
fd = open(value_name,O_RDONLY);
if(fd < 0){
printf("open gpio value err!");
return -1;
}
ret = read(fd,&dat,1);
if(ret < 0){
printf("GetGpioValue write err!");
return -1;
}
if(dat != '0'){
*value = 1;
}else{
*value = 0;
}
close(fd);
return 0;
}