|
在忙碌的玉米地間享受揮汗如雨熱情。不過學習還是沒落下太多的,趁現在難得的網絡,匯總個這一個月的筆記情況。
一.中斷設置
步驟:
1. 設置外設中斷優先級及子優先級,觸發方式等配置
2. 設置為系統向量模式并使能中斷
常用函數如下
INTSetVectorPriority(); 設置優先級
INTSetVectorSubPriority(); 設置子優先級
INTClearFlag(); 清除中斷標志位
INTEnable(); 使能中斷
系統
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();
先設置時鐘的中斷優先級和子優先級并允許中斷
ConfigIntTimer1(T1_INT_ON|T1_INT_PRIOR_3|TI_INT_SUB_PRIOR_0);
//T1中斷優先級為3,子優先級為0, 并 允 許 T1_INT_ON 時鐘源1中斷。
設置系統內核中斷
INTEnableSystemMultiVectoredInt();
//系統多向量中斷MultiVectored開啟,并允許INTEnable中斷。
庫函數說明:
中斷不能返回任何數據(void)
不能傳遞參數(void)
無法直接調用中斷,最好也不調用其他函數
INTEnableSystemSingleVectoredInt(); 單向量模式——在一個向量地址處處理所有中斷請求(復位之后的模式)。
INTEnableSystemMultiVctoredInt(); 多向量模式——在所計算的向量地址處處理中斷請求。
注: 雖然用戶可以在運行時將中斷控制器從單向量模式重新配置為多向量模式(或反
之),但強烈建議用戶不要如此操作。在初始化之后更改中斷控制器模式可能導致
未定義的行為。
必須先允許內核的系統中斷。然后,在IEC 寄存器中允許中斷,并在IPS 寄存器中分配非零優先級后,才會接收到中斷請求。
INTEnableSystemSingleVectoredInt(); 單向量模式——在一個向量地址處處理所有中斷請求(復位之后的模式)。
INTEnableSystemMultiVctoredInt(); 多向量模式——在所計算的向量地址處處理中斷請求。
通用: INTSetVectorPriority(4,INT_PRIORITY_LEVEL_2);
//中斷向量查數據手冊得timer1為4
其他:
INTSetVectorPriority(INT_TIMER_1_VECTOR,INT_PRIORITY_LEVEL_2);//配置中斷向量的組優先級0~7
mXXSetIntPriority(x);//XX為宏縮寫器件例如mT1SetIntPriority(2);
通用: INTSetVectorSubPriority(4, INT_SUB_PRIORITY_LEVEL_0);
//中斷向量查數據手冊得timer1為4
其他:
INTSetVectorSubPriority(INT_TIMER_1_VECTOR,INT_SUB_PRIORITY_LEVEL_0);
//配置中斷向量的子優先級0~3,當組優先級相同時,子優先級高的先執行
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為例
先進行時鐘的設置,也就是震蕩器的配置這是定時器的關鍵
再對定時器選擇并配置
定義中斷向量并允許中斷
中斷函數
#include
#pragma config JTAGEN=OFF
//震蕩器配置如下 在windows->pic MemoryViews->configuration Bits有詳細設置復制出來粘貼
#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,外設時鐘
#pragma config FNOSC =FRCPLL //震蕩主通道內部8MHZ震蕩帶PLL功能
#pragma config POSCMOD =OFF //主震蕩模式關
#pragma config FWDTEN =OFF //看門狗時鐘關閉
#define SYS_FREQ(48000000L) //系統時鐘SYSCLK:8MHz/2*24/2=48MHz
//外設時鐘PBCLK:SYSCLK/FPBDIV=48MHz
#define PERIOD6000
//時鐘源1的1-8分頻,time=period*8/48000000=0.001s

int main()
{ //io口設置
PORTSetPinsDigitalOut(IOPORT_B,BIT_7|BIT_9|BIT_8|BIT_13);//7,8,9.13設為數字輸出端口
PORTSetBits(IOPORT_B,BIT_7|BIT_8|BIT_9|BIT_13); //置一,燈滅
OpenTimer1(T1_ON|T1_SOURCE_INT|T1_PS_1_8,PERIOD);
//中斷設置 配置時鐘中斷允許->系統中斷允許
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();
}
//中斷函數
void__ISR(_TIMER_1_VECTOR, ipl2) Timer1Handler(void)
//時鐘源1所指中斷向量每產生一次中斷運行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);//翻轉7,8,9,13
}
}
振蕩器選擇標準典型的FRC8MHZ通過輸入分頻FPLLIDIV,倍頻FPLLMUL,輸出分頻FPLLODIV成為系統內時鐘SYSCLK,在經由后分頻FPBDIV成為外設時鐘PBCLK。
外設時鐘通過定時器Timer1,時間t=PS*PERIOD/PBCLK;
Timer 定時器工作原理淺析:
經過上面設置,定時器從0開始計數,當計數值與period時產生中斷,中斷后會清標志,并清period值,重新從0開始計數(period對應寄存器PR1)
單向量中斷與多向量中斷
INTEnableSystemSigleVectoredInt();//系統單向量中斷使能,單向量模式則是所有的中斷共用一個向量入口。
INTEnableSystemMultiVectoredInt();//系統多向量中斷使能,所謂多向量模式即中斷向量都有自己的入口,從自己的入口進入ISR。
單向量模式時,共用默認的0向量口,僅由優先級不同來判斷中斷操作。當一個中斷正在執行時,其他的中斷事件就必須等待當前中斷事件結束后才能進行。
void__ISR(0,ipl2) hander2(void)
{
}
多向量中斷時,各個中斷源都有自己的中斷向量,僅當對應的中斷源出現中斷時標志時才會調用中斷事件。當一個中斷進行時,其他優先級高的中斷可以打斷并進行高優先級中斷。
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中斷仍在,繼續觸發Timer1hander
elseif(mT1GetIntFlag())
mT1ClearIntFlag();
n1++;//每0.001s加兩次
if(n1>1000)//約為0.5s
{
n1=0;
PORTBINV=(1<<7|1<<8);
}
}
多向量模式
定時器2優先級高,直接搶占定時器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);
}
}
|
|