簡介
在S32K中,不同的芯片型號支持的ADC通道不同,S32K144UAVLL有兩個ADC,每個ADC有12位、10位、8位和6位可選,每個ADC有16個外部通道。學習ADC的第一步是要掌握ADC的功能框圖,對ADC的工作過程和編程過程有個整體的瞭解。
ADC功能框圖
對ADC的配置主要涉及三種寄存器,控制狀態寄存器、觸發寄存器和數據寄存器。控制狀態寄存器主要有SC2
、SC3
、CFG1
和CFG2
;觸發寄存器主要有SC1
和SC2
;數據寄存器主要有Rn
。
電壓輸入範圍
ADC的輸入電壓範圍爲:,ADC的輸入範圍取決於4個參考電源 。
ADC的電壓輸入範圍取決於4個參考電源,我們在設計原理圖的時候一般把 和 接地,把 和 接3.3V,可以得到ADC的輸入範圍是0~3.3V。在設計原理圖時,應該把ADC設置爲可以配置成外用輸入電壓參考源,以備不時之需,如下圖所示。
如上圖所示,有三個選項。
- 焊接上R103,拆掉R99,R109和D7,電壓參考源爲VDD_MCU,一般爲3.3V
- 焊接上D7和R99,拆掉R103和R109,R99進行分壓之後爲3V
- 焊接上R109,拆掉R103,R99和D7。這裏的是外部輸入電壓引腳,可以配置爲外部電壓參考源
時鐘配置
可以選擇4個時鐘源ALTCLKx
之一來作爲ADC模塊的時鐘源。ADC具有多個時鐘源。 選擇取決於配置PCC_ADCn[PCS]
。 分頻器的配置應使ADC轉換時鐘頻率在ADC要求的有效範圍內(請參見數據手冊)。如下圖所示爲ADC的時鐘分配圖。
如圖所示,ADC的時鐘源輸入通過PCC_ADCn[PCS]
來選擇SOSCDIV2_CLK
、SIRCDIV2_CLK
、FIRCDIV2_CLK
和SPLLDIV2_CLK
四種,然後經過ADC_CFG1[ADIV]
來時鐘分頻,最後產生ADC的輸入時鐘ADCK
,ADCK
由數據手冊可得,最大50MHZ,最小2MHZ,典型值爲40MHZ,如果超過最大頻率,ADC的轉換結果會變得不可靠。ADC時鐘設置流程如下:
- 設置
PCC_ADCn[PCS]
:選擇時鐘源 - 設置
ADC_CFG1[ADICLK]
:選擇時鐘輸入 - 設置
ADC_CFG1[ADIV]
:選擇時鐘分頻
轉換時間
數據手冊顯示,ADC的轉換時間取決於:
ADC_CFG2[SAMPLTS]
確定的採樣時間- MCU的Bus總線時鐘頻率
ADC_CFG1[MODE]
確定的轉換模式- 即ADC的轉換時鐘頻率
由數據手冊可得,ADC的總轉換時間=採樣相位時間(SMPLTS設置的再+1)+保持相位(1個ADC週期)+比較相位時間(8位模式=20個ADC週期,10位模式=24個ADC週期,12位模式=28個ADC週期)+單個或第一個連續時間加法器(5個ADC週期+5個總線時鐘週期)
例:設置BUS時鐘爲40MHZ,ADC時鐘選擇40MHZ,12位ADC,採樣週期選擇255個ADC週期,計算ADC的一次轉換時間爲:
觸發設置
ADC觸發設置主要包括寄存器SC2
和SC1
。ADC支持軟件觸發和硬件觸發兩種,軟件觸發就是在ADC轉換完畢之後產生中斷;在硬件觸發方面,ADC模塊具有可選的異步硬件轉換觸發器ADHWT
,主要通過PDB來觸發。觸發設置可見PDB觸發ADC。設置ADC_SC2[ADTRG]
來選擇是硬件觸發還是軟件觸發。觸發方式的設置流程如下:
- 設置
ADC_SC2[ADTRG]
:選擇觸發方式 - 設置
ADC_SC1n[ADCH]
:選擇ADC通道 - 如果上一步使用了具有硬件交錯功能的通道,則需要設置
SIM_CHIPCTL[ADC_INTERLEAVE_EN]
位 - 設置
ADC_SC1n[AIEN]
:開啓中斷觸發(軟件觸發模式下)
獲得ADC數據
最後轉換成功後,ADC的轉換結果會被存放在ADC_Rn
寄存器,ADC_Rn
寄存器對應的是ADC_SC1n
寄存器,比如ADC_SC1A
的數據會存放在ADC_RA
,ADC_SC1B
的數據會存放在ADC_RB
,以此類推。
在不同的轉換位數下,ADC_Rn
寄存器的數據位數也不同,如下圖所示。
注:ADC_Rn
寄存器是隻讀的
電壓轉換
模擬電壓經過ADC轉換後,是一個相對精度的數字值,如果通過串口以16進制打印出來的話,可讀性比較差,故需要把數字電壓轉換爲模擬電壓,也可以根據實際的模擬電壓(用萬用表測)對比,看看轉換是否準確。
在設計原理圖時,一般會把ADC的輸入電壓範圍定在0~3.3V,若設置的ADC爲12位,那麼12位滿量程對應的就是3.3V,12位滿量程對應的數字值是: 。數值0對應的就是0V。如果轉換後的數值爲X,X對應的模擬電壓爲Y,那麼:
實例:ADC觸發中斷
功能概述
- 平臺:S32K144
現在使用S32K144的ADC0通道8,軟件觸發模式下,轉換結束後觸發中斷。
編程順序
- 初始化ADC0的時鐘
- 初始化ADC0的位數
- 選擇ADC0的通道,開啓中斷
- 如果該通道有硬件交錯功能,需要選擇是哪個ADC通道
- 選擇軟件觸發
- NVIC開啓ADC中斷
// ADC初始化函數
void ADC0_Init(void)
{
PCC->PCCn[PCC_PORTA_INDEX] |= PCC_PCCn_CGC_MASK; /* Enable clock for PORTA */
SIM->CHIPCTL |= (1 << 2); /* 具有硬件交錯功能,選擇PTB13 */
PCC->PCCn[PCC_ADC0_INDEX] &= ~PCC_PCCn_CGC_MASK;
PCC->PCCn[PCC_ADC0_INDEX] |= PCC_PCCn_PCS(6); /* PCS=6: 選擇內核時鐘80MHZ */
PCC->PCCn[PCC_ADC0_INDEX] |= PCC_PCCn_CGC_MASK;
ADC0->CFG1 = ADC_CFG1_ADIV(2) | /* ADIV=2:輸入內核時鐘兩分頻=40MHZ */
ADC_CFG1_MODE(1) | /* MODE=1: 12位ADC */
ADC_CFG1_ADICLK(0); /* ADICLK=0: 默認選擇PCC分配的時鐘 */
ADC0->SC1[0] = ADC_SC1_AIEN_MASK | /* AIEN=1: 開啓中斷觸發 */
ADC_SC1_ADCH(8); /* ADCH=8: 序號0選擇通道8 */
ADC0->SC2 |= ADC_SC2_ADTRG(0); /* ADTRG=0: 開啓軟件觸發 */
ADC0->SC3 = 0;
S32_NVIC->ICPR[1] = 1 << (39 % 32); /* 註冊ADC0中斷 */
S32_NVIC->ISER[1] = 1 << (39 % 32); /* 使能ADC0中斷 */
S32_NVIC->IP[39] = 0xA0; /* 優先級爲10 */
}
/*
* \brief adcChan通道開啓一次ADC轉換
*
* \param adcChan 需要進行ADC轉換的通道
*
*/
void convertAdcChan(uint16_t adcChan)
{
ADC0->SC1[0] &= ~ADC_SC1_ADCH_MASK; /* Clear prior ADCH bits */
ADC0->SC1[0] = ADC_SC1_ADCH(adcChan); /* Initiate Conversion*/
}
/*
* \brief ADC轉換判斷函數
*
* \return >0 轉換已完成
* \return =0 轉換未完成
*
*/
uint8_t adc_complete(void)
{
return((ADC0->SC1[0] & ADC_SC1_COCO_MASK) >> ADC_SC1_COCO_SHIFT);
}
/*
* \brief ADC值轉換函數
*
* \return 返回轉換後的ADC電壓值
*
*/
uint32_t read_adc_chx(uint8_t ChanIndex)
{
uint16_t adc_result = 0;
adc_result = ADC0->R[ChanIndex];
/* For SW trigger mode, R[0] is used */
return(uint32_t)((5000 * adc_result) / 0xFFF);
/* Convert result to mv for 0-5V range */
}
void ADC0_IRQHandler(void)
{
adcRawValue1 = read_adc_chx(0);
adcRawValue2 = read_adc_chx(1);
adcConvDone = true;
}