AD电阻转换---那些年我们一起玩mini2440(arm9)裸机
ADC驱动程序设计
ADC:模/数转换器。
一种将模拟信号转换成数字信号的装置;
DAC:数/模转换器。
一种将数字信号转换成模拟信号的装置。
模拟信号转换为数值信号的步骤:
1. 取值;
2. 量化;
3. 编码;
S3C2440ADC
S3C2440芯片内部共有8路A/D转换通道AIN0~AIN7,但是转换器只有一个。
转换精度为10位,故转换后的值最小时会接近0,最大时会接近1024.
最大的转换率在2.5MHZ转换时钟下能达到500KSPS(每秒采样5000千次)
在常见的设计中,如mini2440开发板,一般AIN4、AIN5、AIN6、AIN7被用作了四线电阻触摸的YM、YP、XM、XP通道;剩余的AIN0~3被引出,其中AIN0直接和一个可调电阻W1连接。
师:AIN4、AIN5、AIN6、AIN7给触摸屏用的;
AIN0用于可调电阻
(这样电压就可以作为一路模拟信号进行转换)
ADC驱动流程:1.初始化à2.启动à3.转换结束à4.读取转换值
一.ADC初始化
A.选择转换通道- B.设置转换频率
怎么判断开始转换了?用一个whlie循环,查询ENABLE_START是否变成0
怎么判断转换完成了?不断查询ECFLG是否为1
读取转换值
pasting
- #define GLOBAL_CLK 1
- #include <stdlib.h>
- #include <string.h>
- #include "def.h"
- #include "option.h"
- #include "2440addr.h"
- #include "2440lib.h"
- #include "2440slib.h"
- #include "mmu.h"
- #include "profile.h"
- #include "memtest.h"
- #define ADC_FREQ 2500000
- //#define ADC_FREQ 1250000
- volatile U32 preScaler;
- void adc_init(void);
- int ReadAdc(int channel);
- static void cal_cpu_bus_clk(void);
- void Set_Clk(void);
- void beep_init(void);
- void beep_run(void);
- /*************************************************
- Function name: delay
- Parameter : times
- Description : 延时函数
- Return : void
- Argument : void
- Autor & date : Daniel
- **************************************************/
- void delay(int times)
- {
- int i,j;
- for(i=0;i<times;i++)
- for(j=0;j<400;j++);
- }
- /*************************************************
- Function name: Main
- Parameter : void
- Description : 主功能函数
- Return : void
- Argument : void
- Autor & date : Daniel
- **************************************************/
- void Main(void)
- {
- int a0=0,tmp;
- int Scom=0;
- Set_Clk();
- Uart_Init(0,115200);
- Uart_Select(Scom);
- adc_init();
- while(1)
- {
- a0=ReadAdc(0);
- Uart_Printf( "AIN0: %04d\n", a0);
- delay(1000) ;
- }
- }
- /*************************************************
- Function name: adc_init()
- Parameter : int channel
- Description : adc初始化
- Return : void
- Argument : void
- Autor & date : Daniel
- **************************************************/
- void adc_init(void)
- {
- int channel=0; //AIN0,对应开发板上W1可调电阻
- preScaler = ADC_FREQ;
- Uart_Printf("ADC conv,freq. = %dHz\n",preScaler);
- preScaler = 50000000/ADC_FREQ - 1; //PCLK=50M 我们要得到ADC_FREQ=2500000
- Uart_Printf("PRSCVL=PCLK/ADC_FREQ - 1=%d\n",preScaler);
- /*AD转换频率设置,最大频率为2.5MHz*/
- rADCCON = (1<<14)|(preScaler<<6)|(channel<<3); //setup channel 1<<14使能预分频器 (preScaler<<6)预分频值 channel<<3模拟通道选择
- delay(1000);
- }
- /*************************************************
- Function name: ReadAdc(int channel)
- Parameter : int channel
- Description : 获取AD 转换后的值
- Return : int
- Argument : void
- Autor & date : Daniel
- **************************************************/
- int ReadAdc(int channel)
- {
- /*开启AD转换*/
- rADCCON |= 0x01; //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 );//读取转换后的值
- }
- /*************************************************
- Function name: Set_Clk()
- Parameter : void
- Description : 设置CPU的时钟频率
- Return : void
- Argument : void
- Autor & date : Daniel
- **************************************************/
- void Set_Clk(void)
- {
- int i;
- U8 key;
- U32 mpll_val = 0 ;
- i = 2 ; //don't use 100M!
- //boot_params.cpu_clk.val = 3;
- switch ( i ) {
- case 0: //200
- key = 12;
- mpll_val = (92<<12)|(4<<4)|(1);
- break;
- case 1: //300
- key = 13;
- mpll_val = (67<<12)|(1<<4)|(1);
- break;
- case 2: //400
- key = 14;
- mpll_val = (92<<12)|(1<<4)|(1);
- break;
- case 3: //440!!!
- key = 14;
- mpll_val = (102<<12)|(1<<4)|(1);
- break;
- default:
- key = 14;
- mpll_val = (92<<12)|(1<<4)|(1);
- break;
- }
- //init FCLK=400M, so change MPLL first
- ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3); //set the register--rMPLLCON
- ChangeClockDivider(key, 12); //the result of rCLKDIVN [0:1:0:1] 3-0 bit
- cal_cpu_bus_clk(); //HCLK=100M PCLK=50M
- }
- /*************************************************
- Function name: cal_cpu_bus_clk
- Parameter : void
- Description : 设置PCLK\HCLK\FCLK的频率
- Return : void
- Argument : void
- Autor & date : Daniel
- **************************************************/
- static void cal_cpu_bus_clk(void)
- {
- static U32 cpu_freq;
- static U32 UPLL;
- U32 val;
- U8 m, p, s;
- val = rMPLLCON;
- m = (val>>12)&0xff;
- p = (val>>4)&0x3f;
- s = val&3;
- //(m+8)*FIN*2 不要超出32位数!
- FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100; //FCLK=400M FIN=12000000
- val = rCLKDIVN;
- m = (val>>1)&3;
- p = val&1;
- val = rCAMDIVN;
- s = val>>8;
- switch (m) {
- case 0:
- HCLK = FCLK;
- break;
- case 1:
- HCLK = FCLK>>1;
- break;
- case 2:
- if(s&2)
- HCLK = FCLK>>3;
- else
- HCLK = FCLK>>2;
- break;
- case 3:
- if(s&1)
- HCLK = FCLK/6;
- else
- HCLK = FCLK/3;
- break;
- }
- if(p)
- PCLK = HCLK>>1;
- else
- PCLK = HCLK;
- if(s&0x10)
- cpu_freq = HCLK;
- else
- cpu_freq = FCLK;
- val = rUPLLCON;
- m = (val>>12)&0xff;
- p = (val>>4)&0x3f;
- s = val&3;
- UPLL = ((m+8)*FIN)/((p+2)*(1<<s));
- UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;
- }