由图可知,模拟ADC分为两部分功能,一部分是触屏功能,另一部分就是普通ADC功能。分别可以产生INT_TC和INT_ADC 两个中断。该ADC模块总共有8个通道可以进行模拟信号的输入,分别是AIN0、AIN1、AIN2、AIN3、YM、YP、XM、XP通过一个8路模拟开关MUX进行选通。设定控制寄存器(ADCCON)中预分频器的值来确定AD转换器频率,之后ADC将模拟信号转换为数字信号保存到ADC数据寄存器ADCDAT0, ADCDAT0中的数据(一般第十位有效)可以通过中断或查询的方式来获取。
ADC 的使用步骤:
(1) 设置ADCCON 寄存器,选择输入信号通道,设置A/D 转换器的时钟。(2) 设置ADCTSC 寄存器,即ADC触摸屏控制寄存器,工作在两种模式,多用于触摸屏;当使用设为普通转换模式,使用默认值即可。(3) 设置ADCDLY 寄存器,启动A/D 转换。如果在ADCCON中设置READ_START 为1,则读取完已转换数据(读 ADCDAT0 寄存器)时即自动启动下一次转换;否则,就通过设置ENABLE_START 位 来启动A/D。(4) 转换结束时,读取ADCDAT0 寄存器来获取数值。如果使用查询方式,则可以不读取ADCCON 寄存器的ECFLG 位来确定转换是否结束;否则可以使用INT_ADC 中断,发生INT_ADC 中断时表示转 换结束。ADC驱动代码:
记录学习到几点:
1,使用信号量semaphore和队列可以实现阻塞式访问临界区,实现对资源的互斥访问,
信号量使用:
定义和初始化(宏):DEFINE_MUTEX(ADC_LOCK)
两种获取和释放信号量方法,函数包含在linux/semaphore.h头文件声明应该对应使用:
获取信号量:mutex_lock(&ADC_LOCK) 释放信号量:mutex_unlock(&ADC_LOCK)
获取信号量:down_trylock(&ADC_LOCK) 释放信号量:up(&ADC_LOCK)
队列使用:
一个等待队列由一个"等待队列头"来管理, wait_queue_head_t 类型的结构, 定义在<linux/wait.h>中. 一个等待队列头可被定义和初始化, 使用:
定义和初始化:
DECLARE_WAIT_QUEUE_HEAD(adc_waitq) 或者
wait_queue_head_t adc_waitq;
init_waitqueue_head(&adc_waitq);
队列睡眠:
wait_event(adc_waitq, condition)
wait_event_interruptible(adc_waitq, condition)
wait_event_timeout(adc_waitq, condition, timeout)
wait_event_interruptible_timeout(adc_waitq, condition, timeout)
adc_waitq 是要用的等待队列头。
队列唤醒:
void wake_up(wait_queue_head_t *adc_waitq);
void wake_up_interruptible(wait_queue_head_t *adc_waitq);
通常, 不用区分的, 实际上, 惯例是使用 wake_up
2,linux的misc设备对字符设备的封装
3,共享中断的使用
申请ADC中断服务,由于触摸屏驱动和普通转换ADC使用同一中断,共享中断参数IRQF_SHARED。
int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *dev_name, void *dev_id);
参数解析:
unsigned int irq //请求的中断号
irqreturn_t (*handler) // 安装的处理函数指针.
unsigned long flags //一个与中断管理相关的选项的位掩码,共享中断设置为IRQF_SHARED, 否则使用IRQF_DISABLED
const char *dev_name //这个传递给 request_irq 的字串用在 /proc/interrupts 来显示中断的拥有者
void *dev_id //用作共享中断线的指针. 它是一个独特的标识, 用在当释放中断线时以及可能还被驱动用来指向它自己的私有数据区(来标识哪个设备在中断). 如果中断没有被共享, dev_id 可以设置为 NULL,
学习链接:
4,测试代码
/********************************************************************************* * Copyright: (C) 2014 zhouguangfeng* All rights reserved. * * Filename: s3c_adc.c * Description: This file * * Version: 1.0.0 * Author: zhouguangfeng * ChangeLog: 1, Release initial version on "04/01/2012 02:51:19 PM" * ********************************************************************************/#include #include #include #include #include #include #include #include #include #include int main(void){ int adc_fd; int adc_value, adc_size; int k=8; adc_fd = open("/dev/adc", O_RDONLY); if (adc_fd < 0) { perror("open device adc"); exit(1); } while(k--) { adc_size = read(adc_fd, &adc_value, sizeof(adc_value)); printf("adc channel %d value : %d\n", k, adc_value); sleep(1); } close(adc_fd); return 0;}