通過觀察單片機程序的中斷向量表,我們不難發現對於ARM架構的單片機中斷向量表基本分為兩部分,一部分是內部中斷,另一部分是外部中斷。
下面是MKL25Z4的中斷向量表:
下面是STM32F429的中斷向量表:
當我們在寫單片機程序的時候,經常會與中斷打交道,控制中斷的開和關是必經的操作,中斷分外部中斷和內部中斷,為了能准確控制中斷就需要明白當前要控制的中斷是外部中斷還是內部中斷。開發單片機程序的都知道對於中斷的控制開關,芯片廠商早已在提供的底層驅動程序中以功能函數的形式呈現給開發人員,我們只需調用即可。以MKL25Z4為例,比如如下幾個函數:
/** \brief Enable External Interrupt \details Enables a device-specific interrupt in the NVIC interrupt controller. \param [in] IRQn External interrupt number. Value cannot be negative. */ __STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) { NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); } /** \brief Disable External Interrupt \details Disables a device-specific interrupt in the NVIC interrupt controller. \param [in] IRQn External interrupt number. Value cannot be negative. */ __STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) { NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); } /** \brief Get Pending Interrupt \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. \param [in] IRQn Interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. */ __STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) { return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); } /** \brief Set Pending Interrupt \details Sets the pending bit of an external interrupt. \param [in] IRQn Interrupt number. Value cannot be negative. */ __STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) { NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); } /** \brief Clear Pending Interrupt \details Clears the pending bit of an external interrupt. \param [in] IRQn External interrupt number. Value cannot be negative. */ __STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) { NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); } /** \brief Set Interrupt Priority \details Sets the priority of an interrupt. \note The priority cannot be set for every core interrupt. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. */ __STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if ((int32_t)(IRQn) < 0) { SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } else { NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } } /** \brief Get Interrupt Priority \details Reads the priority of an interrupt. The interrupt number can be positive to specify an external (device specific) interrupt, or negative to specify an internal (core) interrupt. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ __STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) { if ((int32_t)(IRQn) < 0) { return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } else { return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } }
雖然以上函數能很方便的被開發人員調用,但在調用的時候需要知道,以上函數只能用來控制單片機的外部中斷,對於內部中斷是不能用以上函數控制的。如下圖所示,除了注釋有說明外,在做標記的地方已經限定死了中斷的范圍為0-31。
因此並非所有的中斷都能使用驅動程序中提供的中斷控制函數來控制中斷,那么如果想要關閉內部中斷該如何做?下面以SysTick為例:
具體操作就是怎么打開就怎么關閉,上面只關閉了Systick定時器,控制中斷關是一樣的。
#end