加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權(quán)保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • 一、問題描述
    • 二、問題復(fù)現(xiàn)
    • 三、問題定位
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

RC電路竟然影響GPIO邊沿中斷?(上)

08/12 09:22
1035
閱讀需 18 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家分享的是i.MXRT1050在GPIO上增加RC延時電路后導(dǎo)致邊沿中斷誤觸發(fā)問題探析

前段時間有一個 RT1052 客戶反饋了一個有趣的問題,他們設(shè)計得是一個帶 LCD 屏交互的應(yīng)用,應(yīng)用以官方 SDK 里的 lvgl_demo_widgets_bm 例程為基礎(chǔ)。當(dāng)客戶在這個例程基礎(chǔ)上增加了 GPIO 輸入邊沿中斷檢測,并且硬件上給 GPIO 增加了 RC 延時電路后,發(fā)現(xiàn)邊沿中斷觸發(fā)得不太準(zhǔn)確,這是怎么回事?今天痞子衡帶大家還原現(xiàn)場:

一、問題描述

客戶做得硬件改動很簡單,在 GPIO_AD_B1_04 引腳和 GPIO_AD_B1_10 引腳之間加了如下的 RC 延時電路。GPIO_AD_B1_04 上產(chǎn)生得是 500Hz 的方波(既可以是 GPIO 模塊輸出,也可以去掉 R290 后直接接信號發(fā)生器),這個方波經(jīng)過 RC 電路之后輸出給 GPIO_AD_B1_10,然后通過其輸入邊沿中斷來檢測電平變化,并且在每個邊沿中斷里都翻轉(zhuǎn)一次 GPIO_AD_B1_11 電平。

代碼改動也足夠簡單,只需要在 SDK_2_15_000_EVKB-IMXRT1050boardsevkbimxrt1050lvgl_exampleslvgl_demo_widgets_bm 工程里添加 test_gpio_irq() 函數(shù)調(diào)用即可(這里假定 GPIO_AD_B1_04 上的方波是由外部信號發(fā)生器提供的):

void?GPIO1_Combined_16_31_IRQHandler(void)
{
????//?檢測到?GPIO_AD_B1_10?邊沿
????if?((GPIO1->ISR?&?(1U?<<?26))?&&?(GPIO1->IMR?&?(1U?<<?26)))
????{
????????GPIO_PortClearInterruptFlags(GPIO1,?1U?<<?26);
????????//?翻轉(zhuǎn)?GPIO_AD_B1_11?電平
????????GPIO_PortToggle(GPIO1,?1?<<?27);
????????__DSB();
????}
}

void?config_rc_in_gpio(void)
{
????//?配置?GPIO_AD_B1_10?為邊沿中斷輸入檢測模式
????gpio_pin_config_t?in_config?=?{?kGPIO_DigitalInput,?1,?kGPIO_NoIntmode?};
????IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_10_GPIO1_IO26,?1);
????IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_10_GPIO1_IO26,?0x011030U);
????GPIO_PinInit(GPIO1,?26,?&in_config);
????GPIO_SetPinInterruptConfig(GPIO1,?26,?kGPIO_IntRisingOrFallingEdge);
????EnableIRQ(GPIO1_Combined_16_31_IRQn);
????GPIO_PortEnableInterrupts(GPIO1,?1U?<<?26);
}

void?config_user_out_gpio(void)
{
????//?配置?GPIO_AD_B1_11?為普通輸出模式
????gpio_pin_config_t?out_config?=?{?kGPIO_DigitalOutput,?1,?kGPIO_NoIntmode?};
????IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_11_GPIO1_IO27,?0);
????GPIO_PinInit(GPIO1,?27,?&out_config);
????GPIO_PinWrite(GPIO1,?27,?0U);
}

void?test_gpio_irq(void)
{?
????config_rc_in_gpio();
????config_user_out_gpio();
}

如果 GPIO_AD_B1_10 邊沿中斷檢測無誤,那么輸出的 GPIO_AD_B1_11 信號應(yīng)該是和原始輸入 GPIO_AD_B1_04 完全同頻的方波,而事實上客戶用示波器抓到的 GPIO_AD_B1_11 信號偶爾會出現(xiàn)如下情況,很顯然有邊沿中斷誤觸發(fā)的情況發(fā)生:

并且更有趣的是,這樣的測試僅在 lvgl_demo_widgets_bm 工程里能復(fù)現(xiàn),而在普通 input_interrupt 工程下沒有任何問題。

    Note1:在 lvgl_demo_widgets_bm 工程下出現(xiàn)的 GPIO 邊沿中斷誤觸發(fā)問題僅在增加 RC 電路時存在。Note2:在普通 input_interrupt 工程下即使增加 RC 電路,GPIO 邊沿中斷誤觸發(fā)問題也不存在。

二、問題復(fù)現(xiàn)

理論上分析 GPIO_AD_B1_10 引腳輸入的信號頻率是 500Hz,那么其邊沿中斷應(yīng)該是每 1ms 產(chǎn)生一次,而從上一節(jié)客戶抓取的 GPIO_AD_B1_11 實際信號反推,似乎有時候邊沿中斷在 10us 內(nèi)連續(xù)產(chǎn)生了兩次。

為了從軟件角度抓到這個中斷誤觸發(fā)現(xiàn)象,痞子衡稍微改了一下代碼,將 GPIO_AD_B1_04 上信號改為軟件輸出(在 SysTick 1ms 一次的中斷響應(yīng)里翻轉(zhuǎn)電平),并且用了兩個計數(shù)器 s_outputPinEdgeCount、s_inputRcPinIrqCount 來分別記錄 GPIO_AD_B1_04、GPIO_AD_B1_10 邊沿次數(shù)。如果邊沿中斷觸發(fā)無誤的話,這兩個計數(shù)器的值應(yīng)該是永遠相等的,但是實際跑了一段時間后發(fā)現(xiàn) s_inputRcPinIrqCount 會超過 s_outputPinEdgeCount,并且隨著時間累積,差距會越來越大。這說明邊沿中斷誤觸發(fā)現(xiàn)象是一直存在的。

volatile?uint32_t?s_inputRcPinIrqCount???=?0;
volatile?uint32_t?s_outputPinEdgeCount?=?0;

void?GPIO1_Combined_16_31_IRQHandler(void)
{
????//?檢測到?GPIO_AD_B1_10?邊沿
????if?((GPIO1->ISR?&?(1U?<<?26))?&&?(GPIO1->IMR?&?(1U?<<?26)))
????{
????????GPIO_PortClearInterruptFlags(GPIO1,?1U?<<?26);
????????//?計數(shù)?GPIO_AD_B1_10?邊沿
????????s_inputRcPinIrqCount++;
????????__DSB();
????}
}

void?config_rc_out_gpio(void)
{
????//?配置?GPIO_AD_B1_04?為普通輸出模式
????IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_04_GPIO1_IO20,?0);
????GPIO_PinInit(GPIO1,?20,?&out_config);
????GPIO_PinWrite(GPIO1,?20,?0U);
}

void?test_gpio_irq(void)
{?
????config_rc_in_gpio();
????config_rc_out_gpio();
}

void?SysTick_Handler(void)
{
????//?計數(shù)?GPIO_AD_B1_04?邊沿
????s_outputPinEdgeCount++;
????GPIO_PortToggle(GPIO1,?1?<<?20);
????__DSB();

????//?原應(yīng)用代碼省略
}

三、問題定位

描述至此,你的第一反應(yīng)到底是哪里出了問題?痞子衡想你可能會覺得罪魁禍?zhǔn)资?RC 延時電路,它將標(biāo)準(zhǔn)的方波上升、下降過程變得平緩,導(dǎo)致信號電壓處于臨界區(qū)的時間變長(極端情況下,對于高頻信號,可能會導(dǎo)致其一直處于臨界區(qū)),這個可能會影響 GPIO 電平跳變判定。既如此,我們先翻看一下 RT1050 的 datasheet,找到如下 GPIO DC 參數(shù)表,其高、低電平判定值分別是 70%、30% NVCC_XXXX,此外備注里說明了只要電平變化是單調(diào)的(隨著時間單向增大或減?。肄D(zhuǎn)換時間范圍在 0.1ns - 1s 內(nèi)均會被認(rèn)定為有效跳變。

這時候我們再根據(jù) RC 延時電路標(biāo)準(zhǔn)時間常數(shù)公式 t = RC * 來推算(V1 電源電壓、V0 電容初始時刻電壓、 為 t 時刻電容電壓)。如果 NVCC 為 3.3V,那么上升沿時從 0V 充電到 2.31V 的時間是 12us,顯然這個 12us 充電時間對于 500Hz 的方波來說不足以影響其跳變判定。

有沒有方法能抓住這個異常邊沿中斷發(fā)生時,GPIO_AD_B1_10 信號當(dāng)時的波形狀態(tài)呢?當(dāng)然是可以的,我們可以再修改一下邊沿中斷處理函數(shù)代碼,在里面計算兩次中斷之間的 Tick 間隔,如果間隔 Tick 低于一定值,說明是誤觸發(fā),此時翻轉(zhuǎn)一次 GPIO_AD_B1_11 電平用作標(biāo)記。

volatile?uint32_t?s_systickCurVal?=?0;
volatile?uint32_t?s_systickLastVal?=?0;
volatile?uint32_t?s_systickCurCount?=?0;
volatile?uint32_t?s_systickLastCount?=?0;
volatile?uint32_t?s_systickDeltaVal;

uint32_t?s_systickReloadVal?=?0;

void?GPIO1_Combined_16_31_IRQHandler(void)
{
?????/*?clear?the?interrupt?status?*/
????if?((GPIO1->ISR?&?(1U?<<?26))?&&?(GPIO1->IMR?&?(1U?<<?26)))
????{
????????s_systickCurVal?=?SysTick->VAL;
????????s_systickCurCount?=?s_outputPinEdgeCount;
????????GPIO_PortClearInterruptFlags(GPIO1,?1U?<<?26);
????????//?計算兩次中斷之間的?Tick?間隔
????????s_systickDeltaVal?=?(s_outputPinEdgeCount?-?s_systickLastCount)?*?s_systickReloadVal?+?s_systickLastVal?-?s_systickCurVal;
????????s_systickLastVal?=?s_systickCurVal;
????????s_systickLastCount?=?s_systickCurCount;
????????//?當(dāng)間隔?Tick?低于一定值時,說明是誤觸發(fā),此時翻轉(zhuǎn)一次?GPIO_AD_B1_11?電平
????????if?(s_systickDeltaVal?<=?s_systickReloadVal?/?2)
????????{
????????????GPIO_PortToggle(GPIO1,?1?<<?27);
????????}
????????__DSB();
????}
}

int?main(void)
{
????//?應(yīng)用代碼省略...
????test_gpio_irq();

????s_systickReloadVal?=?SystemCoreClock?/?(LVGL_TICK_MS?*?1000U);
????s_inputRcPinIrqCount???=?0;
????s_systickLastVal?=?s_systickReloadVal;

????DEMO_SetupTick();
????//?應(yīng)用代碼省略...
}

如果用示波器以 GPIO_AD_B1_11 跳變?yōu)橛|發(fā)信號(ch2),即能看到案發(fā)現(xiàn)場 GPIO_AD_B1_10 狀態(tài)(ch1),確實我們看到充放電時間內(nèi)出現(xiàn)了短時脈沖波干擾(glitch),這個脈沖導(dǎo)致了電平變化不是單調(diào)的,因而產(chǎn)生了 GPIO 中斷誤觸發(fā)。本篇僅是定位問題,下一篇我們會具體分析這個 glitch 是如何產(chǎn)生的!

至此,i.MXRT1050在GPIO上增加RC延時電路后導(dǎo)致邊沿中斷誤觸發(fā)問題探析(上篇)痞子衡便介紹完畢了,掌聲在哪里~~~

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風(fēng)險等級 參考價格 更多信息
AFBR-5803ATZ 1 Foxconn Transceiver, 1270nm Min, 1380nm Max, 125Mbps(Tx), 125Mbps(Rx), ST Connector, Through Hole Mount, ROHS COMPLIANT, SIP-9
$205.36 查看
TJA1043TK/1Y 1 NXP Semiconductors TJA1043 - High-speed CAN transceiver SON 14-Pin

ECAD模型

下載ECAD模型
$1.96 查看
TJA1021T/10/C,118 1 NXP Semiconductors TJA1021 - LIN 2.1/SAE J2602 transceiver SOIC 8-Pin

ECAD模型

下載ECAD模型
$1.44 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

碩士畢業(yè)于蘇州大學(xué)電子信息學(xué)院,目前就職于恩智浦(NXP)半導(dǎo)體MCU系統(tǒng)部門,擔(dān)任嵌入式系統(tǒng)應(yīng)用工程師。痞子衡會定期分享嵌入式相關(guān)文章