一、概要
10 位CMOS 的ADC(模数转换器)是有8 通道模拟输入的循环类型设备。其转换模拟输入信号到10 位的数字编码,最大的转换率是在2.5MHz 转换时钟下达到500KSPS。AD 转换
器支持片上采样和保持功能及掉电模式。
触摸屏接口可以控制或选择触摸屏触点用于XY 坐标的转换。触摸屏接口包括触摸触点控制逻辑和有中断产生逻辑的ADC 接口逻辑。
二、触摸屏接口模式
(1) 正常转换模式
单个转换模式可能多数是使用在通用目的的ADC转换。该模式可以通过设置ADCCON(ADC控制寄存器)来初始化并且完成对ADCDAT0 的读写操作(ADC数据寄存器0)。
(2) 分离XY坐标转换模式
触摸屏控制器可以在两种转换模式中的一种模式下操作。分离的XY坐标转换模式由以下方法操作。X坐标模式写X坐标转换数据到ADCDAT0,触摸屏接口产生中断源到中断控制器。Y坐标模式写Y坐标转换数据到ADCDAT1,触摸屏接口产生中断源到中断控制器。
XP XM YP Y M
X Position Conversion External-V GND AIN[5] Hi-Z
Y Position Conversion AIN[7] Hi-Z External-V GND
(3) 自动(连续)XY坐标转换模式
自动(连续)XY坐标转换模式是如下操作,触摸屏控制器连续的转换触摸X坐标和Y坐标。在触摸控制器写X测量数据到ADCDAT0 且写Y测量数据到ADCDAT1 后,触摸屏接口产生中断源到自动坐标转换模式下的中断控制器。
XP XM YP Y M
X Position Conversion External-V GND AIN[5] Hi-Z
Y Position Conversion AIN[7] Hi-Z External-V GND
(4) 等待中断模式
当光标按下,触摸屏控制器产生中断信号(INT_TC)。触摸屏控制器的等待中断模式必须设定为触摸屏接口中触点的状态(XP、XM、YP、YM)。
在触摸屏控制器产生中断信号(INT_TC),等待中断模式必须被清除。(XY_PST设置到无操作模式)。
XP XM YP Y M
Waiting for interrupt Mode pull up Hi-Z AIN[5] GND
备用模式:
备用模式在ADCCON[2]置1 时激活。在此模式下,AD转换操作停止,ADCDAT0 和
ADCDAT1 寄存器保留先前的转换数据。
三、寄存器设置
ADCCON 0x58000000 R/W ADC控制寄存器0x3FC4
(1<<14)|(49<<6)|(3<<3):频率为1MHz,通道AIN3
ADCTSC 0x58000004 R/W ADC触摸屏控制寄存器0x58
(0<<8)|(1<<7)|(1<<6)|(0<<5)|(1<<4)|(0<<3)|(3<<0):等待中断模式,按下
(1<<8)|(1<<7)|(1<<6)|(0<<5)|(1<<4)|(0<<3)|(3<<0):等待中断模式,松开
(1<<3)|(1<<2)|(0<<0):进入自动(连续) X/Y轴坐标转换模式
ADCDLY 0x58000008 R/W ADC开始延时寄存器0x58
ADCDAT0 0x5800000C R/W ADC转换数据寄存器
ADCDAT1 0x58000010 R/W ADC转换数据寄存器-
ADCUPDN 0x58000014 R/W 触摸屏指针上下中断检测寄存器0x0
四、硬件连接
五、代码分析
Makefile
- CC = arm-linux-gcc
- LD = arm-linux-ld
- AR = arm-linux-ar
- OBJCOPY = arm-linux-objcopy
- OBJDUMP = arm-linux-objdump
- INCLUDEDIR := $(shell pwd)/include
- CFLAGS := -Wall -O2
- CPPFLAGS := -nostdinc -I$(INCLUDEDIR)
- LDFLASG := -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc
- export CC LD OBJCOPY OBJDUMP INCLUDEDIR CFLAGS CPPFLAGS
- objs := start.o main.o uart0_init.o i2c_init.o nand.o framebuffer.o \
- lcdlib.o lcddrv.o lib/libc.a adc_ts.o
- adc_ts.bin: $(objs)
- ${LD} -Tmem.lds -o adc_ts_elf $^ ${LDFLASG}
- ${OBJCOPY} -O binary -S adc_ts_elf $@
- ${OBJDUMP} -D -m arm adc_ts_elf > adc_ts.dis
- ${OBJDUMP} -dx adc_ts_elf > memory.map
- .PHONY : lib/libc.a
- lib/libc.a:
- cd lib; make; cd ..
-
- %.o:%.c
- ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
- %.o:%.S
- ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
- clean:
- make clean -C lib
- rm -f adc_ts.bin adc_ts_elf adc_ts.dis *.o
第10行:nostdinc 不要在标准系统目录中寻找头文件.只搜索`-I'选项指定的目录(以及当前目录,如果合适). 结合使用`-nostdinc'和`-I-'选项,你可以把包含文件搜索限制在显式指定的目录.
第11行:指时Linux系统上的GCC库所在目录本机上。
adc_ts.c
- /*
- * FILE: adc_ts.c
- * ADC和触摸屏的测试函数
- */
- #include <stdio.h>
- #include "adc_ts.h"
- #include "s3c2440_addr.h"
- #include "uart0_init.h"
- // ADCCON寄存器
- #define PRESCALE_DIS (0 << 14)
- #define PRESCALE_EN (1 << 14)
- #define PRSCVL(x) ((x) << 6)
- #define ADC_INPUT(x) ((x) << 3)
- #define ADC_START (1 << 0)
- #define ADC_ENDCVT (1 << 15)
- // ADCTSC寄存器
- #define UD_SEN (1 << 8)
- #define DOWN_INT (UD_SEN*0)
- #define UP_INT (UD_SEN*1)
- #define YM_SEN (1 << 7)
- #define YM_HIZ (YM_SEN*0)
- #define YM_GND (YM_SEN*1)
- #define YP_SEN (1 << 6)
- #define YP_EXTVLT (YP_SEN*0)
- #define YP_AIN (YP_SEN*1)
- #define XM_SEN (1 << 5)
- #define XM_HIZ (XM_SEN*0)
- #define XM_GND (XM_SEN*1)
- #define XP_SEN (1 << 4)
- #define XP_EXTVLT (XP_SEN*0)
- #define XP_AIN (XP_SEN*1)
- #define XP_PULL_UP (1 << 3)
- #define XP_PULL_UP_EN (XP_PULL_UP*0)
- #define XP_PULL_UP_DIS (XP_PULL_UP*1)
- #define AUTO_PST (1 << 2)
- #define CONVERT_MAN (AUTO_PST*0)
- #define CONVERT_AUTO (AUTO_PST*1)
- #define XP_PST(x) (x << 0)
- #define NOP_MODE 0
- #define X_AXIS_MODE 1
- #define Y_AXIS_MODE 2
- #define WAIT_INT_MODE 3
- /* 设置进入等待中断模式,XP_PU,XP_Dis,XM_Dis,YP_Dis,YM_En
- * (1)对于S3C2410,位[8]只能为0,所以只能使用下面的wait_down_int,
- * 它既等待Pen Down中断,也等待Pen Up中断
- * (2)对于S3C2440,位[8]为0、1时分别表示等待Pen Down中断或Pen Up中断
- */
- /* 进入"等待中断模式",等待触摸屏被按下 */
- #define wait_down_int() { ADCTSC = DOWN_INT | XP_PULL_UP_EN | \
- XP_AIN | XM_HIZ | YP_AIN | YM_GND | \
- XP_PST(WAIT_INT_MODE); }
- /* 进入"等待中断模式",等待触摸屏被松开 */
- #define wait_up_int() { ADCTSC = UP_INT | XP_PULL_UP_EN | XP_AIN | XM_HIZ | \
- YP_AIN | YM_GND | XP_PST(WAIT_INT_MODE); }
- /* 进入自动(连续) X/Y轴坐标转换模式 */
- #define mode_auto_xy() { ADCTSC = CONVERT_AUTO | XP_PULL_UP_DIS | XP_PST(NOP_MODE); }
- /*
- * 使用查询方式读取A/D转换值
- * 输入参数:
- * ch: 模拟信号通道,取值为0~7
- */
- static int ReadAdc(int ch)
- {
- // 选择模拟通道,使能预分频功能,设置A/D转换器的时钟 = PCLK/(49+1)
- ADCCON = PRESCALE_EN | PRSCVL(49) | ADC_INPUT(ch);
- // 清除位[2],设为普通转换模式
- ADCTSC &= ~(1<<2);
- // 设置位[0]为1,启动A/D转换
- ADCCON |= ADC_START;
- // 当A/D转换真正开始时,位[0]会自动清0
- while (ADCCON & ADC_START);
- // 检测位[15],当它为1时表示转换结束
- while (!(ADCCON & ADC_ENDCVT));
- // 读取数据
- return (ADCDAT0 & 0x3ff);
- }
- /*
- * 测试ADC
- * 通过A/D转换,测量可变电阻器的电压值
- */
- void Test_Adc(void)
- {
- float vol0, vol1;
- int t0, t1;
- printf("\n\rMeasuring the voltage of AIN0 and AIN3, press any key to exit\n\r");
- while (!awaitkey(1000000)) // 串口无输入,则不断测试
- {
- vol0 = ((float)ReadAdc(0)*3.3)/1024.0; // 计算电压值
- vol1 = ((float)ReadAdc(3)*3.3)/1024.0; // 计算电压值
- t0 = (vol0 - (int)vol0) * 1000; // 计算小数部分, 本代码中的printf无法打印浮点数
- t1 = (vol1 - (int)vol1) * 1000; // 计算小数部分, 本代码中的printf无法打印浮点数
- printf("AIN0 = %d.%-3dV AIN3 = %d.%-3dV\r", (int)vol0, t0, (int)vol1, t1);
- }
- printf("\n\r");
- }
- /*
- * INT_TC的中断服务程序
- * 当触摸屏被按下时,进入自动(连续) X/Y轴坐标转换模式;
- * 当触摸屏被松开时,进入等待中断模式,再次等待INT_TC中断
- */
- static void Isr_Tc(void)
- {
- if (ADCDAT0 & 0x8000)
- {
- printf("\n\rStylus Up!!\n\r");
- wait_down_int(); /* 进入"等待中断模式",等待触摸屏被按下 */
- }
- else
- {
- printf("\n\rStylus Down: ");
- mode_auto_xy(); /* 进入自动(连续) X/Y轴坐标转换模式 */
-
- /* 设置位[0]为1,启动A/D转换
- * 注意:ADCDLY为50000,PCLK = 50MHz,
- * 要经过(1/50MHz)*50000=1ms之后才开始转换X坐标
- * 再经过1ms之后才开始转换Y坐标
- */
- ADCCON |= ADC_START;
- }
-
- // 清INT_TC中断
- SUBSRCPND |= BIT_SUB_TC;
- SRCPND |= BIT_ADC;
- INTPND |= BIT_ADC;
- }
- /*
- * INT_ADC的中断服务程序
- * A/D转换结束时发生此中断
- * 先读取X、Y坐标值,再进入等待中断模式
- */
- static void Isr_Adc(void)
- {
- // 打印X、Y坐标值
- printf("\n\rxdata = %4d, ydata = %4d\r\n", (int)(ADCDAT0 & 0x3ff), (int)(ADCDAT1 & 0x3ff));
- /* 判断是S3C2410还是S3C2440 */
- if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
- { // S3C2410
- wait_down_int(); /* 进入"等待中断模式",等待触摸屏被松开 */
- }
- else
- { // S3C2440
- wait_up_int(); /* 进入"等待中断模式",等待触摸屏被松开 */
- }
- // 清INT_ADC中断
- SUBSRCPND |= BIT_SUB_ADC;
- SRCPND |= BIT_ADC;
- INTPND |= BIT_ADC;
- }
- void ISR(void)
- {
- if (SUBSRCPND & BIT_SUB_TC)
- Isr_Tc();
- if (SUBSRCPND & BIT_SUB_ADC)
- Isr_Adc();
- }
- /*
- * 测试触摸屏,打印触点坐标
- */
- void Test_Ts(void)
- {
- //isr_handle_array[ISR_ADC_OFT] = AdcTsIntHandle; // 设置ADC中断服务程序
- INTMASK &= ~BIT_ADC; // 开启ADC总中断
- INTSUBMSK &= ~(BIT_SUB_TC); // 开启INT_TC中断,即触摸屏被按下或松开时产生中断
- INTSUBMSK &= ~(BIT_SUB_ADC); // 开启INT_ADC中断,即A/D转换结束时产生中断
-
- // 使能预分频功能,设置A/D转换器的时钟 = PCLK/(49+1)
- ADCCON = PRESCALE_EN | PRSCVL(49);
- /* 采样延时时间 = (1/3.6864M)*50000 = 13.56ms
- * 即按下触摸屏后,再过13.56ms才采样
- */
- ADCDLY = 50000;
- wait_down_int(); /* 进入"等待中断模式",等待触摸屏被按下 */
- printf("\n\rTouch the screem to test, press any key to exit\n\r");
- getc();
- // 屏蔽ADC中断
- INTSUBMSK |= BIT_SUB_TC;
- INTSUBMSK |= BIT_SUB_ADC;
- INTMASK |= BIT_ADC;
- }
六、运行
以下为能直接运行的二进制文件,下载到Nand Flash Black0 直接以Nand Flash运行。
阅读(1981) | 评论(0) | 转发(0) |