本帖最后由 kctime 于 2014-8-9 21:53 编辑
刚刚才流水线上逃回家,在实习的日子里没有时间学习开发板, 回家的几天大概了解了以下开发板,加上以前的基础,弄了个ADC的程序和大家分享。
平台 fedora20 + helper2416
根据开发板手册上写的,从PC端传输文件到目标板上的几种方法里随意选一种,这里选用linux下的minicom等同于win下的超级终端
首先连接好设备
然后把arm-linux-gcc加入环境变量。exportPATH = $PATH:xxx/xxx/xxx/
- [ljh@localhost code]$ arm-linux-gcc
- arm-linux-gcc: no input files
复制代码在终端建立三个标签,第一个开minicom,第二个用来编写,编译代码,第三个来查找文件
在minicom下查找adc设备 如上图
- [root@jyxtec /dev]# ls -l | grep adc
- crw-rw---- 1 root root 10, 59 Jan 1 2000 adc
复制代码C是字符设备, crw-rw---- 可以读写,不能执行,
在dev目录下找到adc设备
说明已经有了驱动了。。去找驱动把,,
一般是通过 makefile config 文件和grep指令查找
看看.config文件下的adc选项
在源码主目录下搜索该项
- [ljh@localhost s3c-linux.jyx]$ grep -rn "CONFIG_S3C_ADC"
复制代码- arch/arm/plat-samsung/Makefile:25:obj-$(CONFIG_S3C_ADC) += adc.o
复制代码 进入这个makefile的目录找到一个adc.c文件
然后我看了半天,不对,
原来在.config文件下还有一个
重新搜索咯 - drivers/char/Makefile:68:obj-$(CONFIG_HELPER2416_ADC)
- += helper2416_adcdev.o
复制代码这回对了 定位到drivers/char/。去这个目录下找到一个helper2416_adcdev.c文件,,然后看看是不是设备驱动。
在这个C文件80多行的地方
找到如下结构体 - static struct file_operations helper2416adcdev_fops = {
- .owner = THIS_MODULE,
- .open = s3c24xx_adcdev_open,
- .release = s3c24xx_adcdev_close,
- .read = s3c24xx_adcdev_read,
- .unlocked_ioctl = helper2416_adc_ioctl,
- };
复制代码
主要看 s3c24xx_adcdev_read helper2416_adc_ioctl 这两个函数就好了
- static long helper2416_adc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
- {
- int ret = 0;
- int err = 0;
- int ioarg = 0;
- if (_IOC_TYPE(cmd) != ADCDEV_IOC_MAGIC)
- return -EINVAL;
- if (_IOC_NR(cmd) > ADCDEV_IOC_MAXNR)
- return -EINVAL;
- if (_IOC_DIR(cmd) & _IOC_READ)
- err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
- else if (_IOC_DIR(cmd) & _IOC_WRITE)
- err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
- if (err)
- return -EFAULT;
- switch(cmd) {
- case ADCDEV_IOCSETCHANNEL:
- ret = __get_user(ioarg, (int *)arg);
- if (ioarg > 9)
- return -EINVAL;
- printk("Set ADC Channel number is %d\n",(int)ioarg);
- helper2416adc.channel = ioarg;
- break;
- default:
- return -EINVAL;
- }
- return ret;
- }
复制代码
这个函数结合开始找到的adc.c一起看,可以知道这货是选择adc通道的,就是说可以用ioctl去选择adc通道。 这里,参数要传址哦
- ret = __get_user(ioarg, (int *)arg);
- if (ioarg > 9)
- return -EINVAL;
- printk("Set ADC Channel number is %d\n",(int)ioarg);
- helper2416adc.channel = ioarg;
- break;
复制代码
关于一些常量的定义在helper2416_adcdev.h 里
- #define ADCDEV_IOC_MAGIC 'S'
- #define ADCDEV_IOCSETCHANNEL _IOW(ADCDEV_IOC_MAGIC, 0x0c, int)
- #define ADCDEV_IOC_MAXNR 0x10
复制代码 这几个等会要 copy 到我们的应用代码里
- static int s3c24xx_adcdev_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
- {
- unsigned long err;
- int adc_value;
- adc_value = s3c_adc_read(helper2416adc.padc_client, helper2416adc.channel);
- err = copy_to_user(buff, &adc_value, sizeof(adc_value));
- return sizeof(adc_value);
- }
复制代码 这个 read 函数里调用的东西在adc.c文件里
- int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch)
- {
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
- int ret;
- client->convert_cb = s3c_convert_done;
- client->wait = &wake;
- client->result = -1;
- ret = s3c_adc_start(client, ch, 1);
- if (ret < 0)
- goto err;
- ret = wait_event_timeout(wake, client->result >= 0, HZ / 2);
- if (client->result < 0) {
- ret = -ETIMEDOUT;
- goto err;
- }
- client->convert_cb = NULL;
- return client->result;
- err:
- return ret;
- }
- EXPORT_SYMBOL_GPL(s3c_adc_read);
复制代码 最后一个宏表示可以被其他的模块使用,,就说明了这货不是要找的驱动文件
再加上这个文件里面没有定义 file_operations 结构体,,所以果断 ctrl+W 了。。
接下来来写 ADC 的代码,
主要就是 打开文件 -->> 选择通道 --> 读取 ADC 的值 --> 要么继续读取,要么退出。。。。
写一个一次的先试试。
- <div class="blockcode"><blockquote>//包含头文件
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- //定义常量和符号
- #define ADCDEV_IOC_MAGIC 'S'
- #define ADCDEV_IOCSETCHANNEL _IOW(ADCDEV_IOC_MAGIC, 0x0c, int)
- #define ADCDEV_IOC_MAXNR 0x10
- //定义设备文件路径
- #define ADC_PATH "/dev/adc"
- int main()
- {
- int adc_dev;
- int ret;
- int data;
- int i=0;
- if((adc_dev=open(ADC_PATH,O_RDWR))<0) //打开文件,,一定要检测是否打开成功哦
- {
- perror("open:");
- exit(1);
- } else
- {
- printf("Open ADC DeviceOK\n");
-
- ret=ioctl(adc_dev,ADCDEV_IOCSETCHANNEL,&i); //设置ADC通道,记得传址
- ret = read(adc_dev, &data, sizeof(data)); //读取ADC转换结果,记得对比返回值
- if(ret != sizeof(data))
- {
- if(errno != EAGAIN)
- {
- printf("Read ADC Device Faild!\n");
- }
-
- }
- else
- {
- printf("Read ADC value is: %d\n", data);
- }
- if ( close(adc_dev) < 0 ) //最后记得关闭文件。
- {
- perror("close:");
- exit(1);
- }
- else
- printf("Close ADC Device OK\n");
- }
- }
复制代码
论坛ID:kctime 提交时间:2014.08.09
|