|
本帖最后由 conway 于 2015-5-26 18:20 编辑
默认情况下ADC驱动没有将接口导出到用户空间,它只是应用于电阻触屏,若要使用别的ADC通道还得另外实现驱动,下面是一个简单的ADC驱动及测试程序:
lradc.c:
[mw_shl_code=applescript,true]#include<linux/module.h> /* module */
#include<linux/fs.h> /* file operation */
#include<asm/uaccess.h> /* get_user() */
#include<linux/miscdevice.h> /* miscdevice */
#include<asm/io.h> /* ioctl */
#include <mach/regs-lradc.h> /* #define */
static void __iomem *adc_base = NULL;
static int adc_open (struct inode *inode, struct file *fp)
{
try_module_get(THIS_MODULE);
writel(0xC0000000, adc_base + HW_LRADC_CTRL0_CLR); /* 开启CLK,关闭复位模式 */
writel(0x18430000, adc_base + HW_LRADC_CTRL1_CLR); /* 关闭0-1-6通道及按键中断 */
writel(0x30000000, adc_base + HW_LRADC_CTRL3_SET); /* 忽略上电前三次采集数据 */
writel(0x76543210, adc_base + HW_LRADC_CTRL4); /* 设置对应的数据存放位置 */
printk("adc open!\n");
return 0;
}
static int adc_release (struct inode *inode, struct file *fp)
{
module_put(THIS_MODULE);
printk("adc closed!\n");
return 0;
}
/*********************************************************************************************************
** cmd:
** 10:CH0 11:CH1 16:CH6 17:Vbat(内部除4)
** 20:CH0(开启除2) 21:CH1(开启除2) 26::CH6(开启除2)
**
** 被注释部分为3.0以上内核函数定义形式
*********************************************************************************************************/
//static int adc_ioctl(struct file *fp, struct file *flip, unsigned int cmd, unsigned long arg)
static int adc_ioctl(struct inode *inode, struct file *flip, unsigned int cmd, unsigned long arg)
{
int iRes;
int iTmp;
if(cmd <10 || cmd >27){
return -1;
}
iTmp = cmd % 10;
if(cmd == 20){
writel(0x01000000, adc_base + HW_LRADC_CTRL2_SET);
}
if(cmd == 10){
writel(0x01000000, adc_base + HW_LRADC_CTRL2_CLR);
}
if(cmd == 21){
writel(0x02000000, adc_base + HW_LRADC_CTRL2_SET);
}
if(cmd == 11){
writel(0x02000000, adc_base + HW_LRADC_CTRL2_CLR);
}
if(cmd == 26){
writel(0x40000000, adc_base + HW_LRADC_CTRL2_SET);
}
if(cmd == 16){
writel(0x40000000, adc_base + HW_LRADC_CTRL2_CLR);
}
writel(0x00000001 << iTmp, adc_base + HW_LRADC_CTRL0_SET);
while(!( readl(adc_base + HW_LRADC_STATUS) & ((1 << 16) << iTmp) ));
iRes = readl(adc_base + HW_LRADC_CHn(iTmp));
iRes = iRes & 0x0003FFFF;
copy_to_user((void *)arg, (void *)(&iRes), sizeof(int));
return 0;
}
/*********************************************************************************************************
Device Struct
*********************************************************************************************************/
struct file_operations adc_fops =
{
.owner = THIS_MODULE,
.open = adc_open,
.release = adc_release,
.ioctl = adc_ioctl,
};
static struct miscdevice adc_miscdev =
{
.minor = MISC_DYNAMIC_MINOR,
.name = "simple-adc",
.fops = &adc_fops,
};
/*********************************************************************************************************
Module Functions
*********************************************************************************************************/
static int __init adcModule_init (void)
{
int iRet=0;
printk("\nadc module init!\n");
adc_base = ioremap(0x80050000, 0x180*4);
iRet = misc_register(&adc_miscdev);
if (iRet) {
printk("register failed!\n");
}
return iRet;
}
static void __exit adcModule_exit (void) /* warning:return void */
{
printk("\nadc module exit!\n");
misc_deregister(&adc_miscdev);
}
/*********************************************************************************************************
Driver Definitions
*********************************************************************************************************/
module_init(adcModule_init);
module_exit(adcModule_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("abcdczj@163.com");
MODULE_DESCRIPTION("imx28x LRADC");
/*********************************************************************************************************
End File
*********************************************************************************************************/
[/mw_shl_code]
lradc_test.c:
[mw_shl_code=applescript,true]#include<stdio.h> /* using printf() */
#include<stdlib.h> /* using sleep() */
#include<fcntl.h> /* using file operation */
#include<sys/ioctl.h> /* using ioctl() */
int main(int argc, char *argv[])
{
int fd;
int iRes;
int time = 100;
double val;
fd = open("/dev/simple-adc", 0);
if(fd < 0){
printf("open error by APP- %d\n",fd);
close(fd);
return 0;
}
while(time--){
sleep(1);
ioctl(fd, 20, &iRes); /* 开启除2 CH0 */
val = (iRes * 3.7) / 4096.0;
printf("CH0:%.2f\t", val);
ioctl(fd, 11, &iRes); /* 不开除2 CH1 */
val = (iRes * 1.85) / 4096.0;
printf("CH1:%.2f\t", val);
ioctl(fd, 26, &iRes); /* 开启除2 CH6 */
val = (iRes * 3.7) / 4096.0;
printf("CH6:%.2f\t", val);
ioctl(fd, 17, &iRes); /* 电池电压默认除4 */
val = (iRes * 7.4) / 4096.0;
printf("Vbat:%.2f\t", val);
printf("\n");
}
close(fd);
}[/mw_shl_code]
|
|