您的位置:首页 > 运维架构 > Linux

Linux arm9260 ADC驱动程序

2013-05-30 22:28 387 查看
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为外设A,adc采样,'0':is'nt use pullup

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

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;

}

测试结果:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: