Linux arm9260 ADC驱动程序

Linux ARM9260 ADC驱动编程

#include <linux/module.h> 

#include <linux/kernel.h> 

#include <linux/init.h> 

#include <linux/interrupt.h> 

#include <linux/clk.h> 

#include <linux/fs.h> 

#include <asm/uaccess.h> 

#include <asm/io.h> 

#include <asm/arch/gpio.h> 

#include <asm/arch/at91_tc.h> 

#include <linux/time.h>

#include <linux/suspend.h>

#define ADC_CR          0x00    //Control Register Offset

#define ADC_MR          0x04    //Mode Register Offset

#define ADC_CHER        0x10    //Channel Enable Register Offset

#define ADC_CHDR        0x14    //Channel Disable Register Offset

#define ADC_CHSR        0x18    //Channel Status Register Offset

#define ADC_SR          0x1C    //Status Register Offset

#define ADC_LCDR        0x20    //Last Converted Data Register Offset

#define ADC_IER         0x24    //Interrupt Enable Register Offset

#define ADC_IDR         0x28    //Interrupt Disable Register Offset

#define ADC_IMR         0x2C    //Interrupt Mask Register Offset

#define ADC_CDR0        0x30    //Channel Data Register 0 Offset

#define ADC_CDR1        0x34    //Channel Data Register 1 Offset

#define ADC_CDR2        0x38    //Channel Data Register 2 Offset

#define ADC_CDR3        0x3C    //Channel Data Register 3 Offset

#define CH_EN           0x03    //Channels to Enable

#define CH_DIS          0x0C    //Channels to Disable

#define TRGEN           0x00    //Trigger Enable

#define TRGSEL          0x00    //Trigger Select

#define LOWRES          0x01    //Resolution

#define SLEEP_MODE      0x00    //Sleep Mode

#define PRESCAL         0x9   //Prescaler Rate Selection

#define STARTUP         0x7    //Start Up Time

#define SHTIM           0x3    //Sample and Hold Time

#define ADC_MAJOR       33            //Major Number

#define ADC_NAME        "at91adc_output"      //Device Name

void __iomem *adc_base;

struct clk *adc_clk;

static int my_adc_read(struct file *file, char __iomem buf, ssize_t count, loff_t *f_ops)

struct file_operations adc_file = {

        .owner = THIS_MODULE,

        .read = my_adc_read,

};

static int my_adc_read(struct file *filp, char __iomem buf, ssize_t count, loff_t *f_ops)

{

    int data, tmp[2];

    memset(tmp, 0, sizeof(tmp));

    data = __raw_readl(adc_base + ADC_CDR0);

    data &= 0x3ff;

    data = (data * 660) / 1024;

    tmp[0] = data;

    printk("Channel0: %d\n", data);

    data = __raw_readl(adc_base + ADC_CDR1);

    data &= 0x3ff;

    data = (data * 660) / 1024;

    tmp[1] = data;

    printk("Channel1: %d\n", data);

    if (copy_to_user(buf, tmp, sizeof(tmp)))

    {

        printk("copy to user failed\n");

        return 0;

    }

    return sizeof(tmp);

}

static int __init my_adc_init(void)

{

    int result;

    adc_clk = clk_get(NULL, "adc_clk"); //open adc clock

    clk_enable(adc_clk);    //trun on adc clock

    at91_set_A_periph(AT91_PIN_PC0, 0); //设置PC0为外设Aadc采样,'0':is'nt use pullup

    at91_set_B_periph(AT91_PIN_PC1, 0); //设置PC1为外设Aadc采样

    adc_base = ioremap(AT91SAM9260_BASE_ADC, SZ_16K);   //将物理地映射到虚拟内存地址

    __raw_writel(0, adc_base + ADC_CR);     //将控制寄存器清零

    __raw_writel((SHTIM << 24 | STARTUP << 16 | PRESCAL << 8 | SLEEP_MODE << 5), adc_base + ADC_MR);//adc模式控制寄存器,包括adc采样的频率

    __raw_writel(0x03, adc_base + ADC_CHER);    //enable channel 0, 1

    __raw_writel(0x0c, adc_base + ADC_CHDR);    //disable channel 2, 3

    result = register_chrdev(ADC_MAJOR, ADC_NAME, &adc_file);   //注册设备

    if (result < 0)

    {

        printk("Register ADC failed\n");

        return 0;

    }

    __raw_writel(0x02, adc_base + ADC_CR);  //启动ADC采样

    return 0;

}

static void __exit my_adc_exit()

{

    unregister_chrdev(ADC_MAJOR, ADC_NAME); //释放 ADC设备

    iounmap(adc_base);

    clk_disable(adc_clk);   //turne off ADC clock

    clk_put(adc_clk);   //close ADC clock

}

MODULE_LICENSE("GPL");

MODULE_AUTHOR("MIKE CHEN");

module_init(my_adc_init);

module_exit(my_adc_exit);

应用程序:

#include <stdlib.h>

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <string.h>

int main(int argc, char **argv)

{

    int fd, data[2], ret;

    memset((char *)data, 0, 8);

    fd = open("/dev/at91adc_output", O_RDWR);

    if (fd < 0)

    {

        printf("open adc failed\n");

        return 0;

    }

    while (1)

    {

     sleep(3);

  memset((char *)data, 0, 8);

     ret = read(fd, data, sizeof(data));

     if (ret < 0)

     {

         printf("read failed\n");

         return 0;

     }

     printf("Channel0: %d, channel1: %d\n", data[0], data[1]);

    }

    return ret;

}

测试结果:

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值