天嵌 ARM开发社区

 找回密码
 注册
查看: 5962|回复: 12

使用ioctl控制驱动程序的方法(附源码)

[复制链接]
huajiji 发表于 2010-4-15 15:26:45 | 显示全部楼层 |阅读模式
我在天嵌给的adc驱动的基础上加了write函数,要实现这样简单的功能:在应用程序里面给出要选择的ADC通道,然后传递到驱动函数里面。就这么简单。
(tq2440_adc_open函数里面adcdev.channel=2;        //设置ADC的通道    这一句我屏蔽了。)
我的write函数如下:
static int tq2440_adc_write(struct file *file, const char *buffer, size_t count,
loff_t * ppos)
{
         char data;    //这里data有试过定义为int,结果也还是一样……
   
        copy_from_user(&data, buffer, count);
        adcdev.channel=data;
     
   
        DPRINTK("set adc channel=%d, prescale=0x%x\n", adcdev.channel, adcdev.pr
escale);
   
        return count;
}
下面的结构体也添加了write了。
static struct file_operations dev_fops = {
        owner:  THIS_MODULE,
        open:   tq2440_adc_open,
        read:   tq2440_adc_read,
        write:  tq2440_adc_write,
        release:  tq2440_adc_release,
};

相应的应用程序则改为:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <errno.h>
#include <string.h>

int main(void)
{
        int fd ;
        char temp = 1;

        fd = open("/dev/adc", 0);
        if (fd < 0)
        {
                perror("open ADC device !");
                exit(1);
        }

        for( ; ; )
        {
                char buffer[30];
                exit(1);
        }

        for( ; ; )
        {
                char buffer[30];
                char len_r,len_w ;
                char  channel2[]={2};//ADC通道选择2

                len_w = write(fd,channel2,sizeof channel2 -1);
                len_r = read(fd, buffer, sizeof buffer -1);
                if (len_r )
                {
                        buffer[len_r] = '\0';
                        int value;
                        sscanf(buffer, "%d", &value);
                        printf("ADC Value2: %d\n", value);
                }
                else
                {
                        perror("read ADC device !");
                        exit(1);
                }
                sleep(1);
        }
adcstop:
        close(fd);
}
重新编译内核和文件系统后烧写到开发板中,结果却不对。这是结果:
[root@EmbedSky /sbin]# ji_adc
ADC Value2: 387
ADC Value2: 303
ADC Value2: 258
ADC Value2: 299
ADC Value2: 346
ADC Value2: 321
ADC Value2: 275
ADC Value2: 276
ADC Value2: 335
这里的ADC的值应该是810左右才对的,而且上面的数值跳动太大了。。。
我要请教天嵌的工程师的问题是:结果不对的原因是不是我写的write函数没能传递应用程序中channel2的值到驱动程序中呢?那要怎样修改才对呢?
本以为只是一个简单的传值操作却花了我一天的时间,麻烦天嵌的高手帮我解答一下啦。谢谢啦!
亚瑟王 发表于 2010-4-16 10:31:01 | 显示全部楼层
这个810的值你是怎么得到的?波动应该是电源有纹波导致的。
 楼主| huajiji 发表于 2010-4-16 10:47:39 | 显示全部楼层
2# 亚瑟王
810是我用原来天嵌提供的驱动和应用程序烧写到板子上得到的。而且我上面自己的程序不论我怎么调板子上的电阻,显示的ADC的值始终是上面那几个。
所以我还才会认为write函数根本就没有把应用程序里channel2的值传到驱动程序里面。。。
希望亚瑟王能再帮我看看啊。谢谢啦!
亚瑟王 发表于 2010-4-16 19:07:37 | 显示全部楼层
你的意思是将采集通道传递进去,然后设定要选择的通道吗?不应该用写,而使用ioctl,和PWM驱动的测试程序一样的操作。
 楼主| huajiji 发表于 2010-4-17 20:37:49 | 显示全部楼层
4# 亚瑟王
好的,我试一下。谢谢亚瑟王啦。
 楼主| huajiji 发表于 2010-4-17 22:36:04 | 显示全部楼层
4# 亚瑟王

我试过,真的可以啦。哈哈!!!!
再次感谢亚瑟王!
照例把我的代码贴出来。虽然简单,但希望以后与我有相同问题的朋友能看到,能够有所帮助。驱动里面添加的ioctl函数:
static int tq2440_adc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
        if(cmd<=0)
        {
                return -EINVAL;
        }
        else
        {
                adcdev.channel=arg;
                return 0;
        }
}
这个结构体也添加了
static struct file_operations dev_fops = {
        owner:  THIS_MODULE,
        open:   tq2440_adc_open,
        read:   tq2440_adc_read,
        ioctl:  tq2440_adc_ioctl,
        release:  tq2440_adc_release,
};
应用程序里面修改为:(我这里是显示两路AD的值,分别是channel1和channel2)
*************************************/

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <errno.h>
#include <string.h>

int main(void)
{
        int fd ;
        char temp = 1;

        fd = open("/dev/adc", 0);
        if (fd < 0)
        {
                perror("open ADC device !");
                exit(1);
        }
       
        for( ; ; )
        {
                char buffer[30];
                char len_r ;
                char  channel1=1,channel2=2;
                 ioctl(fd,1,channel1);
                 len_r = read(fd, buffer, sizeof buffer -1);
                if (len_r )
                {
                        buffer[len_r] = '\0';
                        int value;
                        sscanf(buffer, "%d", &value);
                        printf("ADC Value1: %d\n", value);
                }
                else
                {
                        perror("read ADC device !");
                        exit(1);
                }
               
                ioctl(fd,1,channel2);
                len_r = read(fd, buffer, sizeof buffer -1);
                if (len_r )
                {
                        buffer[len_r] = '\0';
                        int value;
                        sscanf(buffer, "%d", &value);
                        printf("ADC Value2: %d\n", value);
                }
                else
                {
                        perror("read ADC device !");
                        exit(1);
                }
       
                sleep(1);
        }
adcstop:       
        close(fd);
}
哈哈!!!!!太开心啦!
亚瑟王 发表于 2010-4-19 13:05:35 | 显示全部楼层
编写了就好,要不你重新发个帖子,把完整代码贴出来,然后你修改后的代码用红色部分标出来,如何?
 楼主| huajiji 发表于 2010-4-20 21:46:46 | 显示全部楼层
7# 亚瑟王
应亚瑟王要求,把完整代码贴出来。
完整贴出代码的话太长,系统会说帖子长度不符合要求。
发成word格式的附件吧。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
亚瑟王 发表于 2010-4-23 14:53:36 | 显示全部楼层
谢谢了。我把这个帖子的标题改了。
qihang 发表于 2010-7-30 09:22:58 | 显示全部楼层
顺便路过!觉得挺受益!
guoyin 发表于 2010-8-5 09:19:10 | 显示全部楼层
谢谢楼主,学习了
不言DXH 发表于 2011-12-5 18:13:36 | 显示全部楼层
受教了!:lol
陈世超 发表于 2012-4-16 09:32:32 | 显示全部楼层
谢谢楼主的分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号 )

GMT+8, 2024-4-27 06:26 , Processed in 1.078125 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表