日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

【.Net Micro Framework PortingKit - 08】GPIO驱动

發布時間:2025/1/21 78 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【.Net Micro Framework PortingKit - 08】GPIO驱动 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

要點亮LED燈或獲得輸入IO的狀態應該是比較容易的,打開端口時鐘,然后讀寫相關的GPIO寄存器就可以了,但是要實現一個輸入中斷,就要費些周折了。

對STM32(Cortex-M3)的芯片,要實現一個GPIO中斷一般需要如下幾步:

1、? 配置時鐘控制器寄存器(RCC)的APB2RSTR,確保對應的GPIOA ~ GPIOG時鐘使能。

2、? 對GPIO寄存器的CRL(或CRH)要設置正確的輸入模式,如浮空輸入模式(對接收IO中斷來說,當然要設置成輸入模式)。

3、? 要通過AFIO寄存器配置中斷的輸入來源,對STM32芯片來說,具有19路EXTI中斷線,其中3路分別連接PVD輸出、RTC鬧鐘事件及USB喚醒事件,剩下的對GPIOA ~ GPIOG 7*16=112個IO點來說,同時只能配置16路IO輸入中斷。

4、? 接下來要配置EXIT寄存器,根據需要來配置是上升沿觸發中斷、還是下降沿觸發中斷或兩者都觸發。

5、? 而后比較重要的是, 要配置NVIC的SETENA寄存器,讓對應的EXTI0、EXTI1、EXTI2、EXTI3、EXTI4、EXTI9_5或EXTI15_10中斷位使能,此外還要配置各中斷的優先級(前提是中斷優先級分組寄存器已配置完畢)。

6、? 最后我們要設置中斷向量表(該向量表要重定位到內存中,以便于動態修改),在EXTI0、EXTI1、EXTI2、EXTI3、EXTI4、EXTI9_5或EXTI15_10對應的位置,放入我們的中斷函數的入口地址。

?

和PC平臺程序開發不同,基本上你每做一步,都可以很直觀的看到你的進展和成果,但對嵌入式開發來說,如果上述幾步有任何一個環節出了問題,你的進展都是零,有時候你會花上一天的時間去反復核實每個寄存器的值是否正確,以期獲得你希望的結果。所以說嵌入式開發是驚喜的型的,要么成,要么不成,一線之隔!

接下來我們說一下GPIO實現的詳細步驟,首先在CortexM3.h頭文件中添加GPIO相關的寄存器描述:

  • struct?CortexM3_GPIO ?
  • ?
  • { ?
  • ?
  • ??static?const?UINT32?c_Base?=?0x40010800; ?
  • ?
  • ??static?const?UINT32?A?=?0; ?
  • ?
  • ??static?const?UINT32?B?=?1; ?
  • ?
  • ??static?const?UINT32?C?=?2; ?
  • ?
  • ??static?const?UINT32?D?=?3; ?
  • ?
  • ??static?const?UINT32?E?=?4; ?
  • ?
  • ??static?const?UINT32?F?=?5;? ?
  • ?
  • ??static?const?UINT32?G?=?6;? ?
  • ?
  • ??static?const?UINT32?GPIO_Mode_NULL?=?0x00; ?
  • ?
  • ??static?const?UINT32?GPIO_Mode_Speed_10MHz?=?0x01; ?
  • ?
  • ??static?const?UINT32?GPIO_Mode_Speed_2MHz?=?0x02; ?
  • ?
  • ??static?const?UINT32?GPIO_Mode_Speed_50MHz?=?0x03; ?
  • ?
  • ??static?const?UINT32?GPIO_Mode_IN_FLOATING?=?0x04; ?
  • ?
  • ????/****/?volatile?UINT32???CRL;??//配置寄存器 ?
  • ?
  • ??/****/?volatile?UINT32???CRH; ?
  • ?
  • ??/****/?volatile?UINT32???IDR;??//數據寄存器 ?
  • ?
  • ??/****/?volatile?UINT32???ODR; ?
  • ?
  • ??/****/?volatile?UINT32???BSRR;?//置位復位寄存器 ?
  • ?
  • ??/****/?volatile?UINT32???BRR;??//復位寄存器 ?
  • ?
  • ??/****/?volatile?UINT32???LCKR;?//鎖定寄存器 ?
  • ?
  • }; ?
  • ?
  • struct?CortexM3_EXTI ?
  • ?
  • { ?
  • ?
  • ??static?const?UINT32?c_Base?=?0x40010400; ?
  • ?
  • ??/****/?volatile?UINT32??IMR; ?
  • ?
  • ??/****/?volatile?UINT32??EMR; ?
  • ?
  • ??/****/?volatile?UINT32??RTSR; ?
  • ?
  • ??/****/?volatile?UINT32??FTSR; ?
  • ?
  • ??/****/?volatile?UINT32??SWIER; ?
  • ?
  • ??/****/?volatile?UINT32??PR; ?
  • ?
  • }; ?
  • ?
  • struct?CortexM3_AFIO ?
  • ?
  • { ?
  • ?
  • ??static?const?UINT32?c_Base?=?0x40010000;?? ?
  • ?
  • ??/****/?volatile?UINT32?EVCR; ?
  • ?
  • ??/****/?volatile?UINT32?MAPR; ?
  • ?
  • ??/****/?volatile?UINT32?EXTICR[4]; ?
  • ?
  • }; ?
  • ?
  • 由于NVIC相關的代碼我們已經在《NVIC中斷處理》說過了,這里就不重復了。

    對.Net Micro Framework的架構來說,要實現如下幾個接口:

    1、CPU_GPIO_Initialize

    2、CPU_GPIO_Uninitialize

    3、CPU_GPIO_Attributes

    4、CPU_GPIO_DisablePin

    5、CPU_GPIO_EnableOutputPin

    6、CPU_GPIO_EnableInputPin

    7、CPU_GPIO_EnableInputPin2

    8、CPU_GPIO_GetPinState

    9、CPU_GPIO_SetPinState

    10、CPU_GPIO_GetPinCount

    11、CPU_GPIO_GetPinsMap

    12、CPU_GPIO_GetSupportedResistorModes

    13、CPU_GPIO_GetSupportedInterruptModes

    14、CPU_GPIO_PinIsBusy

    15、CPU_GPIO_ReservePin

    16、CPU_GPIO_GetDebounce

    17、CPU_GPIO_SetDebounce

    考慮到難易程度和篇幅,我們只介紹CPU_GPIO_Initialize、CPU_GPIO_EnableOutputPin、 CPU_GPIO_EnableInputPin和EXTI_IRQHandler 中斷函數的具體實現。

  • BOOL?GPIO_Driver::Initialize() ?
  • ?
  • { ?
  • ?
  • ?????????CortexM3_AFIO?&AFIO?=?CortexM3::AFIO(); ?
  • ?
  • ????for(int?i=0;i<4;i++)? ?
  • ?
  • ????{ ?
  • ?
  • ???????AFIO.EXTICR[i]=0x0000; ?
  • ?
  • ????}???????? ?
  • ?
  • CortexM3_EXTI?&EXTI=?CortexM3::EXTI();???? ?
  • ?
  • ????EXTI.IMR?=?0x00000000; ?
  • ?
  • ????EXTI.EMR?=?0x00000000; ?
  • ?
  • ????EXTI.RTSR?=?0x00000000;? ?
  • ?
  • ????EXTI.FTSR?=?0x00000000;? ?
  • ?
  • ????EXTI.PR?=?0x0007FFFF; ?
  • ?
  • ????//NVIC? ?
  • ?
  • ????if(!CPU_INTC_ActivateInterruptEx(CortexM3_NVIC::c_IRQ_Index_EXTI0,(UINT32)(void?*)EXTI_IRQHandler?))???return?FALSE; ?
  • ?
  • ?????????//略 ?
  • ?
  • ????return?TRUE; ?
  • ?
  • } ?
  • ?
  • 其中比較重要的是CPU_INTC_ActivateInterruptEx函數,它可動態設置c_IRQ_Index_EXTI0中斷所對應的中斷函數的入口地址。

  • void?GPIO_Driver::EnableOutputPin(GPIO_PIN?pin,?BOOL?initialState) ?
  • ?
  • { ?
  • ?
  • ????ASSERT(pin?<?c_MaxPins);???????? ?
  • ?
  • ????UINT32?port?=?PinToPort(pin);? ?
  • ?
  • ?????????UINT32?bit?=?PinToBit(pin); ?
  • ?
  • ????UINT32?pos?=?(bit?%?8)<<2; ?
  • ?
  • ?????????CortexM3_GPIO?&GPIO=?CortexM3::GPIO(port);???? ?
  • ?
  • ????//通用推挽輸出模式 ?
  • ?
  • ????if(bit<8) ?
  • ?
  • ????{???????? ?
  • ?
  • ???????GPIO.CRL?=?(GPIO.CRL?&?~(0x0F?<<?pos))?|?(CortexM3_GPIO::GPIO_Mode_Speed_50MHz?<<?pos); ?
  • ?
  • ????} ?
  • ?
  • ?????????else?
  • ?
  • ?????????{ ?
  • ?
  • ????????????GPIO.CRH?=?(GPIO.CRH?&?~(0x0F?<<?pos))?|?(CortexM3_GPIO::GPIO_Mode_Speed_50MHz?<<?pos); ?
  • ?
  • ?????????} ?
  • ?
  • ? ?
  • ?
  • ????//初值 ?
  • ?
  • ????if(initialState)?GPIO.BSRR?=?0x1?<<?bit; ?
  • ?
  • ????else?GPIO.BRR?=?0x1?<<?bit; ?
  • ?
  • } ?
  • ?
  • 輸出默認為通用推挽輸出模式,你也可以根據實際需要進行必要的調整。

  • BOOL?GPIO_Driver::EnableInputPin(GPIO_PIN?pin,?BOOL?GlitchFilterEnable,?GPIO_INTERRUPT_SERVICE_ROUTINE?ISR,?void?*pinIsrParam,?GPIO_INT_EDGE?intEdge,?GPIO_RESISTOR?resistorState) ?
  • ?
  • { ?
  • ?
  • ????ASSERT(pin?<?c_MaxPins);???????? ?
  • ?
  • ????UINT32?port?=?PinToPort(pin);? ?
  • ?
  • ?????????UINT32?bit?=?PinToBit(pin); ?
  • ?
  • ????UINT32?pos?=?(bit?%?8)<<2; ?
  • ?
  • ?????????CortexM3_GPIO?&GPIO=?CortexM3::GPIO(port);???? ?
  • ?
  • ????//浮空輸入 ?
  • ?
  • ????if(bit<8) ?
  • ?
  • ????{???????? ?
  • ?
  • ???????GPIO.CRL?=?(GPIO.CRL?&?~(0x0F?<<?pos))|?(CortexM3_GPIO::GPIO_Mode_IN_FLOATING?<<?pos); ?
  • ?
  • ????} ?
  • ?
  • ?????????else ?
  • ?
  • ?????????{ ?
  • ?
  • ????????????GPIO.CRH?=?(GPIO.CRH?&?~(0x0F?<<?pos))|?(CortexM3_GPIO::GPIO_Mode_IN_FLOATING?<<?pos); ?
  • ?
  • ?????????} ?
  • ?
  • ????//中斷輸入源配置(AFIO) ?
  • ?
  • ????CortexM3_AFIO?&AFIO?=?CortexM3::AFIO(); ?
  • ?
  • ????AFIO.EXTICR[bit?>>?2]?&=?~(0x0F?<<?(0x04?*?(bit?&?0x03))); ?
  • ?
  • ????AFIO.EXTICR[bit?>>?2]?|=?port?<<?(0x04?*?(bit?&?0x03)); ?
  • ?
  • ?????????CortexM3_EXTI?&EXTI=CortexM3::EXTI(); ?
  • ?
  • ????if(ISR) ?
  • ?
  • ????{ ?
  • ?
  • ????????switch(intEdge) ?
  • ?
  • ????????{ ?
  • ?
  • ????????????case?GPIO_INT_NONE:???//無中斷 ?
  • ?
  • ????????????????EXTI.IMR?&=?~(0x1<<bit);???????????????????????????????????? ?
  • ?
  • ????????????????return?FALSE; ?
  • ?
  • ????????????case?GPIO_INT_EDGE_LOW:???//下降沿中斷 ?
  • ?
  • ????????????case?GPIO_INT_LEVEL_LOW: ?
  • ?
  • ????????????????EXTI.IMR?|=?0x1<<bit;????? ?
  • ?
  • ?????????????????????????????????????EXTI.FTSR?|=?0x1<<bit;????????//下降沿有效 ?
  • ?
  • ?????????????????????????????????????EXTI.RTSR?&=?~(0x1<<bit);??//上升沿無效 ?
  • ?
  • ????????????????break; ?
  • ?
  • ????????????//略 ?
  • ?
  • ????????????default: ?
  • ?
  • ????????????????ASSERT(0); ?
  • ?
  • ????????????????return?FALSE; ?
  • ?
  • ????????} ?
  • ?
  • ????}????????????????? ?
  • ?
  • ??????????????????? ?
  • ?
  • ????return?TRUE; ?
  • ?
  • } ?
  • ?
  • GPIO輸入的實現比較繁瑣一些,可以根據需要僅把端口配置成輸入模式,而不配置相應的中斷參數。這樣可以通過不斷掃描的方式獲得輸入信號。

  • void?GPIO_Driver::ISR(void?*Param) ?
  • ?
  • { ?
  • ?
  • ?????????CortexM3_EXTI?&EXTI=CortexM3::EXTI(); ?
  • ?
  • ????UINT32?interruptsActive?=?EXTI.PR; ?
  • ?
  • ????UINT32?bitMask??=?0x1,?bitIndex?=?0; ?
  • ?
  • ?????????while(interruptsActive) ?
  • ?
  • ????{ ?
  • ?
  • ????????while((interruptsActive?&?bitMask)?==?0) ?
  • ?
  • ????????{ ?
  • ?
  • ????????????bitMask??<<=?1; ?
  • ?
  • ????????????++bitIndex; ?
  • ?
  • ????????} ?
  • ?
  • ????????CortexM3_AFIO?&AFIO?=?CortexM3::AFIO(); ?
  • ?
  • ????????UINT32?port?=?(AFIO.EXTICR[bitIndex?>>?2]>>(0x04?*?(bitIndex?&?0x03)))?&?0xF; ?
  • ?
  • ????????GPIO_PIN?pin?=?BitToPin(?bitIndex,?port); ?
  • ?
  • ????????PIN_ISR_DESCRIPTOR&?pinIsr?=?g_GPIO_Driver.m_PinIsr[?pin?]; ?
  • ?
  • ????????pinIsr.Fire(?(void*)&pinIsr?); ?
  • ?
  • ????????interruptsActive?^=?bitMask; ?
  • ?
  • ???????????????????EXTI.PR?|=?bitMask; ?
  • ?
  • ????}? ?
  • ?
  • } ?
  • ?
  • 在中斷函數中,根據相關寄存器的值來判斷哪一個(或同時哪一些)GPIO發生的中斷,并由此執行業已配置好的異步中斷處理函數。

    好了,寫完了GPIO驅動程序,我們就可以漂漂亮亮的在NativeSample中寫我們的測試程序了:

  • void?ISR(?GPIO_PIN?Pin,?BOOL?PinState,?void*?Param?) ?
  • ?
  • { ?
  • ?
  • ????if(PinState)????//?released,?up ?
  • ?
  • ????{ ?
  • ?
  • ??????CPU_GPIO_SetPinState(GPIO_Driver::PF7,0x0); ?
  • ?
  • ????} ?
  • ?
  • ????else????????????//?pressed,?down ?
  • ?
  • ????{ ?
  • ?
  • ???????CPU_GPIO_SetPinState(GPIO_Driver::PF7,0x1); ?
  • ?
  • ????} ?
  • ?
  • } ?
  • ?
  • ? ?
  • ?
  • void?ApplicationEntryPoint() ?
  • ?
  • {??? ?
  • ?
  • ????//LED?D1?D2?D3?D4??? ?
  • ?
  • ????CPU_GPIO_EnableOutputPin(GPIO_Driver::PF7,FALSE); ?
  • ?
  • ?????????CPU_GPIO_EnableOutputPin(GPIO_Driver::PF8,FALSE); ?
  • ?
  • ? ?
  • ?
  • ?????????//user按鈕?=?0x1 ?
  • ?
  • ?????????CPU_GPIO_EnableInputPin(GPIO_Driver::PG8,FALSE,ISR,GPIO_INT_EDGE_BOTH,RESISTOR_PULLDOWN);???????????????????? ?
  • ?
  • ????while(TRUE)????? ?
  • ?
  • ????{??? ?
  • ?
  • ???????????CPU_GPIO_SetPinState(GPIO_Driver::PF8,!CPU_GPIO_GetPinState(GPIO_Driver::PF8)); ?
  • ?
  • ???????????Events_WaitForEvents(?0,?1000?);??????? ?
  • ?
  • ?????????} ?
  • ?
  • } ?
  • ?
  • 上面的程序比我們最初在《調試初步:點亮LED燈》中提到的代碼清爽多了,把程序下載到開發板上運行,你會發現D3 LED燈以一秒為周期不斷地閃爍,而D2 LED燈則在user按鈕按下時才亮,放開時則滅。

    只要細心 + 耐心,其實嵌入式開發還是比較容易的,并且功能實現那一刻喜悅的“強度”,是作為PC平臺軟件開發者所難以企及的

    ?

    轉載于:https://blog.51cto.com/yfsoft/321228

    總結

    以上是生活随笔為你收集整理的【.Net Micro Framework PortingKit - 08】GPIO驱动的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。