Linux 驅(qū)動--ADC驅(qū)動
內(nèi)核版本:Linux Kernel 2.6.39
本文引用地址:http://www.ex-cimer.com/article/201611/318848.htm硬件平臺:FL2440
開發(fā)板系統(tǒng):Linux Kernel 2.6.28
下面是用CPU輪尋的方式來判斷AD轉(zhuǎn)換完成的
- #include
- #include
- #include
- #include
/*創(chuàng)建設備節(jié)點*/ - #include
- #include
/*延時函數(shù)*/ - #include
- #include
- #include
adc.h> - #include
- #defineADC_MAJOR102
- #defineADC_NAME"my_adc"
- #defineSUCCESS0
- staticintadc_open(structinode*,structfile*);
- staticintadc_release(structinode*,structfile*);
- staticint__initadc_init(void);
- staticint__exitadc_exit(void);
- staticssize_tadc_read(structfile*,char*,size_t,loff_t*);
- volatileunsignedlongadc_con;
- unsignedlongadc_dat0;
- //#defineadc_con(unsignedlong)ioremap(0x58000000,4)
- //#defineadc_dat0(volatileunsignedlong)ioremap(0x5800000c,4)
- structclk*adc_clk;
- structfile_operationsadc_ops=
- {
- .owner=THIS_MODULE,
- .read=adc_read,
- .open=adc_open,
- .release=adc_release,
- };
- staticint__initadc_init(void)
- {
- intret;
- adc_clk=clk_get(NULL,"adc");//獲取時鐘
- clk_enable(adc_clk);//使能時鐘
- ret=register_chrdev(ADC_MAJOR,ADC_NAME,&adc_ops);//注冊設備
- if(ret<0)
- {
- printk("registerdevicefail/n");
- returnret;
- }
- adc_con=(unsignedlong)ioremap(0x58000000,4);
- adc_dat0=(volatileunsignedlong)ioremap(0x58000000+S3C2410_ADCDAT0,4);
- if(adc_con&adc_dat0==0)
- {
- printk("Failedtoioremap/n");
- gotohandle;
- }
- printk("Initialized.../n");
- returnSUCCESS;
- handle:
- unregister_chrdev(ADC_MAJOR,ADC_NAME);
- return-1;
- }
- staticintadc_open(structinode*inode,structfile*file)//打開設備函數(shù)
- {
- returnSUCCESS;
- }
- staticintadc_release(structinode*inode,structfile*file)//關閉設備函數(shù)
- {
- returnSUCCESS;
- }
- staticssize_tadc_read(structfile*file,
- char*buffer,
- size_tlength,
- loff_t*offset)//設備讀取函數(shù)
- {
- unsignedintbuf;
- inttmp;
- inti;
- writew((1<<14)|(0x31<<6),adc_con);//設置ADCCON
- writew((readw(adc_con)|0x1),adc_con);//啟動AD轉(zhuǎn)換
- while(readw(adc_con)&0x1);//啟動轉(zhuǎn)換后,等待啟動位清零
- while(!(readw(adc_con)&0x8000));//等待轉(zhuǎn)換是否完畢
- //for(i=0;i<200000;i++);
- mdelay(100);
- buf=(readw(adc_dat0)&0x3ff);//取出轉(zhuǎn)換后得到的有效數(shù)據(jù)
- copy_to_user(buffer,(char*)&buf,sizeof(buf));
- //printk("Thevalueis%x/n",buf);
- return2;
- }
- staticint__exitadc_exit(void)//驅(qū)動卸載函數(shù)
- {
- iounmap(adc_con);
- iounmap(adc_dat0);
- unregister_chrdev(ADC_MAJOR,ADC_NAME);
- clk_disable(adc_clk);
- clk_put(adc_clk);
- printk("Theadcisunintialized/n");
- returnSUCCESS;
- }
- module_init(adc_init);
- module_exit(adc_exit);
- MODULE_LICENSE("GPL");
其中控制寄存器的第15未標明AD轉(zhuǎn)換是否完成,當AD完成轉(zhuǎn)換時,控制寄存器自動置一,但是由于數(shù)據(jù)存在延遲,當?shù)?5位置一的時候讀出的數(shù)據(jù)并不穩(wěn)定,需要在其后加個延遲的函數(shù),在內(nèi)核態(tài)使用的延遲函數(shù)包含頭文件./linux/delay.h
mdelay(int x);延時x毫秒
udelay(int x);延時x微秒
ndelay(int x);延時x納秒
測試函數(shù)如下:
- #include
- #include
- #include
- #defineADC_DEVICE"/dev/my_adc"
- intmain()
- {
- intret;
- unsignedintdata;
- ret=open(ADC_DEVICE,0);
- if(ret<0)
- {
- printf("Openadcfail/n");
- returnret;
- }
- for(;;)
- {
- //printf("cnt=%d/n",cnt);
- read(ret,&data,sizeof(data));
- printf("Thevalueis0x%x/n",data);
- }
- close(ret);
- return0;
- }
測試結(jié)果
評論