Chinaunix首页 | 论坛 | 博客
  • 博客访问: 301980
  • 博文数量: 63
  • 博客积分: 1482
  • 博客等级: 上尉
  • 技术积分: 1185
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-12 19:06
个人简介

hello world!

文章分类

全部博文(63)

分类: LINUX

2011-03-25 15:39:12

一、概要

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- 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- 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

 

  1. CC = arm-linux-gcc
  2. LD = arm-linux-ld
  3. AR = arm-linux-ar
  4. OBJCOPY = arm-linux-objcopy
  5. OBJDUMP = arm-linux-objdump

  6. INCLUDEDIR     := $(shell pwd)/include
  7. CFLAGS         := -Wall -O2
  8. CPPFLAGS     := -nostdinc -I$(INCLUDEDIR)
  9. LDFLASG := -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc

  10. export     CC LD OBJCOPY OBJDUMP INCLUDEDIR CFLAGS CPPFLAGS

  11. objs := start.o main.o uart0_init.o i2c_init.o nand.o framebuffer.o \
  12.         lcdlib.o lcddrv.o lib/libc.a adc_ts.o

  13. adc_ts.bin: $(objs)
  14.     ${LD} -Tmem.lds -o adc_ts_elf $^ ${LDFLASG}
  15.     ${OBJCOPY} -O binary -S adc_ts_elf $@
  16.     ${OBJDUMP} -D -m arm adc_ts_elf > adc_ts.dis
  17.     ${OBJDUMP} -dx adc_ts_elf > memory.map

  18. .PHONY : lib/libc.a
  19. lib/libc.a:
  20.     cd lib; make; cd ..
  21.     
  22. %.o:%.c
  23.     ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

  24. %.o:%.S
  25.     ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

  26. clean:
  27.     make clean -C lib
  28.     rm -f adc_ts.bin adc_ts_elf adc_ts.dis *.o

第10行:nostdinc 不要在标准系统目录中寻找头文件.只搜索`-I'选项指定的目录(以及当前目录,如果合适). 结合使用`-nostdinc'和`-I-'选项,你可以把包含文件搜索限制在显式指定的目录.

第11行:指时Linux系统上的GCC库所在目录本机上。

 

adc_ts.c
  1. /*
  2.  * FILE: adc_ts.c
  3.  * ADC和触摸屏的测试函数
  4.  */

  5. #include <stdio.h>
  6. #include "adc_ts.h"
  7. #include "s3c2440_addr.h"
  8. #include "uart0_init.h"

  9. // ADCCON寄存器

  10. #define PRESCALE_DIS (0 << 14)
  11. #define PRESCALE_EN (1 << 14)
  12. #define PRSCVL(x) ((x) << 6)
  13. #define ADC_INPUT(x) ((x) << 3)
  14. #define ADC_START (1 << 0)
  15. #define ADC_ENDCVT (1 << 15)

  16. // ADCTSC寄存器

  17. #define UD_SEN (1 << 8)
  18. #define DOWN_INT (UD_SEN*0)
  19. #define UP_INT (UD_SEN*1)
  20. #define YM_SEN (1 << 7)
  21. #define YM_HIZ (YM_SEN*0)
  22. #define YM_GND (YM_SEN*1)
  23. #define YP_SEN (1 << 6)
  24. #define YP_EXTVLT (YP_SEN*0)
  25. #define YP_AIN (YP_SEN*1)
  26. #define XM_SEN (1 << 5)
  27. #define XM_HIZ (XM_SEN*0)
  28. #define XM_GND (XM_SEN*1)
  29. #define XP_SEN (1 << 4)
  30. #define XP_EXTVLT (XP_SEN*0)
  31. #define XP_AIN (XP_SEN*1)
  32. #define XP_PULL_UP (1 << 3)
  33. #define XP_PULL_UP_EN (XP_PULL_UP*0)
  34. #define XP_PULL_UP_DIS (XP_PULL_UP*1)
  35. #define AUTO_PST (1 << 2)
  36. #define CONVERT_MAN (AUTO_PST*0)
  37. #define CONVERT_AUTO (AUTO_PST*1)
  38. #define XP_PST(x) (x << 0)

  39. #define NOP_MODE 0
  40. #define X_AXIS_MODE 1
  41. #define Y_AXIS_MODE 2
  42. #define WAIT_INT_MODE 3


  43. /* 设置进入等待中断模式,XP_PU,XP_Dis,XM_Dis,YP_Dis,YM_En
  44.  * (1)对于S3C2410,位[8]只能为0,所以只能使用下面的wait_down_int,
  45.  * 它既等待Pen Down中断,也等待Pen Up中断
  46.  * (2)对于S3C2440,位[8]为0、1时分别表示等待Pen Down中断或Pen Up中断
  47.  */
  48. /* 进入"等待中断模式",等待触摸屏被按下 */
  49. #define wait_down_int() { ADCTSC = DOWN_INT | XP_PULL_UP_EN | \
  50.                           XP_AIN | XM_HIZ | YP_AIN | YM_GND | \
  51.                           XP_PST(WAIT_INT_MODE); }
  52. /* 进入"等待中断模式",等待触摸屏被松开 */
  53. #define wait_up_int() { ADCTSC = UP_INT | XP_PULL_UP_EN | XP_AIN | XM_HIZ | \
  54.                           YP_AIN | YM_GND | XP_PST(WAIT_INT_MODE); }

  55. /* 进入自动(连续) X/Y轴坐标转换模式 */
  56. #define mode_auto_xy() { ADCTSC = CONVERT_AUTO | XP_PULL_UP_DIS | XP_PST(NOP_MODE); }


  57. /*
  58.  * 使用查询方式读取A/D转换值
  59.  * 输入参数:
  60.  * ch: 模拟信号通道,取值为0~7
  61.  */
  62. static int ReadAdc(int ch)
  63. {
  64.     // 选择模拟通道,使能预分频功能,设置A/D转换器的时钟 = PCLK/(49+1)

  65.     ADCCON = PRESCALE_EN | PRSCVL(49) | ADC_INPUT(ch);

  66.     // 清除位[2],设为普通转换模式

  67.     ADCTSC &= ~(1<<2);

  68.     // 设置位[0]为1,启动A/D转换

  69.     ADCCON |= ADC_START;

  70.     // 当A/D转换真正开始时,位[0]会自动清0

  71.     while (ADCCON & ADC_START);

  72.     // 检测位[15],当它为1时表示转换结束

  73.     while (!(ADCCON & ADC_ENDCVT));

  74.     // 读取数据

  75.     return (ADCDAT0 & 0x3ff);
  76. }

  77. /*
  78.  * 测试ADC
  79.  * 通过A/D转换,测量可变电阻器的电压值
  80.  */
  81. void Test_Adc(void)
  82. {
  83.     float vol0, vol1;
  84.     int t0, t1;

  85.     printf("\n\rMeasuring the voltage of AIN0 and AIN3, press any key to exit\n\r");
  86.     while (!awaitkey(1000000)) // 串口无输入,则不断测试

  87.     {
  88.         vol0 = ((float)ReadAdc(0)*3.3)/1024.0; // 计算电压值

  89.         vol1 = ((float)ReadAdc(3)*3.3)/1024.0; // 计算电压值

  90.         t0 = (vol0 - (int)vol0) * 1000; // 计算小数部分, 本代码中的printf无法打印浮点数

  91.         t1 = (vol1 - (int)vol1) * 1000; // 计算小数部分, 本代码中的printf无法打印浮点数

  92.         printf("AIN0 = %d.%-3dV AIN3 = %d.%-3dV\r", (int)vol0, t0, (int)vol1, t1);
  93.     }
  94.     printf("\n\r");
  95. }

  96. /*
  97.  * INT_TC的中断服务程序
  98.  * 当触摸屏被按下时,进入自动(连续) X/Y轴坐标转换模式;
  99.  * 当触摸屏被松开时,进入等待中断模式,再次等待INT_TC中断
  100.  */
  101. static void Isr_Tc(void)
  102. {
  103.     if (ADCDAT0 & 0x8000)
  104.     {
  105.         printf("\n\rStylus Up!!\n\r");
  106.         wait_down_int(); /* 进入"等待中断模式",等待触摸屏被按下 */
  107.     }
  108.     else
  109.     {
  110.         printf("\n\rStylus Down: ");

  111.         mode_auto_xy(); /* 进入自动(连续) X/Y轴坐标转换模式 */
  112.     
  113.         /* 设置位[0]为1,启动A/D转换
  114.          * 注意:ADCDLY为50000,PCLK = 50MHz,
  115.          * 要经过(1/50MHz)*50000=1ms之后才开始转换X坐标
  116.          * 再经过1ms之后才开始转换Y坐标
  117.          */
  118.         ADCCON |= ADC_START;
  119.     }
  120.     
  121.     // 清INT_TC中断

  122.     SUBSRCPND |= BIT_SUB_TC;
  123.     SRCPND |= BIT_ADC;
  124.     INTPND |= BIT_ADC;
  125. }


  126. /*
  127.  * INT_ADC的中断服务程序
  128.  * A/D转换结束时发生此中断
  129.  * 先读取X、Y坐标值,再进入等待中断模式
  130.  */
  131. static void Isr_Adc(void)
  132. {
  133.     // 打印X、Y坐标值

  134.     printf("\n\rxdata = %4d, ydata = %4d\r\n", (int)(ADCDAT0 & 0x3ff), (int)(ADCDAT1 & 0x3ff));

  135.     /* 判断是S3C2410还是S3C2440 */
  136.     if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
  137.     { // S3C2410

  138.         wait_down_int(); /* 进入"等待中断模式",等待触摸屏被松开 */
  139.     }
  140.     else
  141.     { // S3C2440

  142.         wait_up_int(); /* 进入"等待中断模式",等待触摸屏被松开 */
  143.     }

  144.     // 清INT_ADC中断

  145.     SUBSRCPND |= BIT_SUB_ADC;
  146.     SRCPND |= BIT_ADC;
  147.     INTPND |= BIT_ADC;
  148. }

  149. void ISR(void)
  150. {
  151.     if (SUBSRCPND & BIT_SUB_TC)
  152.         Isr_Tc();

  153.     if (SUBSRCPND & BIT_SUB_ADC)
  154.         Isr_Adc();    
  155. }

  156. /*
  157.  * 测试触摸屏,打印触点坐标
  158.  */
  159. void Test_Ts(void)
  160. {
  161.     //isr_handle_array[ISR_ADC_OFT] = AdcTsIntHandle; // 设置ADC中断服务程序

  162.     INTMASK &= ~BIT_ADC; // 开启ADC总中断

  163.     INTSUBMSK &= ~(BIT_SUB_TC); // 开启INT_TC中断,即触摸屏被按下或松开时产生中断

  164.     INTSUBMSK &= ~(BIT_SUB_ADC); // 开启INT_ADC中断,即A/D转换结束时产生中断

  165.     
  166.     // 使能预分频功能,设置A/D转换器的时钟 = PCLK/(49+1)

  167.     ADCCON = PRESCALE_EN | PRSCVL(49);

  168.     /* 采样延时时间 = (1/3.6864M)*50000 = 13.56ms
  169.      * 即按下触摸屏后,再过13.56ms才采样
  170.      */
  171.     ADCDLY = 50000;

  172.     wait_down_int(); /* 进入"等待中断模式",等待触摸屏被按下 */

  173.     printf("\n\rTouch the screem to test, press any key to exit\n\r");
  174.     getc();

  175.     // 屏蔽ADC中断

  176.     INTSUBMSK |= BIT_SUB_TC;
  177.     INTSUBMSK |= BIT_SUB_ADC;
  178.     INTMASK |= BIT_ADC;
  179. }
 
六、运行
 
以下为能直接运行的二进制文件,下载到Nand Flash Black0 直接以Nand Flash运行。
 
 
阅读(1944) | 评论(0) | 转发(0) |
0

上一篇:14、(继)LCD控制器-S3C2440

下一篇:动荡的心

给主人留下些什么吧!~~