linux adc驅(qū)動(dòng)(基于三星通用adc api)
硬件平臺(tái): 基于訊為開發(fā)板itop4412 scp 1G
驅(qū)動(dòng)說明:
本驅(qū)動(dòng)基于三星提供的通用api函數(shù)來實(shí)現(xiàn)的,具體adc寄存器操作有三星公司實(shí) 現(xiàn),我們要做的是調(diào)用三星公司提供的api來實(shí)現(xiàn)我們自己的功能。下面對(duì)相關(guān)的結(jié)構(gòu)體和api函數(shù)進(jìn)行解析
[cpp]?view plain?copy
struct?s3c_adc_client?{??
struct?platform_device??*pdev;??
struct?list_head?????pend;??
wait_queue_head_t???*wait;??
unsigned?int?????????nr_samples;??
int??????????result;??
unsigned?char????????is_ts;??
unsigned?char????????channel;??
void????(*select_cb)(struct?s3c_adc_client?*c,?unsigned?selected);??
void????(*convert_cb)(struct?s3c_adc_client?*c,??
unsigned?val1,?unsigned?val2,??
unsigned?*samples_left);??
};??
一個(gè)具體s3c_adc_client結(jié)構(gòu)體來描述一個(gè)具體的客戶(一個(gè)具體的驅(qū)動(dòng))
2.我們需要在驅(qū)動(dòng)中構(gòu)建這個(gè)驅(qū)動(dòng),并且注冊(cè)到linux的內(nèi)核
[cpp]?view plain?copy
struct?s3c_adc_client?*s3c_adc_register(struct?platform_device?*pdev,??
void?(*select)(struct?s3c_adc_client?*client,??
unsigned?int?selected),??
void?(*conv)(struct?s3c_adc_client?*client,??
unsigned?d0,?unsigned?d1,??
unsigned?*samples_left),??
unsigned?int?is_ts)??
例子:
[cpp]?view plain?copy
adcdev.client?=?s3c_adc_register(dev,?NULL,?NULL,?0);??
3.adc開始和停止轉(zhuǎn)換函數(shù)?
[cpp]?view plain?copy
int?s3c_adc_start(struct?s3c_adc_client?*client,??
unsigned?int?channel,?unsigned?int?nr_samples)??
[csharp]?view plain?copy
static?void?s3c_adc_stop(struct?s3c_adc_client?*client)??
4.讀取adc轉(zhuǎn)換數(shù)據(jù)
[cpp]?view plain?copy
int?s3c_adc_read(struct?s3c_adc_client?*client,?unsigned?int?ch)??
5.adc配置相關(guān)的函數(shù)
? ?具體的講解可以讀取博客http://blog.csdn.net/liuhaoyutz/article/details/7461268
平臺(tái)文件adc設(shè)備注冊(cè)
方法一:在配置文件/home/topeet/Android4.0/iTop4412_Kernel_3.0/arch/arm/mach-exynos中的mach-iTop4412.添加
[html]?view plain?copy
struct?platform_device?s3c_device_adc_ctl?=?{??
.name???????????????????=?"adc_ll",??
.id?????????????????????????????=?-1,??
};??
方法二:以模塊的方式注冊(cè)到內(nèi)核
[cpp]?view plain?copy
#include???
#include???
#include???
#include???
#include???
#include???
#include???
#include???
#include???
#include???
#include???
static?struct?platform_device?adc_dev?=?{??
.name?????????=?"adc_ll",??
.id???????=?-1,??
};??
static?int?__init?adc_dev_init(void)??
{??
platform_device_register(&adc_dev);??
return?0;??
}??
static?void?__exit?adc_dev_exit(void)??
{??
platform_device_unregister(&adc_dev);??
}??
module_init(adc_dev_init);??
module_exit(adc_dev_exit);??
MODULE_LICENSE("GPL");??
第二部分:基于雜項(xiàng)設(shè)備方式的設(shè)備驅(qū)動(dòng)
[cpp]?view plain?copy
/*?
*?This?program?is?free?software;?you?can?redistribute?it?and/or?modify?
*?it?under?the?terms?of?the?GNU?General?Public?License?version?2?as?
*?published?by?the?Free?Software?Foundation.?
*/??
#include???
#include???
#include???
#include???
#include???
#include???
#include???
#include???
#include???
#include???
#include???
#define?DEVICE_NAME?????"adc"??
#define?DRIVER_NAME?????"adc_ll"??
typedef?struct?{??
struct?mutex?lock;??
struct?s3c_adc_client?*client;??
int?channel;??
}?ADC_DEV;??
static?ADC_DEV?adcdev;??
static?inline?int?exynos_adc_read_ch(void)?{??
int?ret;??
ret?=?mutex_lock_interruptible(&adcdev.lock);??
if?(ret?0)??
return?ret;??
ret?=?s3c_adc_read(adcdev.client,?adcdev.channel);??
mutex_unlock(&adcdev.lock);??
return?ret;??
}??
static?inline?void?exynos_adc_set_channel(int?channel)?{??
if?(channel?0?||?channel?>?3)??
return;??
adcdev.channel?=?channel;??
}??
static?ssize_t?exynos_adc_read(struct?file?*filp,?char?*buffer,??
size_t?count,?loff_t?*ppos)??
{??
char?str[20];??
int?value;??
size_t?len;??
value?=?exynos_adc_read_ch();??
printk("value?=?0x%x ",?value);??
len?=?sprintf(str,?"%d ",?value);??
if?(count?>=?len)?{??
int?r?=?copy_to_user(buffer,?str,?len);??
return?r???r?:?len;??
}?else?{??
return?-EINVAL;??
}??
}??
static?long?exynos_adc_ioctl(struct?file?*file,??
unsigned?int?cmd,?unsigned?long?arg)??
{??
#define?ADC_SET_CHANNEL?????0xc000fa01??
#define?ADC_SET_ADCTSC??????0xc000fa02??
switch?(cmd)?{??
case?ADC_SET_CHANNEL:??
exynos_adc_set_channel(arg);??
break;??
case?ADC_SET_ADCTSC:??
/*?do?nothing?*/??
break;??
default:??
return?-EINVAL;??
}??
return?0;??
}??
static?int?exynos_adc_open(struct?inode?*inode,?struct?file?*filp)??
{??
exynos_adc_set_channel(0);??
printk("adc?opened ");??
return?0;??
}??
static?int?exynos_adc_release(struct?inode?*inode,?struct?file?*filp)??
{??
printk("adc?closed ");??
return?0;??
}??
static?struct?file_operations?adc_dev_fops?=?{??
owner:??THIS_MODULE,??
open:???exynos_adc_open,??
read:???exynos_adc_read,??????
unlocked_ioctl:?exynos_adc_ioctl,??
release:????exynos_adc_release,??
};??
static?struct?miscdevice?misc?=?{??
.minor??=?MISC_DYNAMIC_MINOR,??
.name???=?DEVICE_NAME,??
.fops???=?&adc_dev_fops,??
};??
static?int?__devinit?exynos_adc_probe(struct?platform_device?*dev)??
{??
int?ret;??
mutex_init(&adcdev.lock);??
printk("%s,?%d ",?__FUNCTION__,?__LINE__);??
/*?Register?with?the?core?ADC?driver.?*/??
#if?1??
adcdev.client?=?s3c_adc_register(dev,?NULL,?NULL,?0);??
if?(IS_ERR(adcdev.client))?{??
printk("itop4412_adc:?cannot?register?adc ");??
ret?=?PTR_ERR(adcdev.client);??
goto?err_mem;??
}??
#endif??
printk("%s,?%d ",?__FUNCTION__,?__LINE__);??
ret?=?misc_register(&misc);??
printk("%s,?%d ",?__FUNCTION__,?__LINE__);??
printk(DEVICE_NAME" initialized ");??
err_mem:??
return?ret;??
}??
static?int?__devexit?exynos_adc_remove(struct?platform_device?*dev)??
{??
misc_deregister(&misc);??
s3c_adc_release(adcdev.client);??
return?0;??
}??
static?int?itop4412_adc_ctl_suspend?(struct?platform_device?*pdev,?pm_message_t?state)??
{??
printk("itop4412_led_ctl?suspend:power?off! ");??
return?0;??
}??
static?int?itop4412_adc_ctl_resume?(struct?platform_device?*pdev)??
{??
printk("itop4412_led_ctl?resume:power?on! ");??
return?0;??
}??
static?struct?platform_driver?exynos_adc_driver?=?{??
.probe??????=?exynos_adc_probe,??
.remove?????=?exynos_adc_remove,??
.suspend?=?itop4412_adc_ctl_suspend,??
.resume?=?itop4412_adc_ctl_resume,??
.driver?=?{??
.name???????=?DRIVER_NAME,??
.owner??????=?THIS_MODULE,??
},??
};??
static?int?__init?exynos_adc_init(void)??
{??
return?platform_driver_register(&exynos_adc_driver);??
}??
static?void?__exit?exynos_adc_exit(void)??
{??
platform_driver_unregister(&exynos_adc_driver);??
}??
module_init(exynos_adc_init);??
module_exit(exynos_adc_exit);??
MODULE_LICENSE("GPL");??
MODULE_AUTHOR("TOPEET?Inc.");??
測試代碼
[cpp]?view plain?copy
#include???
#include???
#include???
#include???
#include???
#include???
#include???
#include???
#include???
#include???
//#include???
//#include???
int?main(void){??
int?fd;??
char?*adc?=?"/dev/adc";??
char?buffer[512];??
int?len=0,?r=0;??
memset(buffer,0,sizeof(buffer));??
printf("adc?ready! ");??
if((fd?=?open(adc,?O_RDWR|O_NOCTTY|O_NDELAY))<0)??
printf("open?adc?err! ");??
else{??
printf("open?adc?success! ");??
len=read(fd,buffer,10);???
if(len?==?0)??
printf("return?null ");??
else{??
r?=?atoi(buffer);??
r?=?(int)(r*10000/4095);????//Datas??transition?to?Res??
printf("res?value?is?%d ",r);??
}?????????????
}??
}??
?
評(píng)論
查看更多