/**
* @author emlsyx
* @email yangx_1118@163.com
* @create date 2020-02-19 19:11:53
* @modify date 2020-02-19 19:11:53
* @desc [description]*/#include#include#include#include#include#include
#define err_out(fmt, ...) \
do\
{ \
printf(fmt, ##__VA_ARGS__); \
printf(" \"%s()\" %d error\n", __FILE__, __FUNCTION__, __LINE__); \
}while (0)#define open_gpio_file(path, flag, fd) \
do\
{ \
fd=open(path, flag); \if (fd < 0) \
{ \
err_out("\"%s\" open failed \n", path); \return (-1); \
} \
}while (0);/**
* @brief : gpio 导出
* @param : pin
* @retval: 0 成功; -1失败*/
static int gpio_export(const intpin)
{intfd, len;char buffer[64];char path[64];
sprintf(&path[0], "/sys/class/gpio/gpio%d", pin);/*文件不存在时,导出gpio*/
if (access(path, F_OK) != 0)
{
memset(path,0, 64);
sprintf(&path[0], "/sys/class/gpio/export");
open_gpio_file(path, O_WRONLY, fd);
len= snprintf(buffer, sizeof(buffer), "%d", pin);if (write(fd, buffer, len) < 0)
{
err_out("write failed to export gpio!\n");return -1;
}
close(fd);
}return 0;
}/**
* @brief : gpio 卸载
* @param : pin
* @retval: 0 成功; -1失败*/
static int gpio_unexport(const intpin)
{intfd, len;char buffer[64];char path[64];
sprintf(&path[0], "/sys/class/gpio/gpio%d", pin);/*文件存在时,卸载gpio*/
if (access(path, F_OK) == 0)
{
memset(path,0, 64);
sprintf(&path[0], "/sys/class/gpio/unexport");
open_gpio_file(path, O_WRONLY, fd);
len= snprintf(buffer, sizeof(buffer), "%d", pin);if (write(fd, buffer, len) < 0)
{
err_out("write failed to unexport gpio!\n");return -1;
}
close(fd);
}return 0;
}/**
* @brief : gpio 方向控制
* @param : dir 方向(in/out)
* @retval: 0 成功; -1失败*/
static int gpio_direction(const int pin, const char *dir)
{intfd;char path[64];int w_len = ((dir[0] == 'i') && (dir[1] == 'n')) ? 2 : 3;
snprintf(path,sizeof(path), "/sys/class/gpio/gpio%d/direction", pin);
open_gpio_file(path, O_WRONLY, fd);if (write(fd, dir, w_len) < 0)
{
err_out("Failed to set direction!\n");return -1;
}
close(fd);return 0;
}/**
* @brief : gpio 写
* @param : 0 / 1
* @retval: 0 成功; -1失败*/
static int gpio_write(const int pin, const intvalue)
{intfd;char path[64];const char *val[] = {"0", "1"};
snprintf(path,sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
open_gpio_file(path, O_WRONLY, fd);if (write(fd, val[value], 1) < 0)
{
err_out("Failed to write value!\n");return -1;
}
close(fd);return 0;
}/**
* @brief : gpio 读
* @param : 读取的引脚值
* @retval: 返回引脚的值 0 / 1*/
static int gpio_read(const intpin)
{intfd;char path[64];char value_str[3];
snprintf(path,sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
open_gpio_file(path, O_RDONLY, fd);if (read(fd, value_str, 3) < 0)
{
err_out("Failed to read value!\n");return -1;
}
close(fd);return(atoi(value_str));
}/**
* @brief : gpio 中断控制
* @param : 0 none 表示引脚为输入,不是中断引脚
* @arg : 1 rising 表示引脚为中断输入,上升沿触发
* @arg : 2 falling 表示引脚为中断输入,下降沿触发
* @arg : 3 both 表示引脚为中断输入,边沿触发
* @retval:*/
static int gpio_edge(const int pin, intedge)
{intfd;char path[64];const char *dir_str[] = {"none", "rising", "falling", "both"};if (edge > 3)
{
err_out("Failed edge parameter error\n");return -1;
}
snprintf(path,sizeof(path), "/sys/class/gpio/gpio%d/edge", pin);
open_gpio_file(path, O_WRONLY, fd);if (write(fd, dir_str[edge], strlen(dir_str[edge])) < 0)
{
err_out("Failed to set edge!\n");return -1;
}
close(fd);return 0;
}intmain()
{char buff[10], res;intled_fd, key_fd;structpollfd fds;/*按键led指示灯*/gpio_export(55);
gpio_direction(55, "out");
gpio_write(55, 0);/*按键引脚初始化*/gpio_export(70);
gpio_direction(70, "in");
gpio_edge(70, 2);
open_gpio_file("/sys/class/gpio/gpio70/value", O_RDONLY, key_fd);/*poll 操作的文件符号*/fds.fd=key_fd;/*经测试io中断产生后,正常会发送POLLPRI 这个中断,循环中必须等待这个事件*/fds.events= POLLPRI |POLLERR;/*真实发生的事件*/fds.revents= 0;while (1)
{int ret = poll(&fds, 1, -1);if (!ret)
{
err_out("poll time out\n");
}else{if (fds.revents &POLLPRI)
{
gpio_write(55, gpio_read(55) ? 0 : 1);
res= lseek(fds.fd, 0, SEEK_SET); /*读取按键值*/
if (res == -1)
{
printf("lseek failed!\n");return -1;
}
res= read(fds.fd, buff, sizeof(buff));if (res == -1)
{
perror("read failed!\n");return -1;
}
printf("fds.revents %d key value %s \n", fds.revents, buff);
}
}
}return 0;
}