菜鸟求教读取GPIO的状态的方法

时间:2021-05-11 17:50:41
刚接触驱动这一块,想做一个LED控制读取的驱动。 先设置成OUTPUT状态,用IOCTL函数输入0或者1,控制LED灯亮或者灭,然后换成INPUT状态,用read函数读出GPIO的值。正常应该是给我返回0或者1,但我在应用里读的值是错误的
驱动里的read代码如下:
static ssize_t s3c2440_IO_read(struct file *filp, char *buf, size_t len)
{
char ret;
s3c2410_gpio_cfgpin(GPG0_PIN, GPG0_PIN_INPUT);
          ret = s3c2410_gpio_getpin(GPG0_PIN);
 copy_to_user(buf,&ret,1);
return 1;
}
应用层代码
       int main(void)
{
   int fd;
   int i = 0 ;
   char buf[]={'\n'};
   fd = open("/dev/led_test",O_RDWR|O_NOCTTY|O_NDELAY);
   if(fd == -1)
   {
perror("open failed\n");
return -1;
   }
   while(1)
   {
   ioctl(fd,1,1);
   read(fd,buf,1);
   printf("buf = %d\n",buf);
   sleep(3);
   ioctl(fd,0,1);
   sleep(3);
   read(fd,buf,1);
   printf("buf = %d\n",buf);
   }
   close(fd);
   return 0;


}

求大神指教,怎么才能在应用层read出0或者1。

10 个解决方案

#1


我是第一次发帖·求大神指教

#2


几个小问题:
1、 先设置成OUTPUT状态,用IOCTL函数输入0或者1,控制LED灯亮或者灭,然后换成INPUT状态 
 这个搞反了没哦....

2、你是不是已经可以控制亮/灭了? 那说明你GPIO_PIN那些都是正确的, 这样的话, read应该也不会错。  你在驱动里, read后面直接打印那个ret, 确保在驱动里就读对了。

#3


现在改动了一下read代码:
char Iolavel;
// s3c2410_gpio_cfgpin(GPG0_PIN, GPG0_PIN_INPUT);
Iolavel = s3c2410_gpio_getpin(GPG0_PIN);
ndelay(20);
printk("Iolavel3 %d\r\n",Iolavel);
copy_to_user(buf,&Iolavel,sizeof(Iolavel));
read里面的Iolavel是对的,在应用层
int main(void)
{
   int fd;
   int i = 0 ;
   char buf1[32]={0};
   char buf;
  // unsigned long buf1;
   fd = open("/dev/led_test",O_RDWR|O_NOCTTY|O_NDELAY);
   if(fd == -1)
   {
perror("open failed\n");
return -1;
   }
   while(1)
   {
   ioctl(fd,1,1);
   buf = read(fd,buf1,1);
   sleep(3);
  // buf1 = strtoul(buf,'\0',16);
   printf("buf1 = %d\n",buf);
   sleep(3);
   printf("hello led\n");
   ioctl(fd,0,1);
   sleep(3);
   buf = read(fd,buf1,1);
 //  buf1 = strtoul(buf,'\0',16);
   sleep(3);
   printf("buf2 = %d\n",buf);
   }
   close(fd);
   return 0;


}
现在读取出来的不管高电平还是低电平输出的全是1.求大神帮我看看是哪里出问题了。

#4


刚把代码改动了一下,操作具体的寄存器了,但读出来的还是一直是1,
代码如下
驱动:
static unsigned long S3C2440_GPGDAT;
static int s3c2440_IO_SET(struct inode *inode,struct file *file, unsigned int cmd, unsigned long arg)
{
printk("GPG025 set %d\r\n",cmd);
switch(cmd)
{
   case 1:
*(unsigned long *)S3C2410_GPGDAT = 0xffff;
S3C2440_GPGDAT = *(unsigned long *)S3C2410_GPGDAT;
ndelay(30);
printk("S3C2440_GPGDAT1 %d\n",S3C2440_GPGDAT);
   break;
   case 0:
*(unsigned long *)S3C2410_GPGDAT = 0xfffe;
S3C2440_GPGDAT = *(unsigned long *)S3C2410_GPGDAT;
ndelay(30);
printk("S3C2440_GPGDAT2 %d\n",S3C2440_GPGDAT);
   break;
   default:
    return -1;
}
printk("Get62 GPG0 IO= %d\r\n",s3c2410_gpio_getpin(GPG0_PIN));
return 1;
}



static ssize_t s3c2440_IO_read(struct file *filp, char __user *buf, size_t len)
{


unsigned long  iolevel;
*(unsigned long *)S3C2410_GPGCON = 0x00000000;//config GPG(0)is input
iolevel = S3C2440_GPGDAT;//*(unsigned long *)S3C2410_GPGDAT;
printk("new iolevel4 = %d\r\n",iolevel);
ndelay(30);
//iolevel &=0x01;
//printk("new iolevel2 = %x\r\n",iolevel);
copy_to_user(buf,&iolevel,sizeof(unsigned long));
*(unsigned long *)S3C2410_GPGCON = 0x00000001;//config GPG(0)is output
return 1;
}

应用层代码
int main(void)
{
   int fd;
   int i = 0 ;
   unsigned long buf1;
   unsigned long buf;
  // unsigned long buf1;
   fd = open("/dev/led_test",O_RDWR|O_NOCTTY|O_NDELAY);
   if(fd == -1)
   {
perror("open failed\n");
return -1;
   }
   while(1)
   {
   ioctl(fd,1,1);
   buf = read(fd,buf1,sizeof(unsigned long));
   sleep(3);
  // buf1 = strtoul(buf,'\0',16);
   printf("buf1 = %d\n",buf);
   sleep(3);
   printf("hello led\n");
   ioctl(fd,0,1);
   sleep(3);
   buf = read(fd,buf1,sizeof(unsigned long));
 //  buf1 = strtoul(buf,'\0',16);
   sleep(3);
   printf("buf2 = %d\n",buf);
   }
   close(fd);
   return 0;
}
读出来的值buf一直都是1,buf1一直都是0,请大神搭救,帮我看看是哪里出问题了。

#5


建议阅读一下芯片厂商提提供的GPIO控制相关的文档。对照一下哪做的不太对。

或者,检查一下你板子的物理电路是不是对的。

#6


提醒你一个关键的地方,你的LED是不是外面接了上拉电阻,接了上拉的话……

#7


如果是在linux下面,直接是s3c2410_gpio_getpin(unsigned int pin) 返回状态!

#8


其他类似的还有:
s3c2410_gpio_setpin(unsigned int pin,unsigned int to)//设置状态
s3c2410_gpio_cfgpin(unsigned int pin,unsigned int cfg)//配置管脚为什么功能(输入,输出还是别的),你可以在同一个文件中找到它们

#9


不知道是楼主粗心,还是你的贴出来代码本身就这样。
1.首先,main当中read函数返回的不是buf值,它只是你读取到的字节数。
2.
static ssize_t s3c2440_IO_read(struct file *filp, char __user *buf, size_t len)
{
unsigned long  iolevel;
*(unsigned long *)S3C2410_GPGCON = 0x00000000;//config GPG(0)is input
iolevel = S3C2440_GPGDAT;//*(unsigned long *)S3C2410_GPGDAT;
printk("new iolevel4 = %d\r\n",iolevel);
ndelay(30);
//iolevel &=0x01;
//printk("new iolevel2 = %x\r\n",iolevel);
copy_to_user(buf,&iolevel,sizeof(unsigned long));
*(unsigned long *)S3C2410_GPGCON = 0x00000001;//config GPG(0)is output
return 1;  //你只返回了一个字节给main。
}
所以你的buf一直都是1,buf1是0是因为你要4个字节的长度,而内核只给了1个字节的,所以有可能是只拿到了高8位,这高8位在你的程序中永远都是0。

#10


该回复于2012-11-15 22:29:20被管理员删除

#1


我是第一次发帖·求大神指教

#2


几个小问题:
1、 先设置成OUTPUT状态,用IOCTL函数输入0或者1,控制LED灯亮或者灭,然后换成INPUT状态 
 这个搞反了没哦....

2、你是不是已经可以控制亮/灭了? 那说明你GPIO_PIN那些都是正确的, 这样的话, read应该也不会错。  你在驱动里, read后面直接打印那个ret, 确保在驱动里就读对了。

#3


现在改动了一下read代码:
char Iolavel;
// s3c2410_gpio_cfgpin(GPG0_PIN, GPG0_PIN_INPUT);
Iolavel = s3c2410_gpio_getpin(GPG0_PIN);
ndelay(20);
printk("Iolavel3 %d\r\n",Iolavel);
copy_to_user(buf,&Iolavel,sizeof(Iolavel));
read里面的Iolavel是对的,在应用层
int main(void)
{
   int fd;
   int i = 0 ;
   char buf1[32]={0};
   char buf;
  // unsigned long buf1;
   fd = open("/dev/led_test",O_RDWR|O_NOCTTY|O_NDELAY);
   if(fd == -1)
   {
perror("open failed\n");
return -1;
   }
   while(1)
   {
   ioctl(fd,1,1);
   buf = read(fd,buf1,1);
   sleep(3);
  // buf1 = strtoul(buf,'\0',16);
   printf("buf1 = %d\n",buf);
   sleep(3);
   printf("hello led\n");
   ioctl(fd,0,1);
   sleep(3);
   buf = read(fd,buf1,1);
 //  buf1 = strtoul(buf,'\0',16);
   sleep(3);
   printf("buf2 = %d\n",buf);
   }
   close(fd);
   return 0;


}
现在读取出来的不管高电平还是低电平输出的全是1.求大神帮我看看是哪里出问题了。

#4


刚把代码改动了一下,操作具体的寄存器了,但读出来的还是一直是1,
代码如下
驱动:
static unsigned long S3C2440_GPGDAT;
static int s3c2440_IO_SET(struct inode *inode,struct file *file, unsigned int cmd, unsigned long arg)
{
printk("GPG025 set %d\r\n",cmd);
switch(cmd)
{
   case 1:
*(unsigned long *)S3C2410_GPGDAT = 0xffff;
S3C2440_GPGDAT = *(unsigned long *)S3C2410_GPGDAT;
ndelay(30);
printk("S3C2440_GPGDAT1 %d\n",S3C2440_GPGDAT);
   break;
   case 0:
*(unsigned long *)S3C2410_GPGDAT = 0xfffe;
S3C2440_GPGDAT = *(unsigned long *)S3C2410_GPGDAT;
ndelay(30);
printk("S3C2440_GPGDAT2 %d\n",S3C2440_GPGDAT);
   break;
   default:
    return -1;
}
printk("Get62 GPG0 IO= %d\r\n",s3c2410_gpio_getpin(GPG0_PIN));
return 1;
}



static ssize_t s3c2440_IO_read(struct file *filp, char __user *buf, size_t len)
{


unsigned long  iolevel;
*(unsigned long *)S3C2410_GPGCON = 0x00000000;//config GPG(0)is input
iolevel = S3C2440_GPGDAT;//*(unsigned long *)S3C2410_GPGDAT;
printk("new iolevel4 = %d\r\n",iolevel);
ndelay(30);
//iolevel &=0x01;
//printk("new iolevel2 = %x\r\n",iolevel);
copy_to_user(buf,&iolevel,sizeof(unsigned long));
*(unsigned long *)S3C2410_GPGCON = 0x00000001;//config GPG(0)is output
return 1;
}

应用层代码
int main(void)
{
   int fd;
   int i = 0 ;
   unsigned long buf1;
   unsigned long buf;
  // unsigned long buf1;
   fd = open("/dev/led_test",O_RDWR|O_NOCTTY|O_NDELAY);
   if(fd == -1)
   {
perror("open failed\n");
return -1;
   }
   while(1)
   {
   ioctl(fd,1,1);
   buf = read(fd,buf1,sizeof(unsigned long));
   sleep(3);
  // buf1 = strtoul(buf,'\0',16);
   printf("buf1 = %d\n",buf);
   sleep(3);
   printf("hello led\n");
   ioctl(fd,0,1);
   sleep(3);
   buf = read(fd,buf1,sizeof(unsigned long));
 //  buf1 = strtoul(buf,'\0',16);
   sleep(3);
   printf("buf2 = %d\n",buf);
   }
   close(fd);
   return 0;
}
读出来的值buf一直都是1,buf1一直都是0,请大神搭救,帮我看看是哪里出问题了。

#5


建议阅读一下芯片厂商提提供的GPIO控制相关的文档。对照一下哪做的不太对。

或者,检查一下你板子的物理电路是不是对的。

#6


提醒你一个关键的地方,你的LED是不是外面接了上拉电阻,接了上拉的话……

#7


如果是在linux下面,直接是s3c2410_gpio_getpin(unsigned int pin) 返回状态!

#8


其他类似的还有:
s3c2410_gpio_setpin(unsigned int pin,unsigned int to)//设置状态
s3c2410_gpio_cfgpin(unsigned int pin,unsigned int cfg)//配置管脚为什么功能(输入,输出还是别的),你可以在同一个文件中找到它们

#9


不知道是楼主粗心,还是你的贴出来代码本身就这样。
1.首先,main当中read函数返回的不是buf值,它只是你读取到的字节数。
2.
static ssize_t s3c2440_IO_read(struct file *filp, char __user *buf, size_t len)
{
unsigned long  iolevel;
*(unsigned long *)S3C2410_GPGCON = 0x00000000;//config GPG(0)is input
iolevel = S3C2440_GPGDAT;//*(unsigned long *)S3C2410_GPGDAT;
printk("new iolevel4 = %d\r\n",iolevel);
ndelay(30);
//iolevel &=0x01;
//printk("new iolevel2 = %x\r\n",iolevel);
copy_to_user(buf,&iolevel,sizeof(unsigned long));
*(unsigned long *)S3C2410_GPGCON = 0x00000001;//config GPG(0)is output
return 1;  //你只返回了一个字节给main。
}
所以你的buf一直都是1,buf1是0是因为你要4个字节的长度,而内核只给了1个字节的,所以有可能是只拿到了高8位,这高8位在你的程序中永远都是0。

#10


该回复于2012-11-15 22:29:20被管理员删除