WhyCan Forum(哇酷开发者社区)

我们习惯了"有问题百度一下", 感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信: whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn

您尚未登录。

#1 2018-08-13 17:21:39

小白菜
会员
注册时间: 2017-09-27
累计积分: 88

NUC972上继续填土

苦逼的我又要往坑里填土了
看了新唐97x提供的iio-adc驱动之后,赶脚太脑壳疼,就自个弄了个简单的驱动,能读数了,有点进步,在这里先记录一下,(小白菜声明,借鉴网络以及官方驱动自个胡搞得,如有冒犯,请告知我大哥——晕哥)
废话少说上代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
//#include <mach/platform.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h> //copy_from_user声明
#include <linux/device.h> //设备文件的自动创建
#include <linux/clk.h>
#include <linux/kernel.h>
//#include <asm/mach/map.h>
#include "../../../arch/arm/mach-nuc970/include/mach/map.h"
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/buffer.h>

#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <asm/uaccess.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/cdev.h>

//寄存器地址映射

//#define adcba ioremap(NUC970_PA_ADC,(NUC970_SZ_ADC - 1))
#define CTL 0x00
#define CONF 0x04
#define IER     0x08
#define ISR     0x0C
#define DATA    0x28
//#define ADCCONF (volatile unsigned long *)0xB800A004
static struct clk *adc_clk;//定义adc时钟结构
//static int Device_Open = 0;
static int adc_init(void);
void adc_cleanup(void);
int init_module(void);
void cleanup_module(void);
struct adc_data_misc{
    unsigned int data0;
    unsigned int data1;
    unsigned int data3;
};
struct adc_data{
    unsigned int data;
    int val;
};
struct adc_pag{
    unsigned int buf[127];
};
//static unsigned long *adcbase;
static void adc_read(struct adc_data *adcdata){
    unsigned long *adcbase;
    adcbase = ioremap(NUC970_PA_ADC,(NUC970_SZ_ADC - 1));
    writel(0x3<<6, adcbase + 0x01); //select AGND33 vs AVDD33
    writel(1, adcbase + 0x00); //enable AD_EN, disable bandgap
    writel(1, adcbase + 0x02);
    writel((readl(adcbase + 0x01) | 1<<2), adcbase + 0x01); //enable NACEN
        // enable channel
    writel((readl(adcbase + 0x01) & ~(0x7 << 3)) | (adcdata->val << 3), adcbase + 0x01);
    writel(readl(adcbase + 0x00) | 0x100, adcbase + 0x00);
    writel(readl(adcbase + 0x03) | 0x001,adcbase + 0x03);
    *(adcbase + 0x03) = 0x401;
    //printk("adcbase + 0x03value=%lx\n",*(adcbase + 0x03));
    //if(readl(adcbase + 0x03)&0x400){
    adcdata->data = readl(adcbase + 0x0A);   
    //}
    //else{
        //printk("read error\n");
    //}
    iounmap(adcbase);
}
#define ADC_CHANNEL0 0x100000
#define ADC_CHANNEL1 0x100001
#define ADC_CHANNEL2 0x100002
#define ADC_CHANNEL3 0x100003
#define ADC_CHANNEL4 0x100004
#define ADC_CHANNEL5 0x100005
#define ADC_CHANNEL6 0x100006
#define ADC_CHANNEL7 0x100007
static long adc_ioctl(struct file *file,
            unsigned int cmd,
            unsigned long arg){
    struct adc_data adcdata;
    struct adc_pag adcpag;
    struct adc_data_misc adcdatamisc;
    switch(cmd){
        case ADC_CHANNEL0:
        adcdata.val = 0;
        adc_read(&adcdata);
       
        copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
        break;
        case ADC_CHANNEL1:
        adcdata.val = 1;
        adc_read(&adcdata);
        copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
        break;
        case ADC_CHANNEL2:
        adcdata.val = 2;
        adc_read(&adcdata);
        copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
        break;
        case ADC_CHANNEL3:
        adcdata.val = 3;
        adc_read(&adcdata);
        copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
        break;
        case ADC_CHANNEL4:
        adcdata.val = 4;
        adc_read(&adcdata);
        copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
        break;
        case ADC_CHANNEL5:
        adcdata.val = 5;
        adc_read(&adcdata);
        copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
        break;
        case ADC_CHANNEL6:
        adcdata.val = 6;
        adc_read(&adcdata);
        copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
        break;
        case ADC_CHANNEL7:
        adcdata.val = 0;
        adc_read(&adcdata);
        copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
        break;
        default:
            return -1;
    }
    //copy_from_user(&kindex,(int *)arg,sizeof(kindex));
    return 0;
}
struct file_operations  adc_ops = 
{                                 
       .owner    = THIS_MODULE,
    .unlocked_ioctl = adc_ioctl
};

static struct cdev adc_cdev;
struct class *cls;

static dev_t dev;
static int adc_init(void){

    alloc_chrdev_region(&dev, 0, 1, "xzm");
    cdev_init(&adc_cdev, &adc_ops);
    cdev_add(&adc_cdev, dev, 1);
    cls = class_create(THIS_MODULE, "qiuqiu");
    device_create(cls, NULL, dev, NULL, "myadc");
    adc_clk = clk_get(NULL,"adc");
    if(!adc_clk){
        printk("failed to get adc clocl source \n");
        return -ENOENT;
    }
    clk_enable(adc_clk);
           printk(" initialized\n");
    return 0;
}

void adc_cleanup(void){
    if(adc_clk){
        clk_disable(adc_clk);
            clk_put(adc_clk);
            adc_clk = NULL;
    }
        unregister_chrdev_region(dev, 1);
    cdev_del(&adc_cdev);
    device_destroy(cls, dev);
    class_destroy(cls);
}
module_init(adc_init);       
module_exit(adc_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("you");


调试程序同样上代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#define ADC_FUYONG    0x10000
#define ADC_CHANNEL0 0x100000
#define ADC_CHANNEL1 0x100001
#define ADC_CHANNEL2 0x100002
#define ADC_CHANNEL3 0x100003
#define ADC_CHANNEL4 0x100004
#define ADC_CHANNEL5 0x100005
#define ADC_CHANNEL6 0x100006
#define ADC_CHANNEL7 0x100007
struct adc_data {
    unsigned int x;
};
struct adc_data_misc{
    unsigned int data0;
    unsigned int data1;
    unsigned int data3;
};
struct adc_pag{
    int buf[127];
};
int main(void)
{
    int fd,i,j,cmd;
    int buf[127];
    struct adc_data info; //分配用户缓冲区
    struct adc_data_misc miscinfo;
    struct adc_pag adcpag;
    info.x=1;
    i = 1;
    fd = open("/dev/myadc", O_RDWR);
    if (fd < 0){
    printf("file error\n");
        return -1;
}
    printf("info.x=%d\n",info.x);
    printf("please input channel:\n");
//    scanf("%d",&cmd);
    cmd = 0;
    switch(cmd){
        case 0:
        printf("start write\n");
        for(j = 0;j < 20;j++){
                ioctl(fd,ADC_CHANNEL0, &info);
        //buf{i++} = info.x;
        buf{  i  }= info.x;
        i = i + 1;
                printf("%d ", info.x);
        ioctl(fd,ADC_CHANNEL1, &info);
        //buf{i++} = info.x;
        buf {i } = info.x;
        i = i + 1;
                printf("%d ", info.x);
                ioctl(fd, ADC_CHANNEL2, &info);
        //buf{i++} = info.x;
        buf{ i } = info.x;
        i = i + 1;
                printf("%d ", info.x);
        printf("\n");
                //usleep(50000);
                }
        break;
                case 1:
                while(1){
                ioctl(fd,ADC_CHANNEL1, &info);
                printf("%d\n", info.x);
                //usleep(50000);
                }
                break;
                case 2:
                while(1){
                ioctl(fd, ADC_CHANNEL2, &info);
                printf("%d\n", info.x);
                //usleep(50000);
                }
                break;
                case 3:
                while(1){
                ioctl(fd, ADC_CHANNEL3, &info);
                printf("%d\n", info.x);
                //usleep(50000);
                }
                break;
                case 4:
                while(1){
                ioctl(fd, ADC_CHANNEL4, &info);
                printf("%d\n", info.x);
                //usleep(50000);
                }
                break;
                case 5:
                while(1){
                ioctl(fd, ADC_CHANNEL5, &info);
                printf("%d\n", info.x);
                //usleep(50000);
                }
                break;
                case 6:
                while(1){
                ioctl(fd, ADC_CHANNEL6, &info);
                printf("%d\n", info.x);
                //usleep(50000);
                }
                break;
                case 7:
                for(i = 0;i < 15;i++){
                ioctl(fd, ADC_CHANNEL7, &info);
                printf("%d\n", info.x);
                //usleep(50000);
                }
                break;
        case 8:
        while(1){
        ioctl(fd,ADC_FUYONG,&miscinfo);
        printf("ADC0=%d\n",miscinfo.data0);
        printf("ADC1=%d\n",miscinfo.data1);
        printf("ADC3=%d\n",miscinfo.data3);
        }
        default:
            return -1;
    }
    printf("start read\n");
    for(i = 1;i<64;i++){
    printf("%d ",buf{i});
    }
        printf("\n");
    close(fd);
    return 0;
}

驱动代码写的比较简单,这里之所以要恬不知耻的上传,主要还是给老板(晕哥)打工没办法,大佬们,觉得辣眼睛的话,自觉忽略
驱动是有些问题的,还待完善,大佬们给下建议,用示波器抓的图会让老板上传

QQ20180813172232.jpeg

离线

#2 2018-08-14 22:53:04

sblpp
会员
注册时间: 2018-02-14
累计积分: 88

Re: NUC972上继续填土

顶楼主,我还在坑里  没爬上来呢...

离线

#3 2018-10-16 17:01:52

hzd52044
会员
注册时间: 2018-10-16
累计积分: 7

Re: NUC972上继续填土

感谢分享,正在找ADC相关的东西

离线

#4 2020-05-19 14:19:20

zsk_diy
会员
注册时间: 2020-05-19
累计积分: 6

Re: NUC972上继续填土

看不的确脑壳疼啊,不错,正需要这方面的资料,感谢

离线

#5 2020-05-20 04:10:58

Kota
会员
注册时间: 2020-05-03
累计积分: 7

Re: NUC972上继续填土

How is the driver installed? Over insmod or modprobe?

离线

页脚

工信部备案:粤ICP备20025096号-1 Powered by FluxBB