• 10927阅读
  • 16回复

【提问】怎样在QT程序中访问驱动文件 [复制链接]

上一主题 下一主题
离线jojo
 
只看楼主 倒序阅读 楼主  发表于: 2006-02-07
我写了一个在ARM上跑的QT程序,功能是把输入的数据写到板子上的内存中。现已有那块内存的驱动文件,里面定义了read和write两个函数,我想在程序中使用这两个函数,使它能够通过编译,请问怎么实现?谢谢!
我在widget类的一个自定义函数中使用这两个函数,编译时总说undeclare。
[ 此贴被XChinux在2006-02-07 15:52重新编辑 ]
离线alexzhao
只看该作者 1楼 发表于: 2006-02-10
内核态和用户态不一样吧,驱动程序都是跑在内核态的,你写的代码是在用户态的,linux c里面有专门处理这些问题的内容
离线jojo
只看该作者 2楼 发表于: 2006-02-10
感谢楼上,我知道怎么做了!
离线yypeony
只看该作者 3楼 发表于: 2006-02-11
我还是不明白怎么做的?
楼主能给讲讲吗
离线jojo
只看该作者 4楼 发表于: 2006-02-11
很抱歉,我现在还没有搞定,1楼兄弟提示的我试了,可还是undeclare。我目前在尝试用QT里的QFile类来做,虽然编译是过了,但程序一运行就死,驱动程序里写函数的一条printf提示不断地一行一行刷屏。我的感觉是已经访问驱动程序了,但就是写不进去。恳请有经验者指点一二,不胜感激!
离线yypeony
只看该作者 5楼 发表于: 2006-02-12
我也是用QFile类做的,编译通过了,能运行,但是写不进去,点击按钮时出现以下情况
QObject::connect: No such signal QComboBox::activated(const QString&string)
QObject::connect: (sender name:   'unnamed')
QObject::connect: (receiver name: 'unnamed')
离线jojo
只看该作者 6楼 发表于: 2006-02-13
直接用驱动程序中的函数是可行的,在引用read和write两个函数的文件中添加#include<unistd.h>就可以编译了,而且读写内存也很顺利。
离线yypeony
只看该作者 7楼 发表于: 2006-02-15
读写一般.txt文件与读写设备文件一样吗?
我读写.txt文件可以了,不知道向设备文件传数据可以吗?
我没有用到#include<unistd.h>
离线yypeony
只看该作者 8楼 发表于: 2006-02-15
我用的是QTextstream
离线jojo
只看该作者 9楼 发表于: 2006-02-15
我使用的设备文件是字符型的,用QTextstream或readBlock和writeBlock我感觉都不太适合,因为用他们我还没有成功过,从我的角度来看读写接口方面就不是很匹配。读写一般.txt文件用QT里的类就行,读写设备文件建议最好用C++里的文件读写函数read和write(问了几个做过的人都是这样用的)。
离线yypeony
只看该作者 10楼 发表于: 2006-02-19
在QT里具体怎么用驱动程序里的文件读写函数read和write
对于驱动程序我现在只有一个概念,还没有写过驱动呢
在应用程序里怎么调用我还不明白
希望多多指点,谢谢
离线jojo
只看该作者 11楼 发表于: 2006-02-19
下面是我师兄写的驱动程序的摘录(指摘了与读取相关的部分)。

下面是针对RAM的读写函数:
void write_ram(U16 addr,U16 data)
{      
rGPECON = 0x55555555;                 //data output
rGPBDAT = addr;                     //transfer addr
rGPEDAT = data;                     //transfer data
rGPFDAT&= 0xFFFFFFFB;                 //ce=0
printk("write addr=%X,data=%X\n",addr,data); //for debug
rGPFDAT&= 0xFFFFFFFE;                 //r/w=0
rGPFDAT|= 0x1;                     //r/w=/ce=1
rGPFDAT|= 0x00000004;                 //r/w=/ce=1
}

U16 read_ram(U16 addr)
{
U16 data;
rGPECON = 0x0;                     //input
rGPBDAT = addr;                     //transfer addr
//a condition ?
rGPFDAT&= 0xFFFFFFFB;                 //ce=0
rGPFDAT&= 0xFFFFFFFD;                 //oe=0
data   = rGPEDAT;                   //transfer data
rGPFDAT|= 0x4;                     //ce=1
rGPFDAT|= 0x2;                     //oe=1
printk("read addr=%X,data=%X\n",addr,data);   //for debug
return data;
}

下面是对上面的函数的linux包装,使其适应linux操作系统(一定要有,再深的我也不懂):
//Read to device
static ssize_t ram_rd(struct file *file, char *buf, size_t count, loff_t *offset)
{    
U16 i;
U16 raddr=0,data=0;
dbuf = kmalloc(count*sizeof(U8) , GFP_KERNEL);   //requsest mem in kernel
copy_from_user(dbuf,buf,2);               //transfer data form user to kernel
raddr=(dbuf[1]<<8)+dbuf[0];               //transfer addr
for(i=2;i<count;i=i+2)                   //transfer data
{
  data=read_ram(raddr);
  dbuf=data;
  dbuf[i+1]=data>>8;
  raddr++;
  }
copy_to_user(buf,dbuf,count);             //transfer data form kernel to user
kfree(dbuf);
return 0;
}

//Write to device
static ssize_t ram_wr(struct file *file,const char *buf, size_t count, loff_t *offset)

{
U16 i=0;
U16 raddr=0,data=0;
dbuf = kmalloc(count*sizeof(U8) , GFP_KERNEL);   //requsest mem in kernel
copy_from_user(dbuf,buf,count);             //transfer data form user to kernel
raddr=(dbuf[1]<<8)+dbuf[0];               //transfer addr
for(i=2;i<count;i=i+2)                   //transfer data
{
data=(dbuf[i+1]<<8)+dbuf;
write_ram(raddr,data);
raddr++;
}      
kfree(dbuf);
return 0;
}

下面是注册驱动程序时用到的一个结构,它的作用是定义该驱动程序可以对RAM进行哪些操作,其中就有read和write(它们与ram_rd、ram_wr),也就是要在QT中用的。
static struct file_operations ram_fops =
{
owner:            THIS_MODULE,
llseek:            no_llseek,
read:            ram_rd,
write:            ram_wr,
ioctl:            ram_ioctl,
open:            ram_open,
release:      ram_close,
};

下面是在QT中的应用:
这是自定义的函数,"/dev/ram"中的ram是驱动文件的名字,char数组的赋值是针对我的程序的,看不懂可略过。

void First::send()
{
 
  bool ok;
  char wr[4];
  char rd[4];
  QString str_temp;
 
  str_temp=data_16b.mid( 0, 2 );
  wr[0]=str_temp.toUInt(&ok,16);
  str_temp=data_16b.mid( 2, 2 );
  wr[1]=str_temp.toUInt(&ok,16);
  str_temp=data_16b.mid( 4, 2 );
  wr[2]=str_temp.toUInt(&ok,16);
  str_temp=data_16b.mid( 6, 2 );
  wr[3]=str_temp.toUInt(&ok,16);
  rd[0]=wr[0];
  rd[1]=wr[1];

  int fd;
  fd = open("/dev/ram",O_RDWR);

  write(fd,wr,4);
  read(fd,rd,4);
 
  if(rd[2]==wr[2])
  Hz->setEnabled(TRUE);
  else
  Hz->setEnabled(FALSE);

}

我能帮的就这么多,我也是初学者,再深的我也不太懂,希望能帮到你。
离线yypeony
只看该作者 12楼 发表于: 2006-02-19
非常感谢你,我试试吧
在QT中用到的也就是最后那一段吧
前面的都是驱动程序里的吧
离线jojo
只看该作者 13楼 发表于: 2006-02-19
是的,祝你成功!
离线njlianjian

只看该作者 14楼 发表于: 2006-02-27
楼上的,那个问题解决了吗?能否共享一下你的结果?
离线obrire

只看该作者 15楼 发表于: 2006-03-08
用驱动程序的Read和Write接口,取得所需内容即是相对于user space的地址,就可直接读写了,这与QT没关系呀。或者是发送ioctl命令,驱动会将内核地址内容拷贝至用户空间,直接取过来就可以用了(这要看驱动是否实现了此函数)。

如果是keypad或其它输入设备,QT有相对应的专门接口,请参阅相应手册或源码入口。
离线chenluo168
只看该作者 16楼 发表于: 2009-05-17
这么好的贴子,怎么能让它沉了,我还不知道弄呢
快速回复
限100 字节
 
上一个 下一个