ARM ADC程序設計

ARM ADC程序設計

模擬信號:時間上連續,數值上也連續,數字信號:時間和數值上是離散的,而離散信號只有01

S3c2440內部有8A/D轉換通道AIN0~AIN7,但是轉換器只有一個,從8路中選出一路進行轉換,轉換精度10(0~1024-1),轉換頻率500kSPS(每秒採樣500),在mini2440AIN4,5,6,7,用作了觸摸屏通道YMYPXMXPAIN0連接可變電阻


AIN0爲模擬信號輸入通道,電壓作爲模擬信號輸入,ADC程序流程:

初始化---->啓動(CPU告訴AD硬件做某項工作)---->轉換結束(查詢,中斷)----->讀取轉換值

初始化:選擇轉換通道----->設置轉換頻率 SEL_MUX選擇轉換通道,PRSCEN1表示使用分頻器做頻率設置,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);
}


發佈了56 篇原創文章 · 獲贊 5 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章