1.1优先级分组 首先,我们先通过标识来解释手册里NVIC向量表的含义:
^' F+ c! Q4 u7 k& B2 B8 A3 WCore-M4内核最多支持256级的可编程优先级。用8位来表示优先级级别,,优先级级别分为8组,分别是组0~组7,如表1.0所示 (8位范围:0~255) 表1.1 中断分组讲解 组号 | 抢占优先级 | 响应优先级 | 0 | 用高七位表示抢占优先级 0~127 如果CPU的中断分组选择为“组 0”,则 抢占优先级可以设置为0~127,注意:数字越小,级别越高。 | 最低表示响应优先级 0~1 响应优先级可以设置为0或者1,注意:数字越小级别越高。 | 1 | 用高六位表示抢占优先级 如果CPU的中断分组选择为“组 1”, 抢占优先级可以设置为0~63 | 低两位表示响应优先级 响应优先级可以设置为0~3 | 2 | 用高5位表示抢占优先级 如果CPU的中断分组选择为“组 2”, 抢占优先级可以设置为0~31 | 低三位表示响应优先级 响应优先级可以设置为0~7 | 3 | 用高4位表示抢占优先级 如果CPU的中断分组选择为“组 2”, 抢占优先级可以设置为0~15 | 低四位表示响应优先级 响应优先级可以设置为0~15 | 4 | 用高3位表示抢占优先级 如果CPU的中断分组选择为“组 2”, 抢占优先级可以设置为0~7 | 低五位表示响应优先级 响应优先级可以设置为0~31 | 5 | 用高2位表示抢占优先级 如果CPU的中断分组选择为“组 2”, 抢占优先级可以设置为0~3 | 低6位表示响应优先级 响应优先级可以设置为0~63 | 6 | 最高位表示抢占优先级 如果CPU的中断分组选择为“组 2”, 抢占优先级可以设置为0~1 | 低7位表示响应优先级 响应优先级可以设置为0~127 | 7 | | 8位表示响应优先级 响应优先级可以设置为0~255 | % r; J: B2 Y8 E g
如果用图来形象表示,则看图1.1-8位中断分组 : ( j3 h+ K: C& v# C% ^4 N9 b( c) e
+ Q% V7 ?7 H1 f
1.1 8位中断分组 stm32为了节省材料成本,并没有完全使用这8位,它忽略低4位。如下图1-2
2 u+ x H- Q1 t: z+ q8 e2 z1.2 高位分组
% K$ r h- b; o4 w* d7 R- J M 表1.2 裁剪分组讲解 组号 | 中断优先级分组说明 | 抢占优先级等级范围 | 响应优先级等级范围 | 3 | 所有4位用于指定抢占优先级 | 0~15 | 不可设置 | 4 | 最高3位用于指定抢占优先级,最低1位用于指定响应优先级 | 0~7 | 0~1 | 5 | 最高2位用于指定抢占优先级,最低2位用于指定响应优先级 | 0~3 | 0~3 | 6 | 最高1位用于指定抢占优先级,低3位用于指定响应优先级 | 0~1 | 0~7 | 7 | 所有4位用于指定响应优先级 | 不可设置 | 0~15 | : A7 \4 _% [+ c2 I9 l+ I: F
1 R* q. h1 q6 D2 ~) x6 z% H1.2 NVIC中断中断控制器相关函数NVIC分组设置void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) 位置:core_cm4.h的1453行 作用:设置优先级分组。 参数:PriorityGroup优先级分组组号 举例:STM32的优先级分组设置为组5,则对应的代码如下:NVIC_SetPriorityGrouping(5); NVIC具体中断优先级编码uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) 作用:设置抢占优先级和响应优先级的级别 位置:core_cm4.h的1610行 参数:PriorityGroup优先级分组组号;PreemptPriority:抢占优先级;SubPriority:响应优先级 返回值:32位的编码值,编码值用于中断优先级设置 举例:优先级分组选择为组5,抢占优先级为2,响应优先级为2,代码如下: u32 prio; prio = NVIC_EncodePriority(5,2,2); NVIC中断优先级设置void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) 作用:将优先级分组情况以及抢占优先级和响应优先级设置到响应的中断。 参数: IRQn :中断通道编号。 priority:是NVIC_EncodePriority函数的返回值 举例:设置串口1全局中断的优先级分组选择为组5,抢占优先级为2,响应优先级为3 对应的代码: u32 prio; prio = NVIC_EncodePriority(5,2,3); NVIC_SetPriority(37,prio); 也可以写成NVIC_SetPriority(USART1_IRQn,prio); NVIC中断使能void NVIC_EnableIRQ(IRQn_Type IRQn) 作用:使能中断通道 参数:IRQn :中断通道编号。 举例:使能串口1全局中断,NVIC_EnableIRQ(37); 可以写成NVIC_EnableIRQ(USART1_IRQn); NVIC中断禁能void NVIC_DisableIRQ(IRQn_Type IRQn) 作用:禁止中断通道。 参数:IRQn :中断通道编号。 举例:禁止串口1全局中断,NVIC_DisableIRQ(37); 1.3 实例代码之串口中断: - #include "stm32f4xx.h"
% s* b, ?/ y% ~2 Z9 E - . F$ a; ]: y1 U, B
- //PA9 ----TXD--发送数据 (站在芯片角度)
- a0 ?4 {6 {# [/ A0 Y' v1 r5 l - //PA10 --- RXD--接收收据 (站在芯片角度)1 Y8 _+ ?5 q1 R+ O
- void Usart1_Init(u32 baudRate) @2 ]8 V3 n Z. V B0 P
- {3 ^% o( a1 I3 E9 m; I3 _
- u32 prio;
9 Q: Y! \6 G( }9 { - float USARTDIV;' ^: d/ D8 {5 e' H1 Z
- u16 Mantissa; //整数
+ J- ?, n/ Q( | - u8 Fraction; //小数3 J$ ~. I% f& c* D& |! G5 K
/ K2 _. C6 ?# n% o$ F- /****使能GPIOA的时钟***/; r- z$ j5 G K1 ~2 }
- RCC->AHB1ENR |= 1<<0;) p3 Q8 Z: _0 u U+ F* w
1 s* p* u4 D4 f+ ?# |- /****配置PA10为复用功能+上拉***/
7 `, U' K; N3 _$ J. \0 N9 Q; q - GPIOA->MODER |= 2<<20;//复用功能1 U! s- t2 D3 P7 z( |! ~) V e
- GPIOA->PUPDR |= 1<<20;//上拉
* x# F- P' |4 h - /****配置PA9位复用功能+推挽***/
( J) l6 A: z' f: y; H2 [0 J - GPIOA->MODER |= 2<<18;//复用功能
. R: A2 {2 {& Q v3 T0 E. D - GPIOA->OTYPER &=~(1<<9);//推挽
j1 S1 L5 K B4 u& @ - ! b0 q! p6 y* u' s
- /****PA9选择复用功能7,TXD***/& G) d; u" F* ]2 s; E
- GPIOA->AFR[1] |= 7<<4 ;
: G, h Y" G- V- z5 j& A - /****PA10选择复用功能7,RXD***/
7 H! }( {+ |* y: X/ ?3 u9 W2 g, y - GPIOA->AFR[1] |= 7<<8 ;
5 r( t- _) R7 K+ x( n5 u - : v0 \5 f# a, c/ ]7 ] s8 i# \$ R
- /****使能串口1的时钟***/
- f' G7 M- B% O0 {5 O8 \) N. ~9 E - RCC->APB2ENR |= 1<<4;
' Y+ E, `7 t* _! Z6 I
^! o( R, f& h4 t/ h- /****设置数据帧格式***/
; w H7 p7 l" n$ @ z- R - USART1->CR1 |= 1<<15;//OVER8设置为1 p; f7 o* R& W9 v
- USART1->CR1 &=~(1<<12);//将串口1的数据帧设置为“1 起始位, 8 数据位, n 停止位 ”, x8 g0 e2 C, s5 ~9 l3 l) P
- USART1->CR2 &=~(3<<12);//1位停止位6 O) }6 X2 u3 V& n
- USART1->CR1 &=~(1<<10);//禁止奇偶校验* j; v* O/ M, E, n( b% s& ~ s. k
-
5 p8 \' J0 |0 }$ L w0 p - /****设置波特率***/7 H h# y4 \! K3 z) P
- //USARTDIV = fCK/8*(2- OVER8 )/TxRx 波特率
) _ g0 s, b- w# g; q, _
# F5 x8 P5 J$ W: |! E, F8 F/ U- USARTDIV = (float)84000000/8/baudRate;
0 }! y6 Z* j# ], U7 y# i! \ - Mantissa = (int)USARTDIV;& s/ m& G# k0 h: j, G5 J
- Fraction = (u8)((USARTDIV-Mantissa)*16);- U9 e. }0 J2 Z& C( V }4 [2 G5 ~
- USART1->BRR = Mantissa<<4 | Fraction;
8 d6 m* F# Z8 k - 7 z, ?* B% l w3 C
- 7 U4 |6 J5 a% {( ~7 r3 t9 j% k
- USART1->CR1 |= 1<<5; //使能串口接收中断
: g) F$ o- r# X - NVIC_SetPriorityGrouping(5); //设置优先级分组设置为组5,注意:一个工程只能有一个分组0 w; |- S2 N! q/ W% k; P: J
- prio = NVIC_EncodePriority(5,2,2); //组5,抢占优先级为2,响应优先级为22 \( @; Z' D" M) ?
- NVIC_SetPriority(USART1_IRQn,prio);3 ]7 V: E, v2 q6 U
- NVIC_EnableIRQ(USART1_IRQn); //使能串口1中断通道USART1_IRQn==37 也可以用37表示串口1的通道编号( X! d, B# D4 `1 G! H9 ?
-
' H! U/ X% P# ?1 e; r - USART1->CR1 |= 1<<3;//使能发送器
% U' g3 ~7 G: {% h' [ - USART1->CR1 |= 1<<2;//使能接收器2 G! k; ]1 g+ P+ s; u( K
- USART1->CR1 |= 1<<13;//使能串口1
* w: F. U: ` m' L3 q, G9 R1 z - }
0 ^* m9 j5 l& R. L7 `2 B - //中断服务程序代码,在接收到一个字节是会进入串口中断服务函数- }3 Z$ A y4 c1 {( @7 l% C" L9 Z
- void USART1_IRQHandler(void)
8 G( Z) n. {( c - {0 s. M# J( y/ l9 L6 Y( ]+ ]+ f
- u8 data;: B; W# f1 K0 p% w0 J
- if(USART1->SR&(1<<5))8 B2 |9 Z+ _( K* B! P I9 {2 B) m
- {
& v* {* g3 K& G' @. c% h- F - data = USART1->DR;' m4 H' z9 z9 D& g% q
- /*******接收到一个字节原样回发*******/: n6 i3 d) x! z8 `: Q
- USART1->DR = data;2 r: V, e$ J! M9 x
- while(!(USART1->SR&(1<<6))); ! o$ \$ s. t7 J# J) A
- USART1->SR &=~(1<<6); //清零; `7 z- Q$ l/ G$ a# D/ ^
- }
! L' v/ t1 F/ M0 R( _5 Z - }
复制代码 4 H* l8 Y: E: n+ R4 }( e5 y6 V
|