本文共 2171 字,大约阅读时间需要 7 分钟。
adc.c#include#include #include #include #include #include #include #include #include #include #include #define ADCCON 0x126c0000#define ADCDAT 0x126c000c#define ADCMUX 0x126c001c#define ADCCLEAR 0x126c0018struct 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