linux下i386平台gpio端口操作

linu系统下,在i386平台上操作gpio端口其实很简单,可分为两种:用户层操作和驱动层操作(即编写gpio驱动)。

一、用户层操作gpio端口

可分两种方法:

1、一般方法:关键调用ioperm()函数来获取端口号的操作权限,然后调用inb()、outb()、inw()、outw()等端口操作函数来直接操作端口地址,参考链接:

http://wenku.baidu.com/view/7ddaae02de80d4d8d15a4f8f.html

下面是我写的一个简单例子:

gpio_writ.c

include <stdio.h>#include <sys/io.h>#include <unistd.h>int main(){        /*向系统申请0x000~0x3FF的地址空间控制权*/        ioperm(0x000,0x8FF,1); //0x000是开始地址,0x8FF是结束地址,因为我的gpio端口地址是0x84D,在其范围之内/*向0x84D地址bit0写入全1*/        int i=0;        for(i;i<10;i++)        {                outb(0x40,0x84D);//向0x84D地址bit0写入全1,将电平拉高                sleep(1);                outb(0x00,0x84D);//向0x84D地址bit0写入全0,将电平拉低                sleep(1);        }        /*向系统交回0x000~0x3FF的地址空间控制权*/        ioperm(0x000,0x8FF,0);        return 0;}

2、采用文件操作的方法

gpio设备文件 控制读代码:

#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <sys/select.h>int main(){int fd = -1;fd = open("/dev/port",O_RDWR);if(-1 == fd){perror("open port");exit(EXIT_FAILURE);}fd_set readfd;struct timeval tv;int retval = -1;unsigned char readData;int i = 0;for(i;i<300;i++){FD_ZERO(&readfd);FD_SET(fd,&readfd);if(-1 == lseek(fd,0x84E,SEEK_SET)){perror("lseek");exit(EXIT_FAILURE);}tv.tv_sec = 1;tv.tv_usec = 0;retval = select(fd+1,&readfd,NULL,NULL,&tv);if(-1 == retval){perror("select");exit(EXIT_FAILURE);}else if(0 == retval){continue;}else{if(FD_ISSET(fd, &readfd)){if(-1 == read(fd,&readData,1)){perror("read");exit(EXIT_FAILURE);}if(readData & 0x40)printf("The bit6 is high!\n");elseprintf("The bit6 is low!\n");}}}close(fd);return 0;}

GPIO设备文件控制写 代码:

#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>int main(){int fd = -1;fd = open("/dev/port",O_RDWR);if(-1 == fd){perror("open port");exit -1;}unsigned char writeHighData = 0x40;unsigned char writeLowData = 0x0;int i = 0;for(i;i<100;i++){if(-1 == lseek(fd,0x84D,SEEK_SET)){perror("lseek");exit -1;}if(-1 == write(fd,&writeHighData,1)){perror("write");exit -1;}sleep(1);if(-1 == lseek(fd,0x84D,SEEK_SET)){perror("lseek");exit -1;}if(-1 == write(fd,&writeLowData,1)){perror("write");exit -1;}sleep(1);}close(fd);return 0;}

二、gpio端口驱动

gpio的端口驱动也很简答,大概流程就是:

申请端口号——> 操作端口———>释放端口号

下面我写一个例子供参考:

#include <linux/module.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/types.h>#include <asm/io.h>#include <linux/kdev_t.h>#include <linux/fs.h>#define DEV_NAME "mygpio"static int myIoOperation(void){unsigned char ioData = '0';if(!request_region(0x84D,10,DEV_NAME)){printk(KERN_ERR "myIoOperation error:request_region\n ");return -1  ;}ioData = inb(0x84D);ioData |= 0x40;outb(ioData,0x84D);return 0;}static void  myIoRelease(void){unsigned char ioData = inb(0x84D);ioData  &= 0xbf;outb(ioData,0x84D);release_region(0x84D,10);}int mygpio_init(void){    //ÉêÇë¶Ë¿ÚºÅ£¬²¢ÇÒÀ­?ßbit0    if(-1 == myIoOperation())    {printk(KERN_ERR "myIoOpration fail!\n");return -1;    }    return 0;/*init succeed*/}void mygpio_exit(void){   //    myIoRelease();}MODULE_LICENSE("Dual BSD/GPL");module_init(mygpio_init);module_exit(mygpio_exit);

gpio.c驱动程序编写完成之后,再编写Makefile

Makefile:

KVERS = /home/wxf/sourceCode/linux-2.6.39#kernel modulesobj-m += gpio.obuild:        make -C $(KVERS) M=$(PWD) modulesclean:        make -C $(KVERS) M=$(PWD) clean

之后执行make,生成gpio.ko驱动模块,就是加载驱动模块了:

insmod gpio.ko

如果驱动加载成功,则gpio的第一个引脚被拉高;

卸载驱动:

rmmod gpio

卸载成功后,gpio的的第一个引脚被拉低。

此时一个简单的gpio驱动就完成了。

有些人注定是等待别人的,有些人是注定被人等的。

linux下i386平台gpio端口操作

相关文章:

你感兴趣的文章:

标签云: