iTop4412之ADC驱动开发

adc.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ADCCON 0x126c0000
#define ADCDAT 0x126c000c
#define ADCMUX 0x126c001c
#define ADCCLEAR 0x126c0018
struct cdev adccdev;
static wait_queue_head_t wq;
dev_t devid;
static int have_data;
static int adc;
unsigned int *adccon;
unsigned int *adcdat;
unsigned int *adcmux;
unsigned int *adcclear;
static irqreturn_t adc_interrupt(int irqno,void *dev)//中断处理函数
{
    have_data=1;//转换完成标志位,
    writel(0x12,adcclear);//清除中断标志位
    wake_up_interruptible(&wq);//唤醒等待队列
    return IRQ_HANDLED;
}
static int adcinit()
{
    request_irq(IRQ_ADC,adc_interrupt,IRQF_DISABLED,"adc1",NULL);//申请中断
    adccon=ioremap(ADCCON,4);//物理地址到虚拟地址映射
    adcdat=ioremap(ADCDAT,4);
    adcmux=ioremap(ADCMUX,4);
    adcclear=ioremap(ADCCLEAR,4);
    init_waitqueue_head(&wq);初始化等待队列
    return 0;
}

static ssize_t adc_read(struct file *filep,char __user *buf,size_t len, loff_t *pos)
{
    writel(0x3,ADCMUX);//选择转换通道
    writel(1<<0|0x1<<16|0xff<<6,ADCCON);//启动12位AD转换
    wait_event_interruptible(wq,have_data==1);//进入等待队列
    adc=readl(adcdat)&0xfff;
    if(copy_to_user(buf,&adc,sizeof(int)))
    {
        return -EFAULT;
    }
    have_data=0;
    return len;
}
static int adc_release(struct inode *inode,struct file *file)
{
    return 0;
}
static int adc_open(struct inode *inde,struct file *file)
{
    return 0;
}
struct file_operations adcops={
.owner=THIS_MODULE,
.open=adc_open,
.read=adc_read,
.release=adc_release,
};
static void adc_init()
{
    cdev_init(&adccdev,&adcops);
    alloc_chrdev_region(&devid, 0 , 1 , "adc12");
    cdev_add(&adccdev,devid,1);
    adcinit();
}
static void adc_exit()
{
    unregister_chrdev_region(&devid,1);
    cdev_del(&adccdev);
}
MODULE_LICENSE("GPL");
module_init(adc_init);
module_exit(adc_exit);

insmod ADC.ko
mknod /dev/adc c 248 0
用户测试程序

APP_ADC.c
#include
#include
#include
#include
int main(int argc char **argv)
{
    int fd,len;
    int adc;
    fd=open("dev/adc",O_RDWR);
    if(fd<0)
    {
        perror("open fail\n");
        return;
    }
    while(1){
        read(fd,&adc,4);
        printf("adc%0.2f V\n",(1.8*adc)/4096);
    }
    close(fd);
}

./APP_ADC

iTop4412之ADC驱动开发_第1张图片

你可能感兴趣的:(LINUX设备驱动进阶)