標題: STM32 NVIC編程模板 [打印本頁]

作者: 晚上一直    時間: 2019-12-28 14:50
標題: STM32 NVIC編程模板
今天和大家聊聊什么是NVIC,NVIC全名也叫做嵌套向量控制器,看名字也就知道了它和中斷密不可分。它是ARM公司設(shè)計的內(nèi)核管理設(shè)備,因此各個廠商在使用的時候往往都各不相同,但是原理都差不多,我們今天討論的就是ST公司是在怎么使用的,這里大家最好看看M3/M4權(quán)威指南第7章,239頁。這里我就不說中斷的基本概念了,直接進入主題。為什么要使用中斷?CPU的運行有中斷和查詢,但是查詢的時候CPU一直工作,這樣一直占用CPU,而中斷來的時候,CPU檢查到了中斷標志,就會立刻知道要有事情去處理。那么它就會去處理緊急的事情。這里就涉及到了優(yōu)先級的3種情況。

1)搶占優(yōu)先級:看名字就知道它特別霸道,會從CPU手中去搶占資源,也就是高搶占優(yōu)先級會干擾低搶占優(yōu)先級,也就是中斷嵌套。
2)響應(yīng)優(yōu)先級:高響應(yīng)優(yōu)先級有優(yōu)先處理(同時到來),但是如果高響應(yīng)優(yōu)先級后來的話,那么對不起,你也要排隊,等這個事情處理完,響應(yīng)優(yōu)先級沒有中斷嵌套。
3)自然優(yōu)先級:有沒有響應(yīng)優(yōu)先級,我們在數(shù)據(jù)手冊看到的中斷(除了內(nèi)核設(shè)備)都是自然優(yōu)先級,我們可以通多NVIC來設(shè)置優(yōu)先級級別。

二:中斷的來源:1:外設(shè)比如定時器,串口等;2:中斷請求;3:系統(tǒng)滴答定時器;4:系統(tǒng)異常;5:軟件中斷?偣惨255個中斷來源,15個是系統(tǒng)異常,240個是外部中斷。

三:ARM公司設(shè)計NVIC:
some of the registers are saved onto the stack automatically                                                這段話表明了在處理中斷的時候,外了恢復(fù)中斷程序,ARM                                                                                                                                                  公司把一些寄存器保存到堆棧中,在返回的時候自動恢復(fù),
when an exception is accepted, and are also automatically restored in an exception
return sequence. This mechanism allows the exception handlers to be written as
normal C functions without any additional software overhead.


Set up the priority level of the required interrupt (this step is optional)
• Enable the interrupt generation control in the peripheral that triggers the interrupt
• Enable the interrupt in the NVIC
這段話告訴我們:當要使用中斷的時候,第一步:使用外部中斷的使能(就好比開時鐘一樣);第二步:設(shè)置中斷的優(yōu)先級級別;第3步:啟用NVIC的中斷。

四:優(yōu)先級級別有優(yōu)先級級別寄存器來控制,ARM公司一共有8位確定優(yōu)先級級別;但是ST公司只使用了4位;我們看看ST公司是在怎么確定優(yōu)先級級別的。
      看下面4個函數(shù)就知道了在CM4.h文件的1485頁。
1)void NVIC_EnableIRQ(IRQn_Type IRQn)   函數(shù)功能:NVIC中斷使能,函數(shù)參數(shù):IRQn_Type IRQn,中斷名:指明了是哪一個中斷


2)void NVIC_SetPriority (IRQn_Type IRQn,uint32_t priority) 1568頁:函數(shù)功能:設(shè)定優(yōu)先級級別,函數(shù)參數(shù):IRQn_Type IRQn,中斷名:指明了是哪一個中斷
uint32_t priority:中斷優(yōu)先級級別。
3)void NVIC_SetPriorityGrouping(uint32_tPriorityGroup)函數(shù)功能:設(shè)定優(yōu)先級分組(一個工程內(nèi)就只能用一次分組,如果多次分組,之前的分組就會無效)函數(shù)參數(shù):uint32_tPriorityGroup優(yōu)先級分組值 ===========(7-組編號)


4)uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
{
  uint32_t PriorityGroupTmp = (PriorityGroup & 0x07);          /* only values 0..7 are used          */    //表示ST公司只用了4位
  uint32_t PreemptPriorityBits;                          //搶占優(yōu)先級位數(shù)
  uint32_t SubPriorityBits;                                  //響應(yīng)優(yōu)先級位數(shù)
  PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp;
  SubPriorityBits     = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS;

return (
           ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) |
           ((SubPriority     & ((1 << (SubPriorityBits    )) - 1)))
         );






}
NVIC_PRIO_BITS:恒等于4

我們來分析這個函數(shù):函數(shù)功能:得到優(yōu)先級級別;函數(shù)參數(shù):uint32_t PriorityGroup;優(yōu)先級分組值;uint32_t PreemptPriority:搶占優(yōu)先級

uint32_t SubPriority:響應(yīng)優(yōu)先級;
uint32_t PriorityGroupTmp = (PriorityGroup & 0x07);  上面我們說過PriorityGroup=7-組邊號,當組邊號是0,PriorityGroupTmp=7;帶進這一句話

PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp;結(jié)果PreemptPriorityBits =0;表示搶占優(yōu)先級位數(shù)是0,響應(yīng)優(yōu)先級位數(shù)是4;返回的值是0和15.然后依次分析1,2 ,3,4。組。得到優(yōu)先級級別。


下面我們把這4個函數(shù)封裝成一個函數(shù)得到:


void My_NVIC_Init(IRQn_Type IRQn,u32 PG,u32 PP,u32 SP)
{

u32 priority;

NVIC_SetPriorityGrouping(PG);      //設(shè)定優(yōu)先級分組

priority=NVIC_EncodePriority (PG,PP,SP);  //得到優(yōu)先級級別
  
  NVIC_SetPriority (IRQn, priority);          //設(shè)定優(yōu)先級級別

NVIC_EnableIRQ (IRQn);                          /NVIC中斷使能。

}
接下來我會通過外部中斷實驗來告訴你們?nèi)绾问褂眠@個NVIC函數(shù)。


作者: 老馬工作室    時間: 2020-1-15 20:41
不錯不錯,看明白了




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1