rk3399下adc驱动

搞了搞ADC,突然发现像是再用库函数对32编程一样,API如下

struct iio_channel *iio_channel_get(struct device *dev, const char *consumer_channel);
功能:获取 iio 通道描述
参数:
dev: 使用该通道的设备描述指针
consumer_channel: 该设备所使用的 IIO 通道描述指针
void iio_channel_release(struct iio_channel *chan);
功能:释放 iio_channel_get 函数获取到的通道
参数:
chan:要被释放的通道描述指针
int iio_read_channel_raw(struct iio_channel *chan, int *val);
功能:读取 chan 通道 AD 采集的原始数据。
参数:
chan:要读取的采集通道指针
val:存放读取结果的指针

驱动代码: 

#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/moduleparam.h>
#include <linux/stat.h>

#include <linux/init.h>
#include <linux/module.h> 
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/adc.h>

#include <linux/version.h>

#include <linux/init.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#include <linux/iio/iio.h>
#include <linux/iio/machine.h>
#include <linux/iio/driver.h>
#include <linux/iio/consumer.h>

#define GPIO_LOW 0
#define GPIO_HIGH 1
int major;
int count;

static struct class *cls;
static int arg1=0;
module_param(arg1,int,S_IRUSR);

struct iio_channel *chan;

static int adc_open(struct inode *inode, struct file *file)
{
	printk(KERN_EMERG "%s-%d: enter\n",__FUNCTION__,__LINE__);
	
	return 0;	
}

static struct file_operations adc_fops = {
    .owner  =   THIS_MODULE,   
    .open   =   adc_open,     	   
};

static int adc_probe(struct platform_device *pdev)
{
	int i=0;
	int ret,raw;
	int result = -1;
	
	printk(KERN_EMERG "%s-%d: enter\n",__FUNCTION__,__LINE__);
	
    major = register_chrdev(0, "adc", &adc_fops);
	cls = class_create(THIS_MODULE, "adc");
	device_create(cls, NULL, MKDEV(major, 0), NULL, "adc_test"); 
	chan = iio_channel_get(&(pdev->dev), NULL);
	if (IS_ERR(chan))
 	       	{
			chan = NULL;
			printk("%s() have not set adc chan\n", __FUNCTION__);
            return -1;
	}
	while(i<arg1)
	{
		ret = iio_read_channel_raw(chan, &raw); 
		if (ret < 0) {
			printk("read hook adc channel() error: %d\n", ret);
			return -1;
		    }

		result = (1800*raw)/1023;
		printk(KERN_INFO "i = %d raw= %d Voltage=%dmV\n",i,raw,result);
		i++;
		mdelay(500);
	}
	
	printk(KERN_INFO "%s-%d: exit\n",__FUNCTION__,__LINE__);
	return 0;  
}


static int adc_remove(struct platform_device *pdev)
{ 
	printk(KERN_INFO "Enter %s\n", __FUNCTION__);
	iio_channel_release(chan);
	device_destroy(cls, MKDEV(major, 0));
	class_destroy(cls);
	unregister_chrdev(major, "adc");
    return 0;
}
static const struct of_device_id of_adc_match[] = {
	{ .compatible = "adc_test" },
	{ /* Sentinel */ }
};
static struct platform_driver adc_driver = {
	.probe		= adc_probe,
	.remove		= adc_remove,
	.driver		= {
		.name	= "adc",
		.owner	= THIS_MODULE,
		.of_match_table	= of_adc_match,
	},

};

static int __init adc_init(void)
{
    printk(KERN_INFO "Enter %s\n", __FUNCTION__);
    return platform_driver_register(&adc_driver);
    return 0;
}

static void __exit adc_exit(void)
{
	platform_driver_unregister(&adc_driver);
    printk(KERN_INFO "Exit Hello world\n");
}
module_init(adc_init);
module_exit(adc_exit);
MODULE_LICENSE("GPL");

然后,dts文件新增内容:

adc_demo{
                status = "okay";
                compatible = "adc_test";
                io-channels = <&saradc 3>;//通道三
        };

加载模块使用命令:insmod adc.ko arg1=10,这里传递的参数是打印的次数,防止死循环,由于不知道是什么原因,测试程序无法在开发板上面跑,就把读取的操作放在了prob函数里面,为了防止出现死循环,传了个参数

有什么问题可以先去看看wiki的教程

猜你喜欢

转载自blog.csdn.net/qq_33166886/article/details/83826077