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
讀取轉換值:
#defineGLOBAL_CLK1#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 1250000volatile 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: delayParameter : timesDescription : 延時函數Return : voidArgument : voidAutor & date : Daniel**************************************************/void delay(int times){ int i,j; for(i=0;i<times;i++) for(j=0;j<400;j++);}/*************************************************Function name: MainParameter : voidDescription : 主功能函數Return : voidArgument : voidAutor & 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 channelDescription : adc初始化Return : voidArgument : voidAutor & 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=2500000Uart_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 channelDescription : 擷取AD 轉換後的值Return : intArgument : voidAutor & date : Daniel**************************************************/ int ReadAdc(int channel){/*開啟AD轉換*/rADCCON |= 0x01; //start ADCwhile(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 : voidDescription : 設定CPU的時鐘頻率Return : voidArgument : voidAutor & 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://200key = 12;mpll_val = (92<<12)|(4<<4)|(1);break;case 1://300key = 13;mpll_val = (67<<12)|(1<<4)|(1);break;case 2://400key = 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 firstChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3); //set the register--rMPLLCONChangeClockDivider(key, 12); //the result of rCLKDIVN [0:1:0:1] 3-0 bitcal_cpu_bus_clk(); //HCLK=100M PCLK=50M}/*************************************************Function name: cal_cpu_bus_clkParameter : voidDescription : 設定PCLK\HCLK\FCLK的頻率Return : voidArgument : voidAutor & 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=12000000val = 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;elseHCLK = FCLK>>2;break;case 3:if(s&1)HCLK = FCLK/6;elseHCLK = FCLK/3;break;}if(p)PCLK = HCLK>>1;elsePCLK = HCLK;if(s&0x10)cpu_freq = HCLK;elsecpu_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;}