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函数会总是返回。