PDB(可編程延遲模塊)提供從觸發(fā)源到ADC的硬件觸發(fā)器輸入的可控延遲,觸發(fā)源來(lái)自內(nèi)部、外部觸發(fā)器或可編程間隔時(shí)鐘。PDB可以選擇性的提供脈沖輸出,脈沖輸出可用作CMP(比較器)中的采樣窗口。
CKS32K148有兩個(gè)PDB,每個(gè)PDB模塊有4個(gè)通道、一次脈沖輸出和1個(gè)觸發(fā)器,每個(gè)通道有8個(gè)預(yù)觸發(fā)器。因此,一個(gè)PDB模塊一次可以觸發(fā)ADC多達(dá)32個(gè)輸入通道。
結(jié)構(gòu)與框圖
CKS32K148系列MCU的PDB框圖如下所示,大體可劃分成六個(gè)部分。
圖1 AIPS結(jié)果框圖
①觸發(fā)源選擇部分:PDB的觸發(fā)源選擇通過(guò)PDB_SC寄存器中的TRGSEL位確定,其可以是軟件觸發(fā)-通過(guò)向PDB_SC寄存器的SWTRIG位寫入1實(shí)現(xiàn);也可以是外部觸發(fā)源-如外部觸發(fā)引腳Trigger_In0。
②計(jì)數(shù)器部分:PDB的時(shí)鐘源經(jīng)過(guò)PDB_SC寄存器中的PRESCALER位選擇的分配系數(shù)進(jìn)行分頻,通過(guò)PDB_SC寄存器中的MULT位選擇倍頻系數(shù),之后計(jì)數(shù)器開始工作。計(jì)數(shù)器當(dāng)前計(jì)數(shù)值可以通過(guò)計(jì)數(shù)器寄存器PDB_CNT讀取。計(jì)數(shù)器的周期通過(guò)PDB_MOD模數(shù)寄存器指定,當(dāng)計(jì)數(shù)器達(dá)到該值時(shí),將被重置為零。
計(jì)數(shù)器的控制邏輯通過(guò)PDB_SC寄存器中的CONT位實(shí)現(xiàn):當(dāng)該位無(wú)效時(shí),計(jì)數(shù)器達(dá)到周期值時(shí)被重置為零,直至下一次觸發(fā)出現(xiàn)后重新開始計(jì)數(shù);當(dāng)該位有效時(shí),計(jì)數(shù)器達(dá)到周期值時(shí)自動(dòng)重新開始。
③預(yù)觸發(fā)器輸出部分:PDB通道n(n = 0 ~ 3)預(yù)觸發(fā)器輸出0~m(m最大值為7),每個(gè)預(yù)觸發(fā)輸出連接ADC硬件觸發(fā)選擇和硬件觸發(fā)輸入,預(yù)觸發(fā)可以使用PDB通道預(yù)觸發(fā)使能(CHn1C1[EN[m]])啟用或禁止。
為方便敘述,定義觸發(fā)器輸入事件為:在所選觸發(fā)輸入源上檢測(cè)到上升沿,或者選擇軟件觸發(fā)器并將軟件觸發(fā)器位(SC[SWTRIG])寫入1。預(yù)觸發(fā)源輸出對(duì)應(yīng)三種情況:
a)當(dāng)觸發(fā)器輸入事件發(fā)生時(shí),在2個(gè)外圍時(shí)鐘周期后置位預(yù)觸發(fā)器m。這種情況下,需要清零CHnC1[TOS[m]]。
b)使用通道延遲寄存器CHnDLYm指定延遲值,當(dāng)計(jì)數(shù)器計(jì)數(shù)值達(dá)到該值時(shí),經(jīng)過(guò)兩個(gè)外圍時(shí)鐘周期后置位預(yù)觸發(fā)器m。這種情況下,需要置位CHnC1[TOS[m]]。
c)PDB配置成背靠背操作,背靠背操作使得ADC轉(zhuǎn)換完成觸發(fā)下一個(gè)PDB通道預(yù)觸發(fā)和觸發(fā)輸出。換句話說(shuō),預(yù)觸發(fā)m-1觸發(fā)ADC轉(zhuǎn)換完成之后產(chǎn)生的Ack信號(hào)會(huì)使預(yù)觸發(fā)輸出m置位兩個(gè)外圍時(shí)鐘周期。這種情況下,需要置位CHnC1[BB[m]]。
④觸發(fā)輸出部分:預(yù)觸發(fā)輸出用于在實(shí)際觸發(fā)器發(fā)生之前對(duì)ADC塊進(jìn)行預(yù)處理。當(dāng)ADC接收到觸發(fā)器的上升沿時(shí),ADC將根據(jù)預(yù)觸發(fā)器決定的先決條件開始轉(zhuǎn)換,PDB通道n的預(yù)觸發(fā)和觸發(fā)輸出如下圖所示。
圖2 預(yù)觸發(fā)輸出和觸發(fā)輸出
如果PDB通道n的預(yù)觸發(fā)器被置位時(shí)置位一個(gè)新的預(yù)觸發(fā)器m,那么會(huì)產(chǎn)生PDB通道序列錯(cuò)誤標(biāo)志(CHnS[ERR[m]]置位)。如果使能PDB序列錯(cuò)誤中斷,則產(chǎn)生序列錯(cuò)誤中斷。序列錯(cuò)誤通常是由于延遲m設(shè)置的太短,并且預(yù)觸發(fā)m在先前觸發(fā)的ADC轉(zhuǎn)換之前置位。例如預(yù)觸發(fā)m-1置位并觸發(fā)ADC轉(zhuǎn)換這一過(guò)程還未結(jié)束時(shí),此時(shí)預(yù)觸發(fā)m置位則會(huì)產(chǎn)生序列錯(cuò)誤。
⑤脈沖輸出部分:PDB可以產(chǎn)生可配置寬度的脈沖輸出。當(dāng)PDB計(jì)數(shù)器達(dá)到PonDLY[DLY1]中設(shè)置的值時(shí),脈沖輸出拉高;當(dāng)PDB計(jì)數(shù)器達(dá)到PonDLY[DLY2]中設(shè)置的值時(shí),脈沖輸出拉低。PonDLY[DLY2]可以設(shè)置為大于或者小于PonDLY[DLY1]中的值。
⑥中斷部分:中斷延遲寄存器PDB_IDLY指定PDB中斷的延遲值,可以用來(lái)在PDB周期的某個(gè)點(diǎn)安排一個(gè)獨(dú)立的中斷。如果使能中斷(PDB_SC[PDBIE]置位),當(dāng)計(jì)數(shù)器等于IDLY時(shí),將產(chǎn)生一個(gè)PDB中斷。
PDB延遲觸發(fā)ADC多通道實(shí)驗(yàn)
CKS32K148 PDB最常用的功能就是為ADC提供硬件觸發(fā)源,我們這里展示PDB延遲觸發(fā)ADC功能。即前文介紹過(guò)預(yù)觸發(fā)輸出的b)情況-使用通道延遲寄存器CHnDLYm指定延遲值,當(dāng)計(jì)數(shù)器計(jì)數(shù)值達(dá)到該值時(shí),經(jīng)過(guò)兩個(gè)外圍時(shí)鐘周期后置位預(yù)觸發(fā)器m。
前面介紹過(guò),每個(gè)PDB模塊有4個(gè)通道、1個(gè)觸發(fā)器和一次脈沖輸出,每個(gè)通道有8個(gè)預(yù)觸發(fā)輸出,這里我們只用到1個(gè)通道、1個(gè)觸發(fā)器和8個(gè)預(yù)觸發(fā)輸出,用來(lái)觸發(fā)ADC的8個(gè)輸入通道。為了避免出現(xiàn)PDB序列錯(cuò)誤,需要確保預(yù)觸發(fā)器之間有足夠的延遲。
編程要點(diǎn)如下:
1. 使能相關(guān)外設(shè)時(shí)鐘,如ADC、PDB等,并配置用到的引腳
status = CLOCK_DRV_Init(&clockMan1_InitConfig0);
DEV_ASSERT(status == STATUS_SUCCESS);
status=PINS_DRV_Init(NUM_OF_CONFIGURED_PINS0, g_pin_mux_InitConfigArr0);
DEV_ASSERT(status == STATUS_SUCCESS);
2. 配置ADC結(jié)構(gòu)體參數(shù)、輸入通道。此處僅展示前2個(gè)通道配置函數(shù)
ADC_DRV_ConfigConverter(INST_ADC_0, &ADC_0_ConvConfig0);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB_0, 0U, &pdb_1_adcTrigConfig0);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB_0, 0U, &pdb_1_adcTrigConfig1);
/*** ADC初始化結(jié)構(gòu)體***/
const adc_converter_config_t ADC_0_ConvConfig0 = {
.clockDivide = ADC_CLK_DIVIDE_4,
.sampleTime = 255U,
.resolution = ADC_RESOLUTION_12BIT,
.inputClock = ADC_CLK_ALT_1,
.trigger = ADC_TRIGGER_HARDWARE,
.pretriggerSel = ADC_PRETRIGGER_SEL_PDB,
.triggerSel = ADC_TRIGGER_SEL_PDB,
.dmaEnable = false,
.voltageRef = ADC_VOLTAGEREF_VREF,
.continuousConvEnable = false,
.supplyMonitoringEnable = false
};
關(guān)鍵在于配置ADC為硬件觸發(fā)方式,預(yù)觸發(fā)源和觸發(fā)源均為PDB,禁止連續(xù)模式。配置ADC8個(gè)輸入通道:指定外部/內(nèi)部輸入通道,每個(gè)通道均使能轉(zhuǎn)換完成中斷。
3.PDB計(jì)數(shù)器配置和使能
PDB_DRV_Init(INST_PDB_0, &pdb_1_timerConfig0);
PDB_DRV_Enable(INST_PDB_0);
/*** PDB計(jì)數(shù)器初始化結(jié)構(gòu)體***/
const pdb_timer_config_t pdb_1_timerConfig0 = {
.loadValueMode = PDB_LOAD_VAL_IMMEDIATELY,
.seqErrIntEnable = false,
.clkPreDiv = PDB_CLK_PREDIV_BY_128,
.clkPreMultFactor = PDB_CLK_PREMULT_FACT_AS_10,
.triggerInput = PDB_SOFTWARE_TRIGGER,
.continuousModeEnable = true,
.dmaEnable = false,
.intEnable = false,
.instanceBackToBackEnable = false,
};
參數(shù)loadValueMode:用于選擇加載模式,控制PDB操作時(shí)間的寄存器(如模數(shù)寄存器、中斷延遲寄存器等)可能需要同時(shí)變得有效。這些寄存器被寫入的值會(huì)先更新到它們的緩沖區(qū),因此加載模式就用來(lái)選擇達(dá)到何種條件時(shí)緩沖區(qū)的值更新到內(nèi)部寄存器的情況。這里我們選擇默認(rèn)值,即立即更新緩沖區(qū)的加載值。
參數(shù)seqErrIntEnable:用于設(shè)置PDB序列錯(cuò)誤中斷的使能與否。這里我們關(guān)閉使能。
參數(shù)clkPreDiv:用于選擇預(yù)分頻系數(shù)。這里我們?cè)O(shè)置成128分頻。
參數(shù)clkPreMultFactor:用于選擇倍頻系數(shù)。這里我們?cè)O(shè)置成10倍頻。
參數(shù)triggerInput:用于選擇觸發(fā)輸入源。這里選擇軟件觸發(fā)方式。
參數(shù)continuousModeEnable:用于選擇是否使能連續(xù)模式。配置使能連續(xù)模式,所以當(dāng)計(jì)數(shù)器達(dá)到周期值時(shí),自動(dòng)從零開始重新計(jì)數(shù)。
參數(shù)dmaEnable:用于選擇是否使能DMA。如果使能DMA,當(dāng)PDB計(jì)數(shù)器達(dá)到中斷延遲寄存器PDB_IDLY指定的延遲值時(shí),PDB中斷標(biāo)志置位,PDB請(qǐng)求一個(gè)DMA傳輸。這里我們禁止DMA。
參數(shù)intEnable:用于選擇是否使能計(jì)數(shù)器中斷。只有當(dāng)DMA失能時(shí)才會(huì)產(chǎn)生計(jì)數(shù)器延遲中斷。這里我們禁止計(jì)數(shù)器中斷。
參數(shù)instanceBackToBackEnable:用于選擇是否使能背靠背操作,對(duì)應(yīng)前面介紹的預(yù)觸發(fā)輸出情況c)。這里我們禁止背靠背操作。
4. PDB計(jì)數(shù)器周期值配置
calculateIntValue(&pdb_1_timerConfig0, PDLY_TIMEOUT, &delayValue0);
PDB_DRV_SetTimerModulusValue(INST_PDB_0, (uint32_t) delayValue0);
PDLY_TIMEOUT為用戶設(shè)置的周期值,我們?cè)O(shè)為1s。calculateIntValue函數(shù)可將用戶設(shè)置的計(jì)數(shù)器周期根據(jù)計(jì)數(shù)器的時(shí)鐘頻率轉(zhuǎn)換成對(duì)應(yīng)的十六進(jìn)制數(shù),之后將該十六進(jìn)制數(shù)寫入PDB_MOD寄存器中。
5. PDB預(yù)觸發(fā)輸出配置(此處僅展示通道0的前兩個(gè)預(yù)觸發(fā)輸出函數(shù)配置)
PDB_DRV_ConfigAdcPreTrigger(INST_PDB_0, 0U, &pdb_1_adcTrigConfig0);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB_0, 0U, &pdb_1_adcTrigConfig1);
/*** 預(yù)觸發(fā)輸出配置結(jié)構(gòu)體***/
const pdb_adc_pretrigger_config_t pdb_1_adcTrigConfig0 = {
.adcPreTriggerIdx = 0U,
.preTriggerEnable = true,
.preTriggerOutputEnable = true,
.preTriggerBackToBackEnable = false
};
上述參數(shù)分別為:預(yù)觸發(fā)輸出序號(hào)(0~7),是否使能預(yù)觸發(fā),是否使能預(yù)觸發(fā)輸出以及是否使能背靠背操作。其余預(yù)觸發(fā)輸出除輸出序號(hào)不同外其他配置均相同。
6. 設(shè)置預(yù)觸發(fā)延遲值
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 0UL, 0UL,(uint32_t) delayValue0 / 9);
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 0UL, 1UL,(uint32_t) delayValue0 / 8);
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 0UL, 2UL,(uint32_t) delayValue0 / 7);
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 0UL, 3UL,(uint32_t) delayValue0 / 6);
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 0UL, 4UL,(uint32_t) delayValue0 / 5);
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 0UL, 5UL,(uint32_t) delayValue0 / 4);
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 0UL, 6UL,(uint32_t) delayValue0 / 3);
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 0UL, 7UL,(uint32_t) delayValue0 / 2);
前面我們?cè)O(shè)置PDB周期為1s,因此預(yù)觸發(fā)輸出1和預(yù)觸發(fā)輸出0之間的延遲為1 * (1/8 - 1/9) = 13.88ms。同理,預(yù)觸發(fā)2和預(yù)觸發(fā)1之間的延遲為17.925ms,預(yù)觸發(fā)3和預(yù)觸發(fā)2之間的延遲為11.9ms,預(yù)觸發(fā)4和預(yù)觸發(fā)3之間的延遲為16.65ms,預(yù)觸發(fā)5和預(yù)觸發(fā)4之間的延遲為25ms,預(yù)觸發(fā)6和預(yù)觸發(fā)5之間的延遲為41.65ms,預(yù)觸發(fā)7和預(yù)觸發(fā)6之間的延遲為83.3ms。
7.執(zhí)行加載命令,使能軟件觸發(fā)
PDB_DRV_LoadValuesCmd(INST_PDB_0);
PDB_DRV_SoftTriggerCmd(INST_PDB_0);
執(zhí)行加載命令后,先前設(shè)置好的相關(guān)寄存器值(PDB_MOD、PDB_CHnDLYm)立即從緩沖區(qū)更新到內(nèi)部寄存器。軟件觸發(fā)PDB后,計(jì)數(shù)器開始工作。
8. 使能ADC中斷
INT_SYS_InstallHandler(ADC0_IRQn, &ADC0_IRQHandler, (isr_t*) 0);
INT_SYS_EnableIRQ(ADC0_IRQn);
9. 編寫中斷服務(wù)函數(shù):在中斷中獲取ADC結(jié)果,同時(shí)翻轉(zhuǎn)IO電平
void ADC0_IRQHandler(void)
{
ADC_DRV_GetChanResult(INST_ADC_0, 0UL, (uint16_t *)&adcRawValue0[0]);
ADC_DRV_GetChanResult(INST_ADC_0, 1UL, (uint16_t *)&adcRawValue0[1]);
ADC_DRV_GetChanResult(INST_ADC_0, 2UL, (uint16_t *)&adcRawValue0[2]);
ADC_DRV_GetChanResult(INST_ADC_0, 3UL, (uint16_t *)&adcRawValue0[3]);
ADC_DRV_GetChanResult(INST_ADC_0, 4UL, (uint16_t *)&adcRawValue0[4]);
ADC_DRV_GetChanResult(INST_ADC_0, 5UL, (uint16_t *)&adcRawValue0[5]);
ADC_DRV_GetChanResult(INST_ADC_0, 6UL, (uint16_t *)&adcRawValue0[6]);
ADC_DRV_GetChanResult(INST_ADC_0, 7UL, (uint16_t *)&adcRawValue0[7]);
PINS_DRV_TogglePins(LED_PORT, 1 << LED0);
adc0ConvDone = true;
}
至此,PDB多通道延遲觸發(fā)ADC的例程基本講述完畢。程序編譯后燒錄至開發(fā)板,PDB預(yù)觸發(fā)每置位并觸發(fā)ADC轉(zhuǎn)換完成后即進(jìn)入中斷翻轉(zhuǎn)IO電平。用戶根據(jù)抓取到的IO電平波形即可驗(yàn)證延遲值是否與預(yù)期一致。此外,如果想要查看ADC轉(zhuǎn)換值,用戶可使能串口,通過(guò)adc0ConvDone標(biāo)志位在主函數(shù)while循環(huán)中打印輸出結(jié)果,此處不再詳細(xì)展開。
-
mcu
+關(guān)注
關(guān)注
146文章
17540瀏覽量
355445 -
模塊
+關(guān)注
關(guān)注
7文章
2755瀏覽量
48396 -
adc
+關(guān)注
關(guān)注
99文章
6577瀏覽量
546998 -
比較器
+關(guān)注
關(guān)注
14文章
1717瀏覽量
107869 -
觸發(fā)器
+關(guān)注
關(guān)注
14文章
2026瀏覽量
61570
原文標(biāo)題:MCU微課堂|CKS32K148 PDB
文章出處:【微信號(hào):中科芯MCU,微信公眾號(hào):中科芯MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
MCU微課堂|CKS32F4xx系列產(chǎn)品時(shí)鐘配置
中科芯CKS32K148系列MCU的外設(shè)橋模塊解析

中科芯CKS32F030K6T6 高性能32位RISC內(nèi)核MCU 程序兼容STM32F030K6T6
怎么看待CKS32單片機(jī)能取代ST32單片機(jī)問(wèn)題
中科芯STM32F103系列資料合集免費(fèi)下載

中科芯智能家居系統(tǒng)應(yīng)用方案解析
中科芯推出面向CKS32位MCU的編程調(diào)試工具
中科芯高性能MCU產(chǎn)品獲TüV萊茵認(rèn)證
中科芯與IAR共建生態(tài)合作,IAR集成開發(fā)環(huán)境全面支持CKS32系列MCU

中科芯與IAR共建生態(tài)合作,IAR集成開發(fā)環(huán)境全面支持CKS32系列MCU
中科芯CKS32K148 MCU SCG時(shí)鐘工作頻率范圍和寄存器設(shè)置

評(píng)論