ARM ADC程序設計
模擬信號:時間上連續,數值上也連續,數字信號:時間和數值上是離散的,而離散信號只有0或1。
S3c2440內部有8路A/D轉換通道AIN0~AIN7,但是轉換器只有一個,從8路中選出一路進行轉換,轉換精度10位(0~1024-1),轉換頻率500kSPS(每秒採樣500次),在mini2440,AIN4,5,6,7,用作了觸摸屏通道YM,YP,XM,XP,AIN0連接可變電阻
AIN0爲模擬信號輸入通道,電壓作爲模擬信號輸入,ADC程序流程:
初始化---->啓動(CPU告訴AD硬件做某項工作)---->轉換結束(查詢,中斷)----->讀取轉換值
初始化:選擇轉換通道----->設置轉換頻率 SEL_MUX選擇轉換通道,PRSCEN爲1表示使用分頻器做頻率設置,PRSCVL爲具體分頻器的值,ECFLG轉換結束。
數據在0--9位
使用可調電阻作爲輸入ADC轉換程序:
#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);
void delay(int times) {
int i,j;
for(i=0;i<times;i++)
for(j=0;j<400;j++);
}
void Main(void) {
int a0=0,tmp;
int Scom=0;
Set_Clk(); //PCLK在AD轉換中用到,ADC轉換所需要的時鐘頻率
beep_init();
Uart_Init(0,115200);
Uart_Select(Scom);
Uart_Printf("\nHello World!\n");
adc_init(); //
//tmp=a0;
while(1) {
a0=ReadAdc(0); //啓動轉換
// if(a0 != tmp)
Uart_Printf( "AIN0: %04d\n", a0);
// tmp=a0;
delay(1000) ;
}
}
void adc_init(void) {
int channel=0; //AIN0,對應開發板上W1可調電阻,選擇0號通道
//設置時鐘頻率
preScaler = ADC_FREQ;
Uart_Printf("ADC conv,freq. = %dHz\n",preScaler);
preScaler = 50000000/ADC_FREQ - 1; //PCLK=50M
//50M除以所需頻率爲預分頻係數
Uart_Printf("PRSCVL=PCLK/ADC_FREQ - 1=%d\n",preScaler);
/*AD轉換頻率設置,最大頻率爲2.5MHz*/
rADCCON = (1<<14)|(preScaler<<6)|(channel<<3); //setup channel
delay(1000);
}
int ReadAdc(int channel) {
/*開啓AD轉換,把第0位改爲1,然後檢查是否爲0,變爲0後才真正轉換 */
rADCCON |= 0x01; //start ADC
while(rADCCON & 0x1); //check if Enable_start is low
while(!(rADCCON & 0x8000)); //判斷第15位是否爲1,完成轉換
return ( (int)rADCDAT0 & 0x3ff ); //data寄存器最後十位
}
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
}
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;
}
void beep_init(void) {
rGPBCON &= ~(0x3<<0);
rGPBCON |= (0x1<<0);
}
void beep_run(void) {
rGPBDAT |= (0x1<<0);
delay(5000);
rGPBDAT &= (0x0<<0);
delay(5000);
}