linux提供了一系列的函数来操作GPIO,看下面的代码:
int io_out, in_in; //定义一个输出IO和一个输入IO
io_out = GPIO_TO_PIN(1, 16);
io_in = GPIO_TO_PIN(1, 17);
gpio_request(io_out, "gpio_out"); //申请IO
gpio_request(io_in, "gpio_in");
gpio_direction_output(io_out, 1); //设置IO为输出,上拉
gpio_direction_input(io_in); //设置IO为输入
gpio_set_value(io_out, 0); //设置IO的输出为低
gpio_get_value(io_in); //读取IO的值
gpio_export(io_out, 1); //导出IO到用户空间
gpio_export(io_in, 0);
gpio_export函数的第二个参数表示用户是否可以改变IO的输入输出方向。
使用gpio_export导出到用户空间后,在/sys/class/gpio/gpio16 和/sys/class/gpio/gpio17提供了访问他们的操作。
例如echo 1 > /sys/class/gpio/gpio16/value即是写入1。
在用户层也可以导出IO,使用echo 18 > /sys/class/gpio/export即导出IO18到用户空间,再使用 echo in > /sys/class/gpio/gpio18即设置gpio18为输入io,设置输出io调用“echo out。/sys/class/gpio/unexport的操作与export相反,即取消导出的IO。
gpio的源码在drivers/gpio/Gpiolib.c中,与芯片有关的结构是struct gpio_chip。
用户层也可以将IO配置为中断,即设置/sys/class/gpio/gpioN/edge:
none表示引脚为输入,不是中断引脚
rising表示引脚为中断输入,上升沿触发
falling表示引脚为中断输入,下降沿触发
both表示引脚为中断输入,边沿触发
首先需要将该gpio配置为中断
echo "rising" > /sys/class/gpio/gpio12/edge
以下是伪代码
int gpio_id;
struct pollfd fds[1];
gpio_fd = open("/sys/class/gpio/gpio12/value",O_RDONLY);
if( gpio_fd == -1 )
err_print("gpio open");
fds[0].fd = gpio_fd;
fds[0].events = POLLPRI;
ret = read(gpio_fd,buff,10);
if( ret == -1 )
err_print("read");
while(1){
ret = poll(fds,1,-1);
if( ret == -1 )
err_print("poll");
if( fds[0].revents & POLLPRI){
ret = lseek(gpio_fd,0,SEEK_SET);
if( ret == -1 )
err_print("lseek");
ret = read(gpio_fd,buff,10);
if( ret == -1 )
err_print("read");
/*此时表示已经监听到中断触发了,该干事了*/
...............
}
}
记住使用poll()函数,设置事件监听类型为POLLPRI和POLLERR在poll()返回后,使用lseek()移动到文件开头读取新的值或者关闭它再重新打开读取新值。必须这样做否则poll函数会总是返回。