暑假过了一个月了,在忙碌的玉米地间享受挥汗如雨热情。不过学习还是没落下太多的,趁现在难得的网络,汇总个这一个月的笔记情况。
一.中断设置
步骤:
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 Memory
Views->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 PERIOD
6000
//时钟源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
}
}
振荡器选择标准典型的FRC
8MHZ通过输入分频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
else
if(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);
}
}