1
控制/MCU
Cortex-M3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。但STM32并没有使用Cortex-M3内核的全部东西,而是只用了它的一部分。STM32有84个中断,包括16个内核中断和68个可屏蔽中断,具有16级可编程的中断优先级。而我们常用的就是这68个可屏蔽中断,但是STM32的68个可屏蔽中断,在STM32F103ZET6中只有60个。
STM32F103的中断分为抢占优先级和响应优先级两种,这两种优先级的顺序是抢占优先级高于响应优先级,假设存在两个事件,那就会存在以下几种可能:
(1)情况1:事件1和事件2的抢占优先级都是1,事件1的响应优先级为1,事件2的响应优先级为2,那么事件1和事件2同时发生的时候,CPU优先处理事件1,然后处理事件2;
(2)情况2:事件1和事件2的响应优先级都是1,事件1的抢占优先级为2,事件2的抢占优先级为1,那么,事件1和事件2同时发生的时候,CPU优先处理事件2,然后处理事件1;
(3)情况3:事件1的响应优先级为1,事件2的响应优先级为2,事件1的抢占优先级为2,事件2的抢占优先级为1,当事件1和事件2同时发生的时候,CPU优先处理事件2,然后处理事件1;
通过上面两种情况,我们可以发现,当抢占优先级一致,谁的响应优先级的数小,谁的优先级就高,中断同时发生的时候CPU就先处理谁;如果抢占优先级不一样,那么无所谓响应优先级,谁的抢占优先级数小,优先级就高,中断同时发生的时候CPU就先处理谁。
STM32F103的抢占优先级和响应优先级各有4级,即0~3,根据乘法原理,也从侧面反映了16级可编程的中断优先级,并且抢占优先级和响应优先级的数量是可以设置的,通过中断分组来配置,中断分组和优先级数量的对应如下表所示。
组 | 抢占优先级数量 | 响应优先级处理 |
---|---|---|
0 | 0 | 4 |
1 | 1 | 3 |
2 | 2 | 2 |
3 | 3 | 1 |
4 | 4 | 0 |
(1) 中断应用和复位控制寄存器 :AIRCR
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
KEY[15:0] | |||||||||||||||
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
END | - | GROUP[2:0] | - | REQ | ACT | RST |
Bit 31~Bit 16:激活代码,写入0x05FA激活寄存器
Bit 15:指示数据的字节序(这只能在重置后更改)
0:表示小尾数 1:表示大字节序
Bit 10~Bit 8:中断优先级分组
Bit 2:请求芯片控制逻辑产生复位
Bit 1:清除所有活动状态信息中的异常
Bit 0:重置Cortex-M3处理器(调试逻辑除外)
(2) 中断使能寄存器组 :ISER
在STM32中,ISER寄存器一共有3个,ISER[0]的0到31位对应中断031,ISER[1]的0到31位对应中断3263,ISER[2]的0到3对应中断64~67,如果需要使能某个中断,必须设置对应的ISER位为1,要清除的话可以设置ICER寄存器组对应位为1,或者对ISER写0,但是对于ICER寄存器组写0是不起作用的。
(3) 中断优先级控制寄存器组 :IP
对于STM32,优先级控制寄存器IP一共有68个,对应着68个中断,每个寄存器的结构都是相同的,如下图所示。
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
---|---|---|---|---|---|---|---|
PrePriority[1:0] | SubPriority[1:0] | - |
Bit 7~Bit 6:抢占优先级
Bit 5~Bit 4:响应优先级
/***************************************************
Name :NVIC_Init
Function :设置NVIC
Parameter :
PrePriority :抢占优先级
SubPriority :响应优先级
Channel :中断编号
Group :中断分组 0~4
Return :None
***************************************************/
void NVIC_Init( u8 PrePriority, u8 SubPriority, u8 Channel, u8 Group )
{
u32 temp, temp1 ;
//设置分组
temp1 = ( ~Group )&0x07 ; //取后三位
temp1 <<= 8 ;
temp = SCB->AIRCR ; //读取先前的设置
temp &= 0x0000F8FF ; //清空先前分组
temp |= 0x05FA0000 ; //写入钥匙
temp |= temp1 ;
SCB->AIRCR = temp ; //设置分组
//设置优先级
temp = ( u32 )PrePriority<<( 4-Group ) ;
temp |= SubPriority&( 0x0f>>Group ) ;
temp &= 0x0F ; //取低四位
NVIC->ISER[ Channel/32 ] |= ( 1< IP[ Channel ] |= temp<<4 ; //设置响应优先级和抢断优先级
}
外部中断/事件控制器由连接线设备中的多达20个边缘检测器或其他设备中的19个边缘检测器组成,用于生成事件/中断请求。每条输入线可以独立配置以选择类型(事件或中断)和相应的触发事件(上升或下降或两者)。每条线也可以独立屏蔽。
对于STM32来说,每一个端口都可以配置为外部中断,根据中断信号的类型都可以单独配置上升沿触发或者下降沿触发,中断服务函数相互独立。
(1) 中断屏蔽寄存器 :IMR
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
- | M19 | M18 | M17 | M16 | |||||||||||
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
M15 | M14 | M13 | M12 | M11 | M10 | M9 | M8 | M7 | M6 | M5 | M4 | M3 | M2 | M1 | M0 |
Bit 19~Bit 0:线x上的中断请求配置位
0:禁止输入线x上的中断请求
1:允许输入线x上的中断请求
(2) 上升沿触发选择寄存器 :RTSR
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
- | R19 | R18 | R17 | R16 | |||||||||||
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
R15 | R14 | R13 | R12 | R11 | R10 | R9 | R8 | R7 | R6 | R5 | R4 | R3 | R2 | R1 | R0 |
Bit 19~Bit 0:线x上的上升沿触发事件配置位
0:禁止输入线x上的上升沿触发
1:允许输入线x上的上升沿触发
(3) 下降沿触发选择寄存器 :FTSR
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
- | F19 | F18 | F17 | F16 | |||||||||||
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
F15 | F14 | F13 | F12 | F11 | F10 | F9 | F8 | F7 | F6 | F5 | F4 | F3 | F2 | F1 | F0 |
Bit 19~Bit 0:线x上的下降沿触发事件配置位
0:禁止输入线x上的下降沿触发
1:允许输入线x上的下降沿触发
(4) 外部中断配置寄存器1 :EXTIXR1
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
- | |||||||||||||||
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
EXTI3[3:0] | EXTI2[3:0] | EXTI1[3:0] | EXTI0[3:0] |
EXTIx[3:0]:EXTIx配置(x = 0~3)
0000:PA[x]引脚 0100:PE[x]引脚 0001:PB[x]引脚 0101:PF[x]引脚
0010:PC[x]引脚 0110:PG[x]引脚 0011:PD[x]引脚
(5) 外部中断配置寄存器2 :EXTIXR2
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
- | |||||||||||||||
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
EXTI7[3:0] | EXTI6[3:0] | EXTI5[3:0] | EXTI4[3:0] |
EXTIx[3:0]:EXTIx配置(x = 4~7)
0000:PA[x]引脚
0100:PE[x]引脚
0001:PB[x]引脚
0101:PF[x]引脚
0010:PC[x]引脚
0110:PG[x]引脚
0011:PD[x]引脚
(6) 外部中断配置寄存器3 :EXTIXR3
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
- | |||||||||||||||
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
EXTI11[3:0] | EXTI10[3:0] | EXTI9[3:0] | EXTI8[3:0] |
EXTIx[3:0]:EXTIx配置(x = 8~11)
0000:PA[x]引脚
0100:PE[x]引脚
0001:PB[x]引脚
0101:PF[x]引脚
0010:PC[x]引脚
0110:PG[x]引脚
0011:PD[x]引脚
(7) 外部中断配置寄存器4 :EXTIXR4
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
- | |||||||||||||||
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
EXTI15[3:0] | EXTI14[3:0] | EXTI13[3:0] | EXTI12[3:0] |
EXTIx[3:0]:EXTIx配置(x = 12~15)
0000:PA[x]引脚
0100:PE[x]引脚
0001:PB[x]引脚
0101:PF[x]引脚
0010:PC[x]引脚
0110:PG[x]引脚
0011:PD[x]引脚
(8) APB2外设时钟使能寄存器 :APB2ENR
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
- | |||||||||||||||
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
- | USART1EN | - | SPI1EN | TIM1EN | ADC2EN | ADC1EN | - | IOPEEN | IOPDEN | IOPCEN | IOPBEN | IOPAEN | - | AFIOEN |
Bit 14:USART1时钟使能(写1开启,写0关闭)
Bit 12:SPI1时钟使能(写1开启,写0关闭)
Bit 11:TIM1时钟使能(写1开启,写0关闭)
Bit 10:ADC2时钟使能(写1开启,写0关闭)
Bit 9:ADC1时钟使能(写1开启,写0关闭)
Bit 6:GPIOE时钟使能(写1开启,写0关闭)
Bit 5:GPIOD时钟使能(写1开启,写0关闭)
Bit 4:GPIOC时钟使能(写1开启,写0关闭)
Bit 3:GPIOB时钟使能(写1开启,写0关闭)
Bit 2:GPIOA时钟使能(写1开启,写0关闭)
Bit 0:辅助功能IO时钟使能(写1开启,写0关闭)
/***************************************************
Name :EXIT_Config
Function :外部中断配置
Parameter :
GPIOx:0~6,代表GPIOA~G
BITx:需要使能的位
TRIM:触发模式
1:下升沿
2:上降沿
3:任意电平触发
Return :None
***************************************************/
void EXIT_Config( u8 GPIOx, u8 BITx, u8 TRIM )
{
u8 EXTADDR ;
u8 EXTOFFSET ;
EXTADDR = BITx/4 ; //得到中断寄存器组的编号
EXTOFFSET = ( BITx%4 )*4 ;
RCC->APB2ENR |= 0x01 ; //使能io复用时钟
AFIO->EXTICR[ EXTADDR ] &= ~( 0x000F<<EXTOFFSET ); //清除原来设置
AFIO->EXTICR[ EXTADDR ] |= GPIOx<<EXTOFFSET ; //EXTI.BITx映射到GPIOx.BITx
EXTI->IMR |= 1<<BITx ; //开启line BITx上的中断
if( TRIM&0x01 ) EXTI->FTSR |= 1<<BITx ; //下降沿触发
if( TRIM&0x02 ) EXTI->RTSR |= 1<<BITx ; //上升降沿触发
}
(1)添加用到的NVIC寄存器组和EXTI寄存器组的定义。
(2)定义寄存器组地址
上图就是添加子函数声明,为了用于其他文件调用。
(1)在STM32时钟配置函数之前增加复位时钟和中断的功能,最终函数如下图所示。
(2)添加刚才的两个子函数
至此,sys文件里面最基础的函数就全部添加完毕了。
全部0条评论
快来发表一下你的评论吧 !