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

NVIC中断优先级管理(中断向量表)

[复制链接]
STMCU-管管 发布时间:2020-9-14 12:57

Cortex-M3内核支持256个中断,其中包含了16个内核中断(异常)和240个外部中断,并且具有256级的可编程中断设置。但是,STM32并没有使用CM3内核的全部东西,而是只用了它的一部分。STM32有84个中断,包括16个内核中断(异常)和68个可屏蔽中断,具有16级可编程的中断优先级。而STM32F103系列上面,16个内核中断(异常)不变,而可屏蔽中断只有60个(在107系列才有68个)。

6 W" B7 G! w5 S: b4 t: e

注意一下:CM3的外部中断和STM32的外部中断不是一个概念。CM3:除了内核异常之外的都是外部中断;STM32:外部中断EXTI只有6个

其实,内核中断也叫内核异常。

) Z3 D/ W8 r; C8 `( y

  • 中断是指系统停止当前正在运行的程序转而其他服务,可能是程序接收了比自身高优先级的请求,或者是人为设置中断,中断是属于正常现象。
  • 异常是指由于cpu本身故障、程序故障或者请求服务等引起的错误,异常属于不正常现象。; T. ^, [  X. i, A! N
. ]6 n0 ]$ g4 B1 r8 n' I
1 V( p4 r& x3 k5 O; c8 [

因此,下面就直接介绍一下STM32F103系列的16个内核中断(异常)、60个中断:

1 ^# L+ m6 |6 |8 d  X

1.png


; q7 x- V8 @3 E& F1 o0 J$ O* v


* g+ H0 t4 Y% z; C7 r/ _# H( e  s7 `

在中断向量表中从优先级7-66(中断号从0-59)代表着STM32F103的60个中断。优先级号越小,优先级越高。当表中的某处异常或中断被触发,程序计数器指针(PC)将跳转到该异常或中断的地址处执行,该地址处存放这一条跳转指令,跳转到该异常或中断的服务函数处执行相应的功能。因此,异常和中断向量表只能用汇编语言编写。


$ V3 u7 T) D" Q) Z; w: w2 x8 ^

在MDK中,有标准的异常和中断向量表文件可以使用(startup_stm32f10x_hd.s),在其中标明了中断处理函数的名称,不能随意定义。而中断通道NVIC_IRQChannel(即IRQn_Type类型)是在stm32f10x.h文件中进行了宏定义。

- o: t5 \- I! B

什么是NVIC?即嵌套向量中断控制器(Nested Vectored Interrupt Controller)。CM3的中有一个强大而方便的NVIC,它是属于Cortex内核的器件,中断向量表中60个中断都由它来处理。NVIC是Cortex-M3核心的一部分,关于它的资料不在《STM32的技术参考手册》中,应查阅ARM公司的《Cortex-M3技术参考手册》。Cortex-M3的向量中断统一由NVIC管理。


+ R; u2 p: o% v% {; h

NVIC的核心功能是中断优先级分组、中断优先级的配置、读中断请求标志、清除中断请求标志、使能中断、清除中断等,它控制着STM32中断向量表中中断号为0-59的60个中断!!外部中断信号从核外发出,信号最终要传递到NVIC(嵌套向量中断控制器)。NVIC跟内核紧密耦合,它控制着整个芯片中断的相关功能。

1 c' k+ e6 Z$ c4 `" a% q
STM32中断优先级分组中断优先级分组寄存器

这60个中断,怎么管理呢?这就涉及到STM32的中断分组。STM32可以将中断分成5个组,分别为组0-4;同时,对每个中断设置一个抢占优先级和响应优先级。分组配置是由SCB->AIRCR寄存器的bit10-8来定义的。SCB->AIRCR是在哪里的呢?由于这是CM3内核定义的,在文档《Cortex-M3权威指南(中文)》中能查找到。


' X9 _9 |* f$ i+ C8 y) |3 x& \

具体的分配关系如下所示:

% ]% o3 Q  I) A$ a* E9 @! H

AIRCR中断分组设置表5 a, g5 M& l" S, w
2 C  e# h! c8 r) W# o4 `* U

( i, |2 `" d& }& b  l7 x
3.png
/ T) N6 b  m& D) \- ~( c
* R1 U* p* ^, h1 X3 s6 o7 p

其中AIRCR寄存器来确定是用哪种分组,IP寄存器是相对应于那种分组抢占优先级和响应优先级的分配比例。例如组设置成3,那么此时所有的60个中断优先寄存器高4位中的最高3位是抢占优先级,低1位为响应优先级。CM3中定义了8个Bit用于设置中断源的优先级,而STM32只选用其中的4个Bit。

  b/ W8 A8 G7 B3 {$ m; F. `

抢占优先级的级别高于响应优先级,而数值越小所代表的的优先级越高。

- n' [8 l5 J1 b7 E0 h

介绍一下抢占优先级、响应优先级的区别:


9 a3 F8 w' Z- I5 W! k

  • 高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的;
  • 抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断;
  • 抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行;
  • 如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;
    ( i; o. h6 X/ m" t" o8 W

    - r. S- t/ \- Y- C
0 j$ X8 Y! Y2 h& C

" W5 P+ e2 u& e- ~$ x  s/ D% |

除此之外有两点需要注意:


+ E& M5 @( U$ X. V) Z5 a

  • 打断的情况只会与抢占优先级有关, 和响应优先级无关!
  • 一般情况下,系统代码执行过程中,只设置一次中断优先级分组,比如分组2,设置好分组之后一般不会再改变分组。随意改变分组会导致中断管理混乱,程序出现意想不到的执行结果。+ f; F" p- c2 U. A& l
    1 s  V( I: g7 w
" P: g# @* `# p
# z7 J( ]$ z  i5 |4 i
中断优先级分组库函数
5 U2 d5 {# m1 F0 G' S, D

CM3核的优先级分组方式,使用的设置函数NVIC_SetPriorityGrouping()。

' F+ d- u# F$ o0 o" G. p

接下来介绍STM32的中断优先级分组函数NVIC_PriorityGroupConfig(),用来进行中断分组设置的,此函数是在固件库下misc.c文件中(文件目录是:

  A' y1 v' r2 j! c2 J, I$ R7 _% N* R) o

STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\src\misc.c):

: j1 O: }+ c9 r4 n+ B

  1. ; \) a! y( y; u+ [; A5 A) j: N
  2. void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
    2 V" p% m' Y2 @+ b& S9 W
  3. {
    7 |; M3 X! I+ n2 ?1 w; O4 U6 Q
  4.   /* Check the parameters */
    ; M" @" g/ z2 R: A
  5.   assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
    " W# _: g8 @* w# h
  6.   
    . E: X6 q1 k* q4 Q
  7.   /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
    + l& u; L0 z- q4 x1 C: @: ~
  8.   SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;& }, K- I6 ^+ o" f! @8 Y! g# r
  9. }
复制代码
4 C# Z6 `' {; E7 p) K$ l

函数的参数的取值,是在同文件中进行宏定义的:


/ {1 z! W4 }  Y# m

  1. #define NVIC_PriorityGroup_0         ((uint32_t)0x700) /*!< 0 bits for pre-emption priority& {: N; O. ~7 [! O
  2.                                                             4 bits for subpriority */
    % k$ S+ b3 {: Y6 G+ b1 V) b
  3. #define NVIC_PriorityGroup_1         ((uint32_t)0x600) /*!< 1 bits for pre-emption priority+ p; M' r% i: a" J+ [
  4.                                                             3 bits for subpriority */
    ; u& f2 I+ q6 V) h9 q
  5. #define NVIC_PriorityGroup_2         ((uint32_t)0x500) /*!< 2 bits for pre-emption priority/ S) u# |7 }- C: I/ y: w! X
  6.                                                             2 bits for subpriority */
    - Y! Q" Y2 m! P, H; s
  7. #define NVIC_PriorityGroup_3         ((uint32_t)0x400) /*!< 3 bits for pre-emption priority
    1 C8 k0 Q' C) w- q" ~
  8.                                                             1 bits for subpriority */
    % _6 @$ N+ P: j& F0 F: E/ G
  9. #define NVIC_PriorityGroup_4         ((uint32_t)0x300) /*!< 4 bits for pre-emption priority
    % P3 O. g+ ^% _
  10.                                                             0 bits for subpriority */  C  g8 n/ P/ Y1 @% Z3 e2 i
复制代码
4 T7 @8 a% {( G
$ _/ C9 @; p. a7 |9 z- K; t
STM32中断优先级管理

! w# P, y, E, F; e$ n. E6 K
1 A4 k9 N6 l  f% h$ i中断优先级设置寄存器
" o' X. t! |+ l! H* z

分组设置好了之后,怎么设置单个中断的抢占优先级和响应优先级?

6 ^$ x$ L5 J4 ^8 R% c

MDK为与NVIC相关的寄存器定义了如下的结构体,控制着中断向量表中60个中断(由于与中断内核有关,定义在core_cm3.h文件中):

, b$ m# _, h& k) z5 M5 H

  1. * N5 G+ Z1 s, y. @5 n# `0 |8 f
  2. typedef struct
    % o' R4 V8 M6 X8 _9 {
  3. {5 X& F, G' b5 Y' ^
  4.   __IO uint32_t ISER[8];                      /*!< Offset: 0x000  Interrupt Set Enable Register           */1 w2 s1 f3 @' A
  5.        uint32_t RESERVED0[24];                                   ! g! K) t: _- L2 X: F, f
  6.   __IO uint32_t ICER[8];                      /*!< Offset: 0x080  Interrupt Clear Enable Register         */
    , F$ V3 E% V* j# G0 t1 e6 D
  7.        uint32_t RSERVED1[24];                                    
    / ^7 F& N* L$ D; t1 c! X
  8.   __IO uint32_t ISPR[8];                      /*!< Offset: 0x100  Interrupt Set Pending Register          */
    . I+ x- Z) _4 m3 V" s! l6 K7 f, H3 E
  9.        uint32_t RESERVED2[24];                                   
    ; d5 c' l+ d0 h$ `
  10.   __IO uint32_t ICPR[8];                      /*!< Offset: 0x180  Interrupt Clear Pending Register        */
    3 k( @0 m( x" ~& ^. D
  11.        uint32_t RESERVED3[24];                                   
    - ^1 z: ?' A3 `' b& N
  12.   __IO uint32_t IABR[8];                      /*!< Offset: 0x200  Interrupt Active bit Register           */
    % s% g3 n, l/ h
  13.        uint32_t RESERVED4[56];                                   * p& ^2 ?& r0 x2 i. A4 a
  14.   __IO uint8_t  IP[240];                      /*!< Offset: 0x300  Interrupt Priority Register (8Bit wide) */
    4 M7 T& _% y8 b" t7 |7 [8 Z
  15.        uint32_t RESERVED5[644];                                 
    5 |" f1 r9 K* [; k. G( {
  16.   __O  uint32_t STIR;                         /*!< Offset: 0xE00  Software Trigger Interrupt Register     */8 r  E* j- b% u3 \. {- l
  17. }  NVIC_Type;
复制代码
/ F6 U, P  E+ G9 S! M, d

. H* X4 u2 m" ^0 C! T

我们依次介绍一下这些寄存器:

2 o( O& ]; L1 d( _) m' f6 o

先介绍几个寄存器组长度为8,这些寄存器是32位寄存器。由于STM32只有60个可屏蔽中断,8个32位寄存器中只需要2个就有64位了,每1位控制一个中断。

% u1 b+ K. ~' s- O+ i

  • ISER[8](Interrupt Set-Enable Registers):中断使能寄存器。其中只使用到了ISER[0]和ISER[1],ISER[0]的bit0~bit31分别对应中断0~31。ISER[1]的bit0~27对应中断32~59。要使能某个中断,就必须设置相应的ISER位为1,使该中断被使能(这仅仅是使能,还要配合中断分组、屏蔽、I/O口映射等设置才算完整)。具体每一位对应哪个中断参考stm32f103x.h里面第140行。
  • ICER[8](Interrupt Clear-Enable Registers):中断移除寄存器。该寄存器的作用于ISER相反。这里专门设置一个ICER来清除中断位,而不是向ISER位写0,是因为NVIC的寄存器写1有效,写0无效。
  • ISPR[8](Interrupt Set-Pending Registers):中断挂起控制寄存器。通过置1可以将正在进行的中断挂起,执行同级或者更高级别的中断。写0无效。
  • ICPR[8](Interrupt Clear-Pending Registers):中断解挂控制寄存器。通过置1可以将正在挂起的中断解挂。写0无效。
  • IABR[8](Interrupt Active-Bit Registers):中断激活标志位寄存器。这是一个只读寄存器,可以知道当前在执行的中断是哪一个(为1),在中断执行完后硬件自动清零。; G6 ?( c, Z, Z8 s( l
  • 2 |$ W1 u, G. f
    * f2 _! h& ~& A3 P- ?- l$ Q

最后,介绍一个寄存器组长度为240,这个寄存器为8位寄存器。240个8位寄存器,每个中断使用一个寄存器来确定优先级。由于CM3由240个外部中断,所以这个寄存器组的数目就是240(注意与上面寄存器的区别,一个是一个寄存器控制一个,一个是一位控制一个)。


7 }% Y  Q) [4 Z& L$ C* Z

  • IP[240](Interrupt Priority Registers):中断优先级控制的寄存器。这是用来控制每个中断的优先级。由于STM32F10x系列一共60个可屏蔽中断,故使用IP[59]~IP[0]。其中每个IP寄存器的高4位[7:4]用来设置抢占和响应优先级(根据分组),低4位没有用到。而两个优先级各占几个位又要由上面讲到的中断优先级分组决定。- n3 H; k, j5 K

    1 k. ^' S+ M6 _2 h$ S% \* `/ [

+ S8 X' J9 x  R0 @+ `
$ F( p3 w" X5 m( U. u9 K9 K7 D9 {
中断优先级设置库函数1 y) c# c: l9 r, {6 }6 w- q! T8 _

接下来介绍如何使用库函数实现中断优先级管理,这里使用NVIC_Init()函数来进行对每个中断优先级的设置(misc.c文件中)

* X8 u# B' {8 V* Q5 l0 {5 f

  1.   K" o8 U) X* e+ s
  2. void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)) ]' L  V- U* F6 Y3 }6 l& }& X
  3. {# L; `/ Z: i! U" u
  4.   uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
    . t3 a& g4 t& L
  5.   . w' i& W/ i+ ^" g$ O# P' ?! F
  6.   /* Check the parameters */6 O: b0 t# w6 f& u) e! V
  7.   assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));8 D9 P# e5 j: G  |8 Z, s  c) J
  8.   assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));  - Q5 Z/ ]. M6 x! ^% W( \0 C; K
  9.   assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));: ^' x; l* n( E$ @2 M
  10.     * l. H, t# S; j$ e1 Y. `8 ]* c
  11.   if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
    0 \5 Y3 m6 ]  v% i
  12.   {) z# H6 ]5 n, |/ E
  13.     /* Compute the Corresponding IRQ Priority --------------------------------*/    8 w* \! p( e9 W
  14.     tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;: b3 d' s& ?' Z* y
  15.     tmppre = (0x4 - tmppriority);
    , ?$ ?+ G3 H: f* w! s( S8 Z/ J
  16.     tmpsub = tmpsub >> tmppriority;  p& ~1 {0 }3 `% d% S" A
  17. ( H9 F' V' P! s. Q) a# C2 d  m7 a
  18.     tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;& P; u+ N) l( ~* v( s: O
  19.     tmppriority |=  NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
    * u: _) x" r0 u  H- Q+ T& V$ {
  20.     tmppriority = tmppriority << 0x04;* y" D. p0 U: B6 P; e
  21.         $ J) N8 i) L: b
  22.     NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;1 y4 u! C2 z+ k  Y3 |
  23.     % M& [1 A& l6 n$ y# o: `5 A
  24.     /* Enable the Selected IRQ Channels --------------------------------------*/& H: v" D3 }6 @& T
  25.     NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
    % y4 u; p, u; v- G, T
  26.       (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
    * G( x% q7 t, d3 P# X
  27.   }
    1 t; @/ H" d4 _. D6 X
  28.   else
    % [) A3 r6 l  r/ S% `) `
  29.   {
    ; b9 A9 g0 w% s) ^" d& S
  30.     /* Disable the Selected IRQ Channels -------------------------------------*/
    9 Q# j& Z% e  u4 y, H
  31.     NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =) Y3 X2 x9 I& i. _5 E- v
  32.       (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
    1 @$ z  D( e- F% l4 J
  33.   }2 V! }& y% i8 w* i6 Y4 D3 p
  34. }. Z/ U% \3 B; }1 \# o, U& s# }2 p
复制代码
5 t4 n4 S7 y3 T4 }/ q4 B' }

其中,NVIC_InitTypeDef为一个结构体,它的成员变量为:


" V. d" e  m# l& d  L


  1. * i; u1 b" e: f
  2. typedef struct
    : C' w, x: _) x6 u7 H  I' E
  3. {! Z; Y8 h% O2 _; t. q
  4.   uint8_t NVIC_IRQChannel;                    /*!< Specifies the IRQ channel to be enabled or disabled.# K( z7 K+ e, {
  5.                                                    This parameter can be a value of @ref IRQn_Type ( _  ~8 m$ S$ h# A: F7 q: _  r
  6.                                                    (For the complete STM32 Devices IRQ Channels list, please$ @) G( _" y" @8 y  R
  7.                                                     refer to stm32f10x.h file) */& U4 i/ _( t5 k, D( p
  8. 9 d3 s( K) ?; f2 B3 t$ G  y2 E
  9.   uint8_t NVIC_IRQChannelPreemptionPriority;  /*!< Specifies the pre-emption priority for the IRQ channel# z. e4 l+ ^* L4 Z0 ~7 e
  10.                                                    specified in NVIC_IRQChannel. This parameter can be a value" W8 n; @1 g" H* E
  11.                                                    between 0 and 15 as described in the table @ref NVIC_Priority_Table */- E* }3 N( }* p$ A! U

  12. 5 A6 a" p; A' ~) N
  13.   uint8_t NVIC_IRQChannelSubPriority;         /*!< Specifies the subpriority level for the IRQ channel specified0 g' o  m+ G# U7 m& e
  14.                                                    in NVIC_IRQChannel. This parameter can be a value
    % B( Q8 A& f" i9 z
  15.                                                    between 0 and 15 as described in the table @ref NVIC_Priority_Table */
    - b7 ^) ^  V% D% p

  16. 4 m4 I8 S- P8 B2 v5 j; A1 M
  17.   FunctionalState NVIC_IRQChannelCmd;         /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel
    1 [2 Q4 y- ?0 }; B0 f, }7 U
  18.                                                    will be enabled or disabled.   J* `) j% s. W% l' j* H5 ^
  19.                                                    This parameter can be set either to ENABLE or DISABLE */   * ~2 }; j* E7 Y: w, l) c$ J. {
  20. } NVIC_InitTypeDef;
    ! k2 ?3 S6 j. A$ W( V
复制代码

3 x- {: K  y1 f0 F

NVIC_InitTypeDef结构体有4个成员变量:

  • NVIC_IRQChannel:定义初始化的是哪一个中断,这个可以在stm32f10x.h文件中查到每个中断对应的名字,如USART1_IRQn;
  • NVIC_IRQChannelPreemptionPriority:定义此中断的抢占优先级别;
  • NVIC_IRQChannelSubPriority:定义此中断的响应优先级别;
  • NVIC_IRQChannelCmd:该中断是否使能。) x7 W" t* ^) x: [

    , f7 Z: M# {8 d
$ M. k' h3 d/ D& @
; |2 `7 I: N  G' B

其实我们看NVIC_Init()函数内部使能中断,也是通过ISER寄存器配置的。这与我么之前的内容并不矛盾。函数内部使用NVIC->ISER,而NVIC是一个宏定义,

  1. #define NVIC     ((NVIC_Type *) NVIC_BASE)     /*!< NVIC configuration struct         */
复制代码

" f6 L: s2 K: y4 E1 V

也就是直接操作结构体来实现操作ISER寄存器。

比如,使能串口1中断,抢占优先级为1,响应优先级为2,初始化的方法为:


6 V1 Z, u4 P  H- o( a) I

  1. " H. C' g0 o, z2 n7 r8 @; B2 Z
  2. NVIC_InitTypeDef   NVIC_InitStructure;
    5 |1 U1 X+ F# Q. t" C, C( `0 P
  3. NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断
    2 G4 Q# {- @0 Q0 r5 Y5 ?
  4. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;// 抢占优先级为1
    3 [8 t+ L- J6 u' R  A4 n. L
  5. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// 子优先级位2
    / x. Q; `' X; t0 X, v& P
  6. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能( Z' H  T$ G5 Q& a
  7. NVIC_Init(&NVIC_InitStructure);        //根据上面指定的参数初始化NVIC寄存器
复制代码

0 V) n9 R! A: Y4 H* I9 A
! c0 A; _  T' C( X6 s总结与分析

. t% `  |. F$ y( C3 y0 t

最后总结一下中断优先级设置的步骤:

4 U; ~5 n0 Z4 C1 U; q

1、系统运行后先设置中断优先级分组。调用函数:

  1. void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
复制代码

0 y* I" `8 L: |! Z! M. T1 R

整个系统执行过程中,只设置一次中断分组;


% V& r9 }6 }/ L" h

2、针对每个中断,设置对应的抢占优先级和响应优先级:

  1. void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
复制代码
6 e; R. O: I+ P- e1 `- m

3、如果需要挂起/解挂,查看中断当前激活状态,分别调用相关函数即可。


; F# h% _9 z; O" l" w, ^7 h; e* q# O& ?4 u7 g
2.png
赞 1 收藏 1 评论0 发布时间:2020-9-14 12:57

举报

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