S3C2440包含一个8通道A/D转换器,有10位分辨率下面简要介绍一下S3C2440中ADC的用法:
用到的寄存器:
ADCCON:ADC控制寄存器
ADCDAT0:ADC转换数据寄存器
SUBSRCPND:次级源挂起寄存器
INTSUBMSK:中断次级屏蔽寄存器
SRCPND:源挂起寄存器
INTPND:中断挂起寄存器
INTMSK:中断屏蔽寄存器
ADCCON:AD控制寄存器
ADCDAT0:AD转换数据寄存器
1,首先设置控制寄存器ADCCON的相应位来选择频率和通道:
- rADCCON = (1<<14)|(preScaler<<6)|(ch<<3); //setup channel,分频使能,写入分频值,选择通道
其中PreScaler是预分频值,决定
A/D转换器频率 = 50MHz/(49+1) = 1MHz
如图:
2,然后启动AD并等待启动位ADCCON[0]清0和转换结束位ADCCON[15]置1:
- rADCCON|=0x1; //start ADC开始转换
-
- while(rADCCON & 0x1); //check if Enable_start is low等待启动位清零,转换启动结束
- while(!(rADCCON & 0x8000)); //check if EC(End of Conversion) flag is high等待转换结束
3,最后读取相应通道转换结果寄存器的值:
寄存器ADCDAT0的低10位用于存储A/D转换后的数据。
- return ( (int)rADCDAT0 & 0x3ff );//返回0~9位的采样值,0~1023
- a0=ReadAdc(0); //对应开发板上W1可调电阻
- a1=ReadAdc(1); //对应开发板上W2可调电阻
OK!
有必要介绍一下寄存器ADCCON:
如下图:
寄存器ADCCON的第15位用于标识A/D转换是否结束。第14位用于使能是否进行预分频,而第6位到第13位则存储的是预分频数值,因为A/D转换的速度不能太快,所以要通过预分频处理才可以得到正确的A/D转换速度,如我们想要得到A/D转换频率为1MHz,则预分频的值应为49。第3位到第5位表示的是A/D转换的通道选择。第2位可以实现A/D转换的待机模式。第1位用于是否通过读取操作来使能A/D转换的开始。第0位则是在第1位被清零的情况下用于开启A/D转换。
ADC.c源码,可实现超级终端显示adc0,adc1转换后的结果0-1023,adc0可通过滑动变阻器调节输入电压
- //====================================================================
- // File Name : Adc.c
- // Function : S3C2410 ADC Test
- // Program : Kang, Weon Tark
- // Date : May 22, 2002
- // Version : 0.0
- // History
- // 0.0 : Programming start (March 29,2002) -> KWT
- // ADC Test -> May 15, 2002 SOP
- //====================================================================
-
- #include "def.h"
- #include "option.h"
- #include "2440addr.h"
- #include "2440lib.h"
- #include "2440slib.h"
-
- #define REQCNT 100 //May 08, 2002 SOP
- #define ADC_FREQ 2500000
- //#define ADC_FREQ 1250000
- //#define LOOP 1
- #define LOOP 10000
-
- volatile U32 preScaler;
-
- //==================================================================================
- int ReadAdc(int ch)
- {
- int i;
- static int prevCh=-1;
-
- rADCCON = (1<<14)|(preScaler<<6)|(ch<<3); //setup channel,分频使能,写入分频值,选择通道
-
- if(prevCh!=ch)
- {
- rADCCON = (1<<14)|(preScaler<<6)|(ch<<3); //setup channel
- for(i=0;i<LOOP;i++); //delay to set up the next channel切换通道要等待一段时间?
- prevCh=ch;
- }
- rADCCON|=0x1; //start ADC开始转换
-
- while(rADCCON & 0x1); //check if Enable_start is low等待启动位清零,转换启动结束
- while(!(rADCCON & 0x8000)); //check if EC(End of Conversion) flag is high等待转换结束
-
- return ( (int)rADCDAT0 & 0x3ff );//返回0~9位的采样值,0~1023
- }
-
- //==================================================================================
- void Test_Adc(void)
- {
- int a0=0, a1; //Initialize variables
- U32 rADCCON_save = rADCCON;//保存原值
-
- Uart_Printf( "ADC INPUT Test, press ESC key to exit !\n" ) ;
-
- preScaler = ADC_FREQ;
- Uart_Printf("ADC conv. freq. = %dHz\n",preScaler);
- preScaler = 50000000/ADC_FREQ -1; //PCLK:50.7MHz//preScaler =1转换频率freq=50M/(1+1)=25M,最大不超过PCLK的1/5?
-
- Uart_Printf("PCLK/ADC_FREQ - 1 = %d\n",preScaler);
-
- while( Uart_GetKey() != ESC_KEY )
- {
- a0=ReadAdc(0); //对应开发板上W1可调电阻
- a1=ReadAdc(1); //对应开发板上W2可调电阻
-
- Uart_Printf( "AIN0: %04d, AIN1: %04d\n", a0, a1 );
- Delay( 500 ) ;
- }
-
- //rADCCON=(0<<14)|(19<<6)|(7<<3)|(1<<2); //stand by mode to reduce power consumption
- rADCCON = rADCCON_save;//恢复原值
- Uart_Printf("\nrADCCON = 0x%x\n", rADCCON);
- }
效果图:
完整工程文件可在这里下载。