1. 程式人生 > >飛思卡爾微控制器KEA128之ADC學習

飛思卡爾微控制器KEA128之ADC學習

這個ADC模組的操作模式其實也比較簡單。

首先就是配置,羅列一下該配置什麼吧

ADICLK     ADC模組的輸入時鐘選擇。是匯流排時鐘,匯流排時鐘2分頻還是外部的

ADIV         對上面的時鐘再分頻後就可以給ADC的核心模組使用了。

MODE        選擇8/10/12位轉換

ADLSMP  短還是長時間取樣。不設定的話預設是短

ADLPC    高速還是低功耗,低功耗的話會慢一些,不設定的話預設是高速

AIEN      使能不使能中斷啊,預設不使能

ADCO      連續轉換功能,預設單次。單次的話在一次取樣完成後,要再一次選擇通道才能開始下一次轉換。

ADTRG    軟體觸發啟動轉換還是硬體觸發。預設是軟體

ACFE     比較功能是否開啟,預設關閉。比較功能就是說你設定一個值,只有取樣得到的值比這個值大或者小才會進中斷,不然就一直取樣。

 

ACFGT   這個是配合上面比較功能,進一步設定是比設定值大還是小才觸發中斷,預設於

REFSEL  基準電壓的選擇。是選擇VREFH/VREFL還是VDDA/VSSA。預設VREFH/VREFL

ADC_APCTL1 這個很重要,ADC總共有十六個通道,每個通道對應一個引腳。這個暫存器就相當於在配置說要使用哪個通道。這個暫存器低十六位是可以用的,一個位對應一個通道。

HTRGMASKE            

HTRGMASKSEL 這兩個暫存器是為了硬體觸發準備的,如果你不用硬體觸發,保持預設值就是了

ADC_CV

這個暫存器是儲存比較值的,還記得上面有個暫存器使能比較功能嗎

AFDEP  FIFO深度,可以是0即禁用FIFO或者是1就是2級,2就是3級以此類推最大可以8級。這個也很重要。

ASCANE  FIFO掃描模式開啟和關閉。預設關閉,暫時沒摸清楚什麼是掃描模式

 

配置了一大堆,該講講怎麼用這個ADC了。

你在設定完上面這一堆暫存器後,ADC就算初始化完成了,如果使用庫函式的話,就是在配置結構體裡把上面這些功能配置給填好了,可以呼叫Init函數了。

接下來講Init完之後該幹啥才能啟動ADC

我配置的軟體觸發,就是預設的情況下啦。

你配置完之後,ADC就在等著你選擇通道,外部的有十六個通道AD0~AD15,內部的有五個,有地、溫度、氣隙,VREFH,VREFL。這些個內部通道就是專用的,你不能改用途,不能說把溫度通道改用成外部或者其他功能。

你通過設定ADCH,選擇通道後ADC就會開始轉換,如果你開了比較功能取樣後會自動比較,沒有的話就只是取樣,取樣完成後COCO標誌就會置1,如果使能中斷,就會進中斷,然後你就可以通過ADC_R這個暫存器把取樣結果讀走,COCO標誌你就不用管了,你讀ADC_R的時候系統就會自動幫你把COCO清零的啦。如果你開了連續轉換功能,那麼這個時候你就可以走了,去幹別的事,等下一次取樣完成,如果你沒開連續,那麼在你讀完ADC_R的值後,你還要再設定一次ADCH的值,告訴ADC模組接下來要採哪個通道,不然的話ADC就不鳥你了自己休息去。

如果ADC就這麼簡單,好像功能太少了,如果我有好幾個通道要採,豈不是每讀一次ADC_R就要設定一下下一個通道,還得判斷下一個通道該誰了。太麻煩了,所以系統還給你個增強型功能,FIFO。系統裡FIFO有兩個,一個FIFO存通道號,一個FIFO存取樣值,這兩FIFO的深度必須是一致的,暫存器裡也只有一個地方設定FIFO深度,沒有說通道號FIFO深度,取樣值FIFO深度這種設定,就一個FIFO深度。

有了FIFO深度該怎麼用呢,普通情況下在你Init之後要選擇通道,ADC才開始轉換,有了FIFO這操作順序還是一樣的,只不過,這個時候你可以連續設定幾次通道,系統會自動把你設定的值存到FIFO裡,比如說你對ADCH寫0x01,然後寫0x02,最後寫0X03,系統會把這三個值順序寫到FIFO裡,這裡需要注意的是你設定的FIFO深度跟你寫通道號的次數要保持一次,意思就是說不能你設定FIFO深度是5,然後寫通道號的時候你只連續寫了三個,這樣ADC是不會啟動取樣的,會一直等你寫滿5個才啟動。FIFO的好處就是,比如說你設定FIFO深度是5,那麼只有5個通道都取樣完了COCO才會置1,才會進中斷,讀的時候還是讀ADC_R的值,只不過像設定通道號那樣,你可以連續讀幾次,用FIFO的時候要注意了,FIFO的意思就是first in first out,你連續寫通道號的時候假如說順序是這樣的,5號,6號,3號,那麼你連續讀ADC_R出來的值的順序就是5號,6號,3號。一定要記得順序,不然亂了可別怪我。

剛剛上面講的這個FIFO的功能是你有幾個通道需要取樣,用FIFO幫你全取樣完了你才進中斷一次性取出來。那麼另外一種用FIFO的想法是,我就有一個通道需要取樣,我不想採一次就進一次中斷讀取樣值,能不能用FIFO一次幫我取樣幾個值,取樣完了我再去中斷裡一次性讀出來。我想這個功能應該就是上面我沒摸頭的FIFO掃描模式吧。

void ADC_Module_Init()
{
    ADC_ConfigType  sADC_Config = {0};
    sADC_Config.u8ClockDiv = ADC_ADIV_DIVIDE_4;
    sADC_Config.u8ClockSource = CLOCK_SOURCE_BUS_CLOCK;
    sADC_Config.u8Mode = ADC_MODE_12BIT;
    sADC_Config.sSetting.bIntEn = 1;   //使能中斷
    sADC_Config.u8FiFoLevel = ADC_FIFO_LEVEL4;
//    sADC_Config.sSetting.bFiFoScanModeEn=1;
    sADC_Config.u16PinControl |= 0x08;//使能AD3引腳的AD取樣功能
    ADC_SetCallBack(ADC_CallBack);
    ADC_Init( ADC, &sADC_Config);
    ADC_SetChannel(ADC,ADC_CHANNEL_AD22_TEMPSENSOR);
    ADC_SetChannel(ADC,ADC_CHANNEL_AD29_VREFH);
    ADC_SetChannel(ADC,ADC_CHANNEL_AD23_BANDGAP);
    ADC_SetChannel(ADC,ADC_CHANNEL_AD3);
	
}
void ADC_CallBack(void)
{
    uint8 i;
	//when read the result register,COCO can reset automatic
	while( !ADC_IsFIFOEmptyFlag(ADC) )	//wait read all data in FIFO
	{
        TempsensorBuffer[Index] = ADC_ReadResultReg(ADC);      //這幾個陣列都是static性質
        VrefhBuffer[Index] = ADC_ReadResultReg(ADC);
        BandgapBuffer[Index] = ADC_ReadResultReg(ADC);
		LightsensorBuffer[Index] = ADC_ReadResultReg(ADC);
        Index++;                        //這個Index也是static
 
	}
   if (Index == (MAXBUFFSIZE-1))
   {
        ADC_Calculate();                //儲存完一組AD值後就要進行一次演算法
   }
    u8Adc_Converted_Completed_Flag = 1;
    ADC_SetChannel(ADC,ADC_CHANNEL_AD22_TEMPSENSOR);
    ADC_SetChannel(ADC,ADC_CHANNEL_AD29_VREFH);
    ADC_SetChannel(ADC,ADC_CHANNEL_AD23_BANDGAP);
    ADC_SetChannel(ADC,ADC_CHANNEL_AD3);
}

void ADC_Calculate()                //這裡用了最簡單的平均值演算法,還可以使用中間值濾波法
{
    UINT8 i;
    UINT32 tmp=0;
    for (i=0;i