你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32之NVIC

[复制链接]
STMCU小助手 发布时间:2022-2-2 20:00
1.1优先级分组
首先,我们先通过标识来解释手册里NVIC向量表的含义:
810734-20191003085041023-632236589.png : q- e' V" Z' A2 W, n3 L$ r
Core-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
- A' h+ D. ^; g% z( {2 M( K
如果用图来形象表示,则看图1.1-8位中断分组 :

+ M# j( `7 L, y; P+ E! A7 i) M+ ^: n
810734-20191003081629753-759539393.png
& s/ x3 }6 I1 C( A5 a( K; f3 v
1.1 8位中断分组
stm32为了节省材料成本,并没有完全使用这8位,它忽略低4位。如下图1-2

$ s: K% f7 `. h. }( O
810734-20191003082134842-1067264450.png
1.2 高位分组
0 q8 M  E8 n' d1 Y9 b
                                        表1.2  裁剪分组讲解
组号中断优先级分组说明抢占优先级等级范围响应优先级等级范围
3所有4位用于指定抢占优先级0~15不可设置
4最高3位用于指定抢占优先级,最低1位用于指定响应优先级0~70~1
5最高2位用于指定抢占优先级,最低2位用于指定响应优先级0~30~3
6最高1位用于指定抢占优先级,低3位用于指定响应优先级0~10~7
7所有4位用于指定响应优先级不可设置0~15

& Q+ K5 ~3 E& J/ `0 X5 U7 M& h2 M7 E7 `6 X$ I9 D- s8 V
1.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 实例代码之串口中断:
  1. #include "stm32f4xx.h"
    & e7 U: w9 p4 ?+ O- e
  2. 8 U) _0 y4 M  V5 w: t- u
  3. //PA9 ----TXD--发送数据      (站在芯片角度)# h& [2 \0 j3 g% ]# x" B- I; c
  4. //PA10 --- RXD--接收收据    (站在芯片角度)
    ' K1 P9 }' X) u1 S. I
  5. void Usart1_Init(u32 baudRate)
    , k8 }- P" d$ `/ L$ m# R5 e9 v  L
  6. {
    7 a( ]* r( ~; b" `
  7.     u32 prio;  M- A3 L2 r0 x
  8.     float USARTDIV;1 L, C. y8 i5 ]0 m* _9 t1 A
  9.     u16 Mantissa;  //整数
    + A4 o+ }: C% b2 W7 C( X! o8 v
  10.     u8 Fraction;   //小数
    5 W# x9 y- X  n8 Y
  11. 3 j8 w  J8 y3 j1 n% h$ h" ^! ]
  12.     /****使能GPIOA的时钟***/
    * h& D+ _3 r, b' ]/ L% [( M$ g
  13.     RCC->AHB1ENR |= 1<<0;
    ' k7 ~# ]( e# ^0 H9 @! H: t8 Z

  14. ( i3 V7 `+ q4 V2 f
  15.     /****配置PA10为复用功能+上拉***/
    3 N" K: r" ]- B! K. Q8 F/ X; i/ h
  16.     GPIOA->MODER |= 2<<20;//复用功能$ j$ }$ K! e$ }: V- |
  17.     GPIOA->PUPDR |= 1<<20;//上拉& j2 P# p& a3 @) Y7 w
  18.     /****配置PA9位复用功能+推挽***/
    6 N9 B& k3 p# u) z7 n, P+ \/ j
  19.     GPIOA->MODER |= 2<<18;//复用功能* x( @6 R; {1 Q
  20.     GPIOA->OTYPER &=~(1<<9);//推挽
    8 R) ?* O$ `; E, q" f: {

  21. . j* [  `+ @, e8 h! w0 c+ E5 m
  22.     /****PA9选择复用功能7,TXD***/0 l+ {, H5 u# C. |, b4 d  c/ B' F
  23.     GPIOA->AFR[1] |= 7<<4 ;
    # g( @! y3 K5 m3 n' v
  24.     /****PA10选择复用功能7,RXD***/
    & a* u! M1 F0 I) \" u5 \+ k8 R# {. C
  25.     GPIOA->AFR[1] |= 7<<8 ;
    ; q$ ]. J& g. n3 a3 b' K
  26.     " d8 J& Y5 E3 k. D  Z
  27.     /****使能串口1的时钟***/
    ) x3 m3 n  u# d; h3 f3 Z
  28.     RCC->APB2ENR |= 1<<4;
    . ^5 @4 i9 s! X! ]

  29. , c3 p+ N; l6 C. F
  30.     /****设置数据帧格式***/9 Q2 o8 G5 c6 d+ p& d  e
  31.     USART1->CR1 |= 1<<15;//OVER8设置为1
    , p$ h( P/ J  F7 _: M# X' u
  32.         USART1->CR1 &=~(1<<12);//将串口1的数据帧设置为“1 起始位, 8 数据位, n 停止位 ”4 c$ H  S. H; u+ v& N
  33.     USART1->CR2 &=~(3<<12);//1位停止位
    7 X' S. f) X2 @# Q- {& [
  34.     USART1->CR1 &=~(1<<10);//禁止奇偶校验
    % v& ]9 D* r9 d* e' ?5 ^$ S5 `  _
  35.     ! H2 ]- q) R( q3 h/ Z
  36.     /****设置波特率***/
    : e6 v# _) A; a) [# B
  37.     //USARTDIV =  fCK/8*(2- OVER8 )/TxRx 波特率0 H$ Z8 ]4 F7 N
  38. 2 S* `5 @6 L9 n2 h
  39.     USARTDIV = (float)84000000/8/baudRate;
    $ N, d) N) r% `* O" R9 i: }
  40.     Mantissa = (int)USARTDIV;
      n% R8 N2 N9 }5 D0 I
  41.     Fraction = (u8)((USARTDIV-Mantissa)*16);
    . @  h) A8 V# t
  42.     USART1->BRR = Mantissa<<4 | Fraction;
    ; H6 S+ h% Y6 {' a: }& R
  43.       n) b5 m" T4 q  x, T
  44.     ! D. }( |" o6 Q" }
  45.     USART1->CR1 |= 1<<5;  //使能串口接收中断, S5 G' ~( u$ M3 z8 b
  46.     NVIC_SetPriorityGrouping(5);  //设置优先级分组设置为组5,注意:一个工程只能有一个分组, V7 R, G3 E. f' ~% g; f+ c
  47.     prio = NVIC_EncodePriority(5,2,2); //组5,抢占优先级为2,响应优先级为2. K$ @$ I, c: i. W" H
  48.     NVIC_SetPriority(USART1_IRQn,prio);/ z/ ]7 R+ `, ]* y/ G
  49.     NVIC_EnableIRQ(USART1_IRQn);  //使能串口1中断通道USART1_IRQn==37  也可以用37表示串口1的通道编号
    / A: c1 H) M0 p* a6 U
  50.      2 G+ V8 t. t1 V* ^! g
  51.     USART1->CR1 |= 1<<3;//使能发送器
    ' ?% Q: A# L8 |% W( L
  52.     USART1->CR1 |= 1<<2;//使能接收器
    ) T$ \5 i' P+ f, @" i8 h6 D9 x7 R- T0 O
  53.     USART1->CR1 |= 1<<13;//使能串口1
    ( F/ c8 K' E+ d0 x
  54. }
    % W2 L4 c' @1 B3 z2 ~
  55. //中断服务程序代码,在接收到一个字节是会进入串口中断服务函数
    3 H$ i3 {: |: S4 ~1 _5 O3 g$ k) K
  56. void USART1_IRQHandler(void)
    0 J8 c. z; I  g% H* U0 O
  57. {2 J$ v0 H' Q) r7 V: u, L
  58.     u8 data;" l# B) J% K8 B  K& q  t
  59.     if(USART1->SR&(1<<5)), s. T1 u! |1 h( _( Y3 s5 w- b# O
  60.     {3 E3 B9 O+ W5 T5 o
  61.         data = USART1->DR;4 b0 I  g' N1 d$ T" T
  62.         /*******接收到一个字节原样回发*******/
    % p+ y, B2 q" W
  63.         USART1->DR = data;$ a5 j& s  U5 f  r- u
  64.         while(!(USART1->SR&(1<<6))); ! F% |. w: O9 v( O, ~, l4 G
  65.         USART1->SR &=~(1<<6);  //清零; S- y' h: J2 H7 {8 A7 V1 v9 b
  66.     }
    , l5 E  S0 s: G+ U7 w% i
  67. }
复制代码
5 [3 G% k. ^' s  d' B3 `" A
收藏 评论0 发布时间:2022-2-2 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版