本帖最后由 wateras1 于 2018-4-16 13:42 编辑
mtk7688 之openwr下的gpio应用编程
在上一篇我是在终端中通过读写文件实现了对GPIO的操作(
https://bbs.eeworld.com.cn/thread-641726-1-1.html), 这篇主要是对上一篇的应用程序编写,通过读写文件来实现相关功能,相关代码如下:
#ifndef __GPIO_H__
#define __GPIO_H__
#ifdef __cplusplus
extern "C" {
#endif
/* GPIO value */
#define GPIO_HIGH 1
#define GPIO_LOW 0
/* GPIO direction code */
#define GPIO_INPUT 0
#define GPIO_OUTPUT 1
#define GPIO_OUTPUT_HIGH 2
#define GPIO_OUTPUT_LOW 3
/* GPIO error code */
#define GPIO_SUCCESS 1
#define GPIO_INVALID_RESOURCE -1
#define GPIO_ERROR_READ -2
#define GPIO_ERROR_WRITE -3
#define GPIO_ERROR_DIRECTION -4
/**
* Read specified GPIO pin
*
* @param pin_number specified the pin
*
*
@return integer value of GPIO if success.
* return negative integer error code if fail.
*/
int gpio_read(int pin_number);
/**
* Write specified GPIO pin
*
* @param pin_number specified the pin
*
* @param value could be GPIO_HIGH or GPIO_LOW
*
* @return 1 if success.
* return negative integer error code if fail.
*/
int gpio_write(int pin_number, int value);
/**
* set direction of specified GPIO pin
*
* @param pin_number specified the pin
*
* @param direction could be GPIO_IN or GPIO_OUT, GPIO_OUT_HIGH, GPIO_OUT_LOW
*
* @return 1 if success.
* return negative integer error code if fail.
*/
int gpio_set_direction(int pin_number, int direction);
/**
* get direction of specified GPIO pin
*
* @param pin_number specified the pin
*
* @return positive integer direction code if success.
* return negative integer error code if fail.
*/
int gpio_get_direction(int pin_number);
/**
* export specified GPIO pin
*
* @param pin_number specified the pin
*
* @return 1 if success.
* return negative integer error code if fail.
*/
int gpio_export(int pin_number);
/**
* unexport specified GPIO pin
*
* @param pin_number specified the pin
*
* @return 1 if success.
* return negative integer error code if fail.
*/
int gpio_unexport(int pin_number);
/**
* Return 1 if specified GPIO pin is exported
*
* @param pin_number specified the pin
*
* @return 1 if GPIO pin is exported.
* return 0 if GPIO pin is not exported
*/
int gpio_is_exported(int pin_number);
#ifdef __cplusplus
}
#endif
#include
#include
#include
#include
#include
#include
#include
#include "gpio.h"
#define FILENAME_SIZE 128
#define GPIO_PATH "/sys/class/gpio"
/**
* Export specified GPIO pin
*
* @param pin_number specified the pin
*
* @return 1 if success.
* return negative integer error code if fail.
*/
int gpio_export(int pin_number) {
char buf[FILENAME_SIZE];
int fp;
int length;
if ( gpio_is_exported(pin_number) )
return GPIO_SUCCESS;
//write to export file
fp = open(GPIO_PATH "/export", O_WRONLY);
if ( fp == -1) {
return GPIO_INVALID_RESOURCE;
}
length = snprintf(buf, sizeof(buf), "%d", pin_number);
if (write(fp, buf, length * sizeof(char)) == -1) {
close(fp);
return GPIO_INVALID_RESOURCE;
}
close(fp);
return gpio_is_exported(pin_number);
}
/**
* Return 1 if specified GPIO pin is exported
*
* @param pin_number specified the pin
*
* @return 1 if GPIO pin is exported.
* return 0 if GPIO pin is not exported
*/
int gpio_is_exported(int pin_number) {
char buf[FILENAME_SIZE];
struct stat dir;
//check if the gpioXX directory exists
snprintf(buf, sizeof(buf), GPIO_PATH "/gpio%d/", pin_number);
if (stat(buf, &dir) == 0 && S_ISDIR(dir.st_mode)) {
return GPIO_SUCCESS;
} else {
return 0;
}
}
/**
* unexport specified GPIO pin
*
* @param pin_number specified the pin
*
* @return 1 if success.
* return negative integer error code if fail.
*/
int gpio_unexport(int pin_number) {
char buf[FILENAME_SIZE];
int fp;
int length;
//write to unexport file
fp = open(GPIO_PATH "/unexport", O_WRONLY);
if ( fp == -1) {
return GPIO_INVALID_RESOURCE;
}
length = snprintf(buf, sizeof(buf), "%d", pin_number);
if (write(fp, buf, length * sizeof(char)) == -1) {
close(fp);
return GPIO_INVALID_RESOURCE;
}
close(fp);
return GPIO_SUCCESS;
}
/**
* Read specified GPIO pin
*
* @param pin_number specified the pin
*
* @return integer value of GPIO if success.
* return negative integer error code if fail.
*/
int gpio_read(int pin_number) {
char buf[FILENAME_SIZE];
int fp;
if ( !gpio_is_exported(pin_number) ) {
if ( 1 != gpio_export(pin_number) )
return GPIO_INVALID_RESOURCE;
}
//read value file
snprintf(buf, sizeof(buf), "%s/gpio%d/value", GPIO_PATH, pin_number);
fp = open(buf, O_RDWR);
if ( fp == -1) {
return GPIO_INVALID_RESOURCE;
}
if ( lseek(fp, 0, SEEK_SET) < 0 ) {
close(fp);
}
if (read(fp, buf, 2 * sizeof(char)) != 2) {
close(fp);
return GPIO_ERROR_READ;
}
close(fp);
return (int) strtol(buf, NULL, 10);
}
/**
* Write specified GPIO pin
*
* @param pin_number specified the pin
*
* @param value could be GPIO_HIGH or GPIO_LOW
*
* @return 1 if success.
* return negative integer error code if fail.
*/
int gpio_write(int pin_number, int value) {
char buf[FILENAME_SIZE];
int fp;
int length;
if ( !gpio_is_exported(pin_number) ) {
if ( 1 != gpio_export(pin_number) )
return GPIO_INVALID_RESOURCE;
}
//write to value file
snprintf(buf, sizeof(buf), "%s/gpio%d/value", GPIO_PATH, pin_number);
fp = open(buf, O_RDWR);
if ( fp == -1) {
return GPIO_INVALID_RESOURCE;
}
if ( lseek(fp, 0, SEEK_SET) < 0 ) {
close(fp);
}
length = snprintf(buf, sizeof(buf), "%d", value);
if ( write(fp, buf, length * sizeof(char)) == -1) {
close(fp);
return GPIO_ERROR_WRITE;
}
close(fp);
return GPIO_SUCCESS;
}
/**
* set direction of specified GPIO pin
*
* @param pin_number specified the pin
*
* @param direction could be GPIO_INPUT or GPIO_OUTPUT, GPIO_OUTPUT_HIGH, GPIO_OUTPUT_LOW
*
* @return 1 if success.
* return negative integer error code if fail.
*/
int gpio_set_direction(int pin_number, int direction) {
char buf[FILENAME_SIZE];
int fp;
int length;
if ( !gpio_is_exported(pin_number) ) {
if ( 1 != gpio_export(pin_number) )
return GPIO_INVALID_RESOURCE;
}
//write direction file
snprintf(buf, sizeof(buf), "%s/gpio%d/direction", GPIO_PATH, pin_number);
fp = open(buf, O_RDWR);
if ( fp == -1) {
return GPIO_INVALID_RESOURCE;
}
if ( lseek(fp, 0, SEEK_SET) < 0 ) {
close(fp);
return GPIO_INVALID_RESOURCE;
}
switch (direction) {
case GPIO_OUTPUT:
length = snprintf(buf, sizeof(buf), "out");
break;
case GPIO_INPUT:
length = snprintf(buf, sizeof(buf), "in");
break;
case GPIO_OUTPUT_HIGH:
length = snprintf(buf, sizeof(buf), "high");
break;
case GPIO_OUTPUT_LOW:
length = snprintf(buf, sizeof(buf), "low");
break;
default:
close(fp);
return GPIO_ERROR_DIRECTION;
}
if (write(fp, buf, length * sizeof(char)) == -1) {
close(fp);
return GPIO_ERROR_WRITE;
}
close(fp);
return GPIO_SUCCESS;
}
/**
* get direction of specified GPIO pin
*
* @param pin_number specified the pin
*
* @return positive integer direction code if success.
* return negative integer error code if fail.
*/
int gpio_get_direction(int pin_number) {
char buf[FILENAME_SIZE];
int fp;
int length;
int result;
if ( !gpio_is_exported(pin_number) ) {
if ( 1 != gpio_export(pin_number) )
return GPIO_INVALID_RESOURCE;
}
//read direction file
snprintf(buf, sizeof(buf), "%s/gpio%d/direction", GPIO_PATH, pin_number);
fp = open(buf, O_RDONLY);
if ( fp == -1) {
return GPIO_INVALID_RESOURCE;
}
if ( lseek(fp, 0, SEEK_SET) < 0 ) {
close(fp);
return GPIO_INVALID_RESOURCE;
}
memset(buf, '\0', sizeof(buf));
length = read(fp, buf, sizeof(buf));
close(fp);
if (length <= 0) {
return GPIO_INVALID_RESOURCE;
}
if (strncmp(buf, "out", 3) == 0) {
result = GPIO_OUTPUT;
} else if (strncmp(buf, "in", 2) == 0) {
result = GPIO_INPUT;
} else if (strncmp(buf, "high", 4) == 0) {
result = GPIO_OUTPUT_HIGH;
} else if (strncmp(buf, "low", 3) == 0) {
result = GPIO_OUTPUT_LOW;
} else {
result = GPIO_ERROR_DIRECTION;
}
return result;
}
#include "gpio.h"
#include
#include
void blink(int pin) {
printf("blink GPIO %d for 100 times\n", pin);
fflush(stdout);
if ( 1 == gpio_export(pin) ) {
if ( 1 == gpio_set_direction(pin, GPIO_OUTPUT) ) {
//blink
int value = GPIO_HIGH;
int i;
for ( i = 0; i < 100; i++ ) {
printf("blink %d\n", i);
value = (value == GPIO_HIGH) ? GPIO_LOW : GPIO_HIGH;
gpio_write( pin, value );
sleep(1);
}
}
}
}
int main() {
blink(11); //blink on gpio11
}
这个GPIO封装的还是不错,对于已经集成了相关GPIO驱动的功能的openwrt来说,还是很方便的,这个主要涉及linux的应用开发,没有涉及到具体的GPIO的驱动+GPIO的应用开发,灵活性感觉还是很一般,接下来我就完整的围绕openwrt系统来实现一个GPIO的闪烁的功能,
主要涉及到GPIO的驱动的编写以及内核加载,GPIO应用开发的编写以及opkg的安装。
此内容由EEWORLD论坛网友wateras1原创,如需转载或用于商业用途需征得作者同意并注明出处