專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機教程網(wǎng) >> MCU設(shè)計實例 >> 瀏覽文章

PIC32中斷及振蕩器配置

作者:未知   來源:枯葉之碟的博客   點擊數(shù):  更新時間:2014年08月08日   【字體:

 暑假過了一個月了,在忙碌的玉米地間享受揮汗如雨熱情。不過學(xué)習(xí)還是沒落下太多的,趁現(xiàn)在難得的網(wǎng)絡(luò),匯總個這一個月的筆記情況。

 

 

一.中斷設(shè)置

步驟:

1.   設(shè)置外設(shè)中斷優(yōu)先級及子優(yōu)先級,觸發(fā)方式等配置

2.   設(shè)置為系統(tǒng)向量模式并使能中斷

常用函數(shù)如下

    INTSetVectorPriority(); 設(shè)置優(yōu)先級

    INTSetVectorSubPriority(); 設(shè)置子優(yōu)先級

    INTClearFlag(); 清除中斷標志位

    INTEnable(); 使能中斷

系統(tǒng)

    INTEnableSystemMultiVectoredInt();//多向量中斷允許

    INTEnableSystemSingleVectoredInt();//單向量中斷允許

所謂多向量模式即中斷向量都有自己的入口,從自己的入口進入ISR。而單向量模式則是所有的中斷共用一個向量入口。

 

例如控制時鐘中斷

                   

   INTSetVectorPriority(INT_TIMER_1_VECTOR, INT_PRIORITY_LEVEL_2);

   INTEnable(INT_T1,INT_ENABLED);                                //ConfigIntTimer1(T1_INT_ON | T1_INT_PRIOR_3 | T1_INT_SUB_PRIOR_0);

   INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);

   INTEnableInterrupts();                                         //INTEnableSystemMultiVectoredInt();

   先設(shè)置時鐘的中斷優(yōu)先級和子優(yōu)先級并允許中斷

   ConfigIntTimer1(T1_INT_ON|T1_INT_PRIOR_3|TI_INT_SUB_PRIOR_0);      

//T1中斷優(yōu)先級為3,子優(yōu)先級為0,  并     允     許     T1_INT_ON      時鐘源1中斷。                       

   設(shè)置系統(tǒng)內(nèi)核中斷

   INTEnableSystemMultiVectoredInt();

//系統(tǒng)多向量中斷MultiVectored開啟,并允許INTEnable中斷。 

  

 

庫函數(shù)說明:

 

 

中斷不能返回任何數(shù)據(jù)(void)

不能傳遞參數(shù)(void)

無法直接調(diào)用中斷,最好也不調(diào)用其他函數(shù)

 

INTEnableSystemSingleVectoredInt();     單向量模式——在一個向量地址處處理所有中斷請求(復(fù)位之后的模式)。

INTEnableSystemMultiVctoredInt();       多向量模式——在所計算的向量地址處處理中斷請求。

注: 雖然用戶可以在運行時將中斷控制器從單向量模式重新配置為多向量模式(或反

之),但強烈建議用戶不要如此操作。在初始化之后更改中斷控制器模式可能導(dǎo)致

未定義的行為。

必須先允許內(nèi)核的系統(tǒng)中斷。然后,在IEC 寄存器中允許中斷,并在IPS 寄存器中分配非零優(yōu)先級后,才會接收到中斷請求。

 

INTEnableSystemSingleVectoredInt();    單向量模式——在一個向量地址處處理所有中斷請求(復(fù)位之后的模式)。

INTEnableSystemMultiVctoredInt();     多向量模式——在所計算的向量地址處處理中斷請求。

 

通用:        INTSetVectorPriority(4,INT_PRIORITY_LEVEL_2);

//中斷向量查數(shù)據(jù)手冊得timer1為4

其他:

INTSetVectorPriority(INT_TIMER_1_VECTOR,INT_PRIORITY_LEVEL_2);//配置中斷向量的組優(yōu)先級0~7

mXXSetIntPriority(x);//XX為宏縮寫器件例如mT1SetIntPriority(2);

 

通用:             INTSetVectorSubPriority(4, INT_SUB_PRIORITY_LEVEL_0);

//中斷向量查數(shù)據(jù)手冊得timer1為4

其他:

INTSetVectorSubPriority(INT_TIMER_1_VECTOR, INT_SUB_PRIORITY_LEVEL_0);

//配置中斷向量的子優(yōu)先級0~3,當(dāng)組優(yōu)先級相同時,子優(yōu)先級高的先執(zhí)行

mXXSetIntSubPriorty(x);//XX為宏縮寫器件例如mT1SetIntPriority(0);

 

INTEnable(INT_XX,INT_ENABLED);

mXXIntEnable();//中斷源允許中斷

 

INTClearFlag(INT_XX);// 清除XX的中斷標志

mXXClearIntFlag();// XX為宏縮寫器件例如ClearIntFlag(INT_T1);

 

INTGetFlag(INT_XX);

mXXGetIntFlag();//獲得XX的中斷標志,有中斷為1,否則0.

 

 

 

 

 

                                                  中斷源





 

 

                                                  向量表

 




 

 

以控制1s時鐘led為例

  

   先進行時鐘的設(shè)置,也就是震蕩器的配置這是定時器的關(guān)鍵

  

   再對定時器選擇并配置

  

   定義中斷向量并允許中斷

  

   中斷函數(shù)

  

   #include

   #pragma config JTAGEN =OFF

   //震蕩器配置如下  在windows->pic Memory Views->configuration Bits有詳細設(shè)置復(fù)制出來粘貼

   #pragma config FPLLIDIV = DIV_2         // PLL輸入分頻2

   #pragma config FPLLMUL = MUL_24         // PLL倍頻24

   #pragma config FPLLODIV = DIV_2         // PLL輸出分頻2

   #pragma config FPBDIV = DIV_1           // PLL后分頻1,外設(shè)時鐘

   #pragma config FNOSC = FRCPLL           //震蕩主通道內(nèi)部8MHZ震蕩帶PLL功能

   #pragma config POSCMOD = OFF             //主震蕩模式關(guān)

   #pragma config FWDTEN = OFF             //看門狗時鐘關(guān)閉

   #define SYS_FREQ (48000000L)            //系統(tǒng)時鐘SYSCLK:8MHz/2*24/2=48MHz     

                                                                 //外設(shè)時鐘PBCLK:SYSCLK/FPBDIV=48MHz

   #define PERIOD 6000                   

 //時鐘源1的1-8分頻,time=period*8/48000000=0.001s 

   int main()

   //io口設(shè)置

   PORTSetPinsDigitalOut(IOPORT_B,BIT_7|BIT_9|BIT_8|BIT_13);//7,8,9.13設(shè)為數(shù)字輸出端口

   PORTSetBits(IOPORT_B,BIT_7|BIT_8|BIT_9|BIT_13);          //置一,燈滅

   OpenTimer1(T1_ON|T1_SOURCE_INT|T1_PS_1_8,PERIOD);

    //中斷設(shè)置  配置時鐘中斷允許->系統(tǒng)中斷允許

   INTEnable(INT_T1, INT_ENABLED);                     

   INTSetVectorPriority(INT_TIMER_1_VECTOR, INT_PRIORITY_LEVEL_2);

//ConfigIntTimer1(T1_INT_ON | T1_INT_PRIOR_2 | T1_INT_SUB_PRIOR_0);

   INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);

   INTEnableInterrupts();                                         //INTEnableSystemMultiVectoredInt();

}

                       //中斷函數(shù)

void __ISR(_TIMER_1_VECTOR,      ipl2) Timer1Handler(void)  

//時鐘源1所指中斷向量每產(chǎn)生一次中斷運行0.001s

{

//  Clear the interrupt flag

    INTClearFlag(INT_T1);

    n++;

    if(n > 1000)  //1s=1000ms=1000us

    {

       n= 0;

       PORTBINV=(1<<7)|(1<<8)|(1<<9)|(1<<13);//翻轉(zhuǎn)7,8,9,13

    }

}

 

 

     振蕩器選擇標準典型的FRC 8MHZ通過輸入分頻FPLLIDIV,倍頻FPLLMUL,輸出分頻FPLLODIV成為系統(tǒng)內(nèi)時鐘SYSCLK,在經(jīng)由后分頻FPBDIV成為外設(shè)時鐘PBCLK。

   外設(shè)時鐘通過定時器Timer1,時間t=PS*PERIOD/PBCLK;

  

  

   Timer 定時器工作原理淺析:

經(jīng)過上面設(shè)置,定時器從0開始計數(shù),當(dāng)計數(shù)值與period時產(chǎn)生中斷,中斷后會清標志,并清period值,重新從0開始計數(shù)(period對應(yīng)寄存器PR1)

  

 

 

單向量中斷與多向量中斷

INTEnableSystemSigleVectoredInt();//系統(tǒng)單向量中斷使能, 單向量模式則是所有的中斷共用一個向量入口。

INTEnableSystemMultiVectoredInt();//系統(tǒng)多向量中斷使能,所謂多向量模式即中斷向量都有自己的入口,從自己的入口進入ISR。

 

 

 

單向量模式時,共用默認的0向量口,僅由優(yōu)先級不同來判斷中斷操作。當(dāng)一個中斷正在執(zhí)行時,其他的中斷事件就必須等待當(dāng)前中斷事件結(jié)束后才能進行。

     void__ISR(0,ipl2) hander2(void)

     {

     }

 

 

多向量中斷時,各個中斷源都有自己的中斷向量,僅當(dāng)對應(yīng)的中斷源出現(xiàn)中斷時標志時才會調(diào)用中斷事件。當(dāng)一個中斷進行時,其他優(yōu)先級高的中斷可以打斷并進行高優(yōu)先級中斷。

Void__ISR(_TIMER_1_VECTOR,ipl1)han(void)     void__ISR(_TIMER_2_VECTOR,ipl2) han2(void)

                                        {

                                        }

 

                          單向量模式

#include

#pragma config FPLLIDIV = DIV_2         // PLL Input Divider (2x Divider)

#pragma config FPLLMUL = MUL_24         // PLL Multiplier (24x Multiplier)

#pragma config FPLLODIV = DIV_2         // System PLL Output Clock Divider (PLL Divide by 2)

#pragma config FNOSC = FRCPLL           // Oscillator Selection Bits (Fast RC Osc with PLL)

#pragma config FPBDIV = DIV_1           // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)

#pragma config JTAGEN = OFF

#pragma config FWDTEN = OFF

#define PERIOD 48000

int n2,n1;

int main()

{

 PORTSetPinsDigitalOut(IOPORT_B,BIT_7|BIT_8|BIT_9|BIT_13);

 PORTSetBits(IOPORT_B,BIT_7|BIT_8|BIT_9|BIT_13);

 OpenTimer1(T1_ON|T1_SOURCE_INT|T1_PS_1_1,PERIOD);

 OpenTimer2(T2_ON|T2_SOURCE_INT|T1_PS_1_1,PERIOD);

 INTSetVectorPriority(INT_TIMER_1_VECTOR,INT_PRIORITY_LEVEL_2);

 INTSetVectorPriority(INT_TIMER_2_VECTOR,INT_PRIORITY_LEVEL_5);

 mT1IntEnable(1);

 mT2IntEnable(1);

 INTEnableSystemSingleVectoredInt();

}

void __ISR(0,ipl5)  Timer1hander(void)

{

    if(mT2GetIntFlag())//單向量T2先進行

    mT2ClearIntFlag();//清除T2中斷,但T1中斷仍在,繼續(xù)觸發(fā)Timer1hander

    else if(mT1GetIntFlag())

    mT1ClearIntFlag();

    n1++;//每0.001s加兩次

    if(n1>1000)//約為0.5s

    {

        n1=0;

    PORTBINV=(1<<7|1<<8);

    }

 

}

                          多向量模式

定時器2優(yōu)先級高,直接搶占定時器1

#include

#pragma config FPLLIDIV = DIV_2         // PLL Input Divider (2x Divider)

#pragma config FPLLMUL = MUL_24         // PLL Multiplier (24x Multiplier)

#pragma config FPLLODIV = DIV_2         // System PLL Output Clock Divider (PLL Divide by 2)

#pragma config FNOSC = FRCPLL           // Oscillator Selection Bits (Fast RC Osc with PLL)

#pragma config FPBDIV = DIV_1           // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)

#pragma config JTAGEN = OFF

#pragma config FWDTEN = OFF

#define PERIOD 48000

int n2,n1;

int main()

{

 PORTSetPinsDigitalOut(IOPORT_B,BIT_7|BIT_8|BIT_9|BIT_13);

 PORTSetBits(IOPORT_B,BIT_7|BIT_8|BIT_9|BIT_13);

 OpenTimer1(T1_ON|T1_SOURCE_INT|T1_PS_1_1,PERIOD);

 OpenTimer2(T2_ON|T2_SOURCE_INT|T1_PS_1_1,PERIOD);

 INTSetVectorPriority(INT_TIMER_1_VECTOR,INT_PRIORITY_LEVEL_2);

 INTSetVectorPriority(INT_TIMER_2_VECTOR,INT_PRIORITY_LEVEL_5);

 mT1IntEnable(1);

 mT2IntEnable(1);

 INTEnableSystemMultiVectoredInt();

}

void __ISR(_TIMER_1_VECTOR,ipl2)  Timer1hander(void)

{

    mT1ClearIntFlag();

    n1++;

    if(n1>1000)

    {

        n1=0;

    PORTBINV=(1<<7|1<<8);

    }

 

}

void __ISR(_TIMER_2_VECTOR,ipl5)  Timer2hander(void)

{

   mT2ClearIntFlag();

    n2++;

    if(n2>1000)

    {

        n2=0;

    PORTBINV=(1<<9|1<<13);

    while(1);

    }

   

}

關(guān)閉窗口

相關(guān)文章