本帖最后由 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选项
CONFIG_S3C_ADC=y复制代码在源码主目录下搜索该项
[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文件下还有一个CONFIG_HELPER2416_ADC=y复制代码
重新搜索咯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 的值 --> 要么继续读取,要么退出。。。。
写一个一次的先试试。
//包含头文件
#include
#include
#include
#include
#include
#include
#include
#include
//定义常量和符号
#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))