视频讲解及资料链接:链接:https://pan.baidu.com/s/1rPjq2goHFZf2ArBuo99Ehg 提取码:fdqk
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//------------------------------------------------
#define GEC6818_ADC_IN0 _IOR('A', 1, unsigned long)
#define GEC6818_ADC_IN1 _IOR('A', 2, unsigned long)
static void __iomem *adc_base_va; //adc的虚拟地址基址
static void __iomem *adccon_va;
static void __iomem *adcdat_va;
static void __iomem *prescalercon_va;
//---------------------------------------------
static int gec6818_adc_open (struct inode * inode, struct file *file)
{
printk("gec6818_adc_open \n");
return 0;
}
static int gec6818_adc_release (struct inode * inode, struct file *file)
{
printk("gec6818_adc_release \n");
return 0;
}
static long gec6818_adc_ioctl (struct file *filp, unsigned int cmd, unsigned long args)
{
unsigned long adc_val=0,adc_vol=0;
int rt=0;
//adc通道选择
switch(cmd)
{
case GEC6818_ADC_IN0:
iowrite32(ioread32(adccon_va)&(~(7<<3)),adccon_va);
break;
case GEC6818_ADC_IN1:
{
iowrite32(ioread32(adccon_va)&(~(7<<3)),adccon_va);
iowrite32(ioread32(adccon_va)|(1<<3),adccon_va);
}break;
default:
printk("IOCTLCMD failed\n");
return -ENOIOCTLCMD;
}
//将电源开启
iowrite32(ioread32(adccon_va)&(~(1<<2)),adccon_va);
//预分频值=199+1,ADC的工作频率=200MHz/(199+1)=1MHz
iowrite32(ioread32(prescalercon_va)&(~(0x3FF<<0)),prescalercon_va);
iowrite32(ioread32(prescalercon_va)|(199<<0),prescalercon_va);
//预分频值使能
iowrite32(ioread32(prescalercon_va)|(1<<15),prescalercon_va);
//ADC使能
//iowrite32(ioread32(adccon_va)&(~(1<<0)),adccon_va);
iowrite32(ioread32(adccon_va)|(1<<0),adccon_va);
//等待AD转换结束
while(ioread32(adccon_va)&(1<<0));
//读取12bit数据
adc_val = ioread32(adcdat_va)&0xFFF;
//关闭CLKIN时钟输入
iowrite32(ioread32(prescalercon_va)&(~(1<<15)),prescalercon_va);
//关闭ADC电源
iowrite32(ioread32(adccon_va)|(1<<2),adccon_va);
//将AD转换的结果值 换算为 电压值
adc_vol = adc_val*1800/4095;
rt = copy_to_user((void *)args,&adc_vol,4);
if(rt != 0)
return -EFAULT;
return 0;
}
static ssize_t gec6818_adc_read (struct file *file, char __user *buf, size_t len, loff_t * offs)
{
return 0;
}
static const struct file_operations gec6818_adc_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = gec6818_adc_ioctl,
.open = gec6818_adc_open,
.release = gec6818_adc_release,
.read = gec6818_adc_read,
};
static struct miscdevice gec6818_adc_miscdev = {
.minor = MISC_DYNAMIC_MINOR, //MISC_DYNAMIC_MINOR,动态分配次设备号
.name = "adc_drv", //设备名称,/dev/adc_drv
.fops = &gec6818_adc_fops, //文件操作集
};
//入口函数
static int __init gec6818_adc_init(void)
{
int rt=0;
struct resource *adc_res=NULL;
//混杂设备的注册
rt = misc_register(&gec6818_adc_miscdev);
if (rt)
{
printk("misc_register fail\n");
return rt;
}
//-------------------------------------------------------------
//IO内存动态映射,得到物理地址相应的虚拟地址
adc_base_va = ioremap(0xC0053000,0x14);
if(adc_base_va == NULL)
{
printk("ioremap 0xC0053000,0x14 fail\n");
goto fail_ioremap_adc;
}
//得到每个寄存器的虚拟地址
adccon_va = adc_base_va+0x00;
adcdat_va = adc_base_va+0x04;
prescalercon_va = adc_base_va+0x10;
printk("gec6818 adc init\n");
//------------------------------------------------------------
return 0;
fail_ioremap_adc:
misc_deregister(&gec6818_adc_miscdev);
return rt;
}
//出口函数
static void __exit gec6818_adc_exit(void)
{
iounmap(adc_base_va);
misc_deregister(&gec6818_adc_miscdev);
printk("gec6818 adc exit\n");
}
//驱动程序的入口:insmod led_drv.ko调用module_init,module_init又会去调用gec6818_adc_init。
module_init(gec6818_adc_init);
//驱动程序的出口:rmsmod led_drv调用module_exit,module_exit又会去调用gec6818_adc_exit。
module_exit(gec6818_adc_exit)
//模块描述
MODULE_AUTHOR("[email protected]"); //作者信息
MODULE_DESCRIPTION("gec6818 adc driver"); //模块功能说明
MODULE_LICENSE("GPL"); //许可证:驱动遵循GPL协议
#include
#include
#include
#include
#include
#include
#include
#define GEC6818_ADC_IN0 _IOR('A', 1, unsigned long)
#define GEC6818_ADC_IN1 _IOR('A', 2, unsigned long)
int main(int argc, char **argv)
{
int fd=-1;
int rt;
int i=0;
unsigned long adc_vol = 0;
//打开adc设备
fd = open("/dev/adc_drv",O_RDWR);
if(fd < 0)
{
perror("open /dev/adc_drv:");
return fd;
}
while(1)
{
//读取ADC通道0的电压值
rt=ioctl(fd,GEC6818_ADC_IN0,&adc_vol);
if(rt != 0)
{
printf("adc in0 read filed\r\n");
usleep(50*1000);
continue;
}
printf("adc in0 vol: %lu=mv\r\n",adc_vol);
sleep(1);
}
close(fd);
return 0;
}