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

基于STM32CubeMX的SPI总线经验分享

[复制链接]
攻城狮Melo 发布时间:2023-7-1 18:56
1.SPI总线及W25QXX芯片
1.1 SPI总线简介
SPI全称Serial Peripheral Interface,即串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在EEPROM、FLASH、实时时钟、AD转换器,还有数字信号处理器和数字信号解码器之间。SPI是一种高速的、全双工、同步通讯总线,在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局节省空间提供了方便,正是这种简单易用的特性,如今越来越多的芯片集成了这种通讯协议。下图是SPI内部结构简易图
- s/ d2 ?0 [/ `! H6 W3 V" F
微信图片_20230701185542.png

/ K+ Y# y0 E+ K
从上图可以看出,主设备和从设备都有一个串行移位寄存器,主设备通过向它的SPI串行寄存器写入一个字节来发起一次传输,寄存器通过MOSI信号线将字节传送给从设备,从设备也将自已的移位寄存器中的内容通过MISO信号线返回给主设备。这样两个移位寄存器中的内容就被交换。外设的写操作和读操作时同步完成的,如果只进行写操作,主设备只需要忽略接收到的字节,如果主设备要进行读操作,就必须发送一个空字节来引发从设备的传输。
SPI接口一般使用4条线通讯,单向传输时也可以使用3条线,其中3条线为SPI总线(MISO,MOSI,SCLK),1条为SPI片选信号线(CS),它们的作用如下:

    5 t4 I2 i" {. {, v- A
  • MISO:主设备数据输入,从设备数据输出
  • MOSI:主设备数据输出,从设备数据输入
  • SCLK:时钟信号,由主设备产生
    + r! x% ~+ R& [9 W2 B+ ]+ P
  • CS:从设备片选信号,由主设备控制
    . o' U* d$ q6 I( l
    ' p) l- J# X+ e: }8 q9 s( e
SPI使用MOSI/MISO信号线来传输数据,使用SCLK信号线进行数据同步。MOSI/MISO数据线在SCLK的每个时钟周期传输1位数据,且数据输入输出是同时进行的。数据传输时,MSB先行或LSB先行没有硬性规定,但是两个SPI通讯设备之间必须使用同样的协定,一般都会采用MSB先行模式。
! ?8 E7 P/ p! ?7 f8 {4 V; ^& U当有多个SPI从设备与SPI主设备相连时,设备的MOSI/MISO/SCLK信号线并联到相同的SPI总线上,即无论有多少个从设备,都共同使用者3条总线;而每个从设备都有独立的1条CS信号线,该信号线独占主设备的一个引脚,即有多少个从设备就有多少条片选信号线。当主设备要选择从设备时,把该从设备的CS信号线设置为低电平,该从设备即被选中(片选有效),接着主设备开始与从设备进行SPI通讯。& P4 i1 r: l+ u( H; r  F! E
SPI总线根据时钟极性(CPOL)和时钟相位(CPHA)的配置不同,可以有四种工作方式:
    5 t" ^! c. Y" ]# \1 G2 t7 @' V
  • CPOL=0:串行同步时钟的空闲状态为低电平
  • CPOL=1:串行同步时钟的空闲状态为高电平
  • CPHA=0:在串行同步时钟的第一个跳变沿(上升或下降)数据被采样

    ) S/ b$ r3 k- q: S- B
  • CPHA=1:在串行同步时钟的第二个跳变沿(上升或下降)数据被采样
    6 o' b/ p  R* M9 h7 Y
    8 k6 v( ], u) ^( M$ Z
微信图片_20230701185539.png
4 _5 t2 F- q. m, }1 j! [. d& U
1.2 W25QXX芯片简介
W25QXX芯片是华邦公司推出的大容量SPI FLASH产品,该系列有W25Q16/32/62/128等。本例程使用W25Q64,W25Q64容量为64Mbits(8M字节):8MB的容量分为128个块(Block)(块大小为64KB),每个块又分为16个扇区(Sector)(扇区大小为4KB);W25Q64的最小擦除单位为一个扇区即4KB,因此在选择芯片的时候必须要有4K以上的SRAM(可以开辟4K的缓冲区)。W25Q64的擦写周期多达10万次,具有20年的数据保存期限。下表是W25QXX的常用命令表

! W; P* Y( B; t, h  ?+ a5 Y4 i
微信图片_20230701185536.png
$ u6 z2 D% I, r  ]( z( w9 l
2.硬件设计
D1指示灯用来提示系统运行状态,K_UP按键用来控制W25Q64数据写入,K_DOWN按键用来控制W25Q64数据读取,串口1用来打印写入和读取的数据信息

    ; D* f" N- {/ k- d% P4 m
  • 指示灯D1
  • USART1串口
  • W25Q64
      ?0 R8 H/ l) M# `
  • K_UP和K_DOWN按键/ {) @+ u% Z; ]2 H5 F% W2 l% ]: q

    + n- Q% Y, [: j8 W3 w& K. i

    7 Q, f& [& S" b" i$ e- Z
微信图片_20230701185531.png
1 s2 U; g" ^" {$ F, W7 n
9 Y9 o# f, @2 M' _; Q& x  K; c) Q9 ~
3.软件设计
3.1 STM32CubeMX设置
➡️ RCC设置外接HSE,时钟设置为72M
➡️ PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平
➡️ USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位
➡️ PA0设置为GPIO输入模式、下拉模式;PE3设置为GPIO输入模式、上拉模式
➡️ PG13设置为GPIO推挽输出模式、上拉、高速(片选引脚)
➡️ 激活SPI2,不开启NSS,数据长度8位,MSB先输出,分频因子256,CPOL为HIGH,CPHA为第二个边沿,不开启CRC检验,NSS为软件控制
微信图片_20230701185526.png
; G# g6 g5 @! B8 P# w4 B

. ~" ^$ L$ C1 k2 q6 a
➡️输入工程名,选择路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码

- H+ F& J" O, |) d) ]& W
3.2 MDK-ARM软件编程
➡️ 在spi.c文件下可以看到SPI2的初始化函数,片选管脚的初始化在gpio.c中

6 S% H9 E" r  |3 m" U# e
  1. void MX_SPI2_Init(void){+ {% o' n' r+ [
  2.   hspi2.Instance = SPI2;
    % H# L+ {1 j, b; `: w# f) q7 N
  3.   hspi2.Init.Mode = SPI_MODE_MASTER;//设置为主模式
    1 g, V; |& t) u
  4.   hspi2.Init.Direction = SPI_DIRECTION_2LINES;//双线模式- s& k4 ?6 c# W. v; R+ D
  5.   hspi2.Init.DataSize = SPI_DATASIZE_8BIT;//8位数据长度2 k, M1 [, i' K  U
  6.   hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;//串行同步时钟空闲状态为高电平' }, P; j' i$ A) _5 h+ I
  7.   hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;//第二个跳变沿采样
    4 L3 d6 p1 I* N
  8.   hspi2.Init.NSS = SPI_NSS_SOFT;//NSS软件控制
    4 G" M6 E0 U; z
  9.   hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;//分配因子256
    $ z& t4 A- J9 x* j' m' L1 R# q
  10.   hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;//MSB先行
    0 {; |0 R2 c% n. r8 H; r
  11.   hspi2.Init.TIMode = SPI_TIMODE_DISABLE;//关闭TI模式
      N9 I$ C$ M( J9 p
  12.   hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;//关闭硬件CRC校验
    ( E# }& X8 |/ J+ ]/ f3 {3 }5 b
  13.   hspi2.Init.CRCPolynomial = 10;' g  }. _/ w( P9 h5 ?
  14.   if (HAL_SPI_Init(&hspi2) != HAL_OK){
    6 Z3 ^1 L0 x4 d6 z2 _. a
  15.     Error_Handler();
    1 {4 j; L9 B! S' @
  16.   }
    - O" m6 c9 x: N/ p3 e/ L
  17. }
    ; Y8 W" @8 f! I5 K8 ^* i2 x7 s
  18. & Y& p) D7 o$ I  B+ ]
  19. void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle){8 t$ H) K- T0 ]* U# [) h
  20.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    : L9 l: x. `4 U
  21.   if(spiHandle->Instance==SPI2){8 v4 N4 X; }, p/ }* W) C% w
  22.   __HAL_RCC_SPI2_CLK_ENABLE();  2 `- P& x+ c% y4 i
  23.   __HAL_RCC_GPIOB_CLK_ENABLE();. f! ]8 e! O% j* v# A3 m2 Z
  24.   /**SPI2 GPIO Configuration   
    , c. K$ J- s) |$ B& M8 ?$ X1 h& _) ^$ K
  25.   PB13     ------> SPI2_SCK
    3 L5 r& N  t5 P( t9 P: [2 N
  26.   PB14     ------> SPI2_MISO
    . o" [2 F& r) Y( G: _+ h
  27.   PB15     ------> SPI2_MOSI */
    & D" Z7 r2 u2 o0 u) A
  28.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15;
    $ u$ h6 X6 f7 A3 s# x7 R$ v8 @# f  M
  29.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    $ f  E: O! A+ r
  30.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    ' _( |. s1 v7 @1 n* y5 e
  31.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    " U# P& n7 k' ?) v: t$ V
  32.   GPIO_InitStruct.Pin = GPIO_PIN_14;
    4 A# y9 c2 p2 Z
  33.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    5 G  O& k" n" H, S
  34.   GPIO_InitStruct.Pull = GPIO_NOPULL;
    : U5 R, z; _% A; Y, c3 [/ @3 a& v% ]
  35.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    % A0 t+ I% S. i0 j
  36.   }5 i  Z3 h1 Q: e2 C  c
  37. }
复制代码
* Q( o* j$ f/ r2 e1 c. q' z, a2 f
➡️ 创建按键驱动文件key.c 和相关头文件key.h
➡️ 创建包含W25Q64芯片的相关操作函数及驱动函数的文件w25qxx.c和w25qxx.h,这里仅介绍几个重要的函数,源文件下载方式见文末介绍
  1. //这里仅介绍几个重要的函数- M! K2 h, s! Z# z! u" ~& c$ b
  2. void W25QXX_Init(void){4 i3 c9 |$ G7 d9 D( x; |, `
  3.   W25Qx_Disable();
    ' _# K6 l+ L0 P, A9 C0 m
  4.   W25QXX_TYPE = W25QXX_ReadID();//读取芯片ID( f! M9 S/ O8 ^/ h: c- S
  5.   printf("FLASH ID:%X\r\n",W25QXX_TYPE);
      z3 s0 ?* Q3 e0 k7 k2 S. I6 G
  6.   if(W25QXX_TYPE == 0xc816)- ?; d9 A) U4 E
  7.     printf("FLASH TYPE:W25Q64\r\n");
    - s: ~, \8 D. B
  8. }
    6 x+ b/ c5 Z: x$ v7 l( r% K
  9. ( \7 X4 v$ w! f7 n8 {5 E
  10. uint16_t W25QXX_ReadID(void){0 u; t# X% l; n' J
  11.   uint16_t ID;
    8 t. A- U3 K3 M- a" Z9 @+ S& x8 H
  12.   uint8_t id[2]={0};
    1 i. {6 v- D+ S+ n/ X. U+ R
  13.   uint8_t cmd[4] = {W25X_ManufactDeviceID,0x00,0x00,0x00};//读取ID命令        : W( V$ U9 d0 p- P+ N0 Y7 f
  14.   W25Qx_Enable();//使能器件+ ?3 V# m5 @( Y' j; X( g: q) I
  15.   HAL_SPI_Transmit(&hspi2,cmd,4,1000);0 k& c/ @, s. n: E3 Z8 ?& [4 o* `9 M
  16.   HAL_SPI_Receive(&hspi2,id,2,1000);0 P8 y* C& W; m/ x3 M1 q
  17.   W25Qx_Disable();//取消片选        ; ^, k+ B7 p* L* U  e
  18.   ID = (((uint16_t)id[0])<<8)|id[1];0 _8 v9 Z6 n, s" Q* x7 F+ @
  19.   return ID;
    1 |% J3 P8 A! r8 V5 q2 P
  20. }
    7 J' e+ N1 T0 E; N6 q
  21. 7 }* B# C# ^/ E  s! p
  22. void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead){
    6 ]! ~* O& x7 ]
  23.   uint8_t cmd[4] = {0};
    # m5 V$ u: {/ E6 t5 l; ?
  24.   cmd[0] = W25X_ReadData;//读取命令" F9 F, V  G, j' C: y/ T: Q; b" q
  25.   cmd[1] = ((uint8_t)(ReadAddr>>16));
    ! _" V. c& {# [+ T
  26.   cmd[2] = ((uint8_t)(ReadAddr>>8));
    " x1 H" f2 g. R2 i! C0 Q7 p* }
  27.   cmd[3] = ((uint8_t)ReadAddr);
    # k3 T. @' B: D6 |: M* @$ H4 g
  28.   [1 t. G, K0 r$ P% _
  29.   W25Qx_Enable();//使能器件
    & ]. |2 D- [# o0 B/ W# `# p
  30.   HAL_SPI_Transmit(&hspi2,cmd,4,1000);5 j% ]- l3 z7 L6 l0 p! H
  31.   HAL_SPI_Receive(&hspi2,pBuffer,NumByteToRead,1000);
    . L6 ~" N* h' q6 W5 [) k
  32.   W25Qx_Disable();//取消片选        ; t$ I/ u; k1 C5 [: C* O) s4 E
  33. }7 U7 T5 j- ?1 j" m6 ~6 G( n
  34. ! A/ g. q  c5 ^: B+ v* e/ x
  35. void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite){
    , {* g9 S, v3 z
  36.   uint32_t secpos;! O0 B3 c- p7 s" F8 X3 E$ q+ h
  37.   uint16_t secoff;% T! a) d9 l! T6 x5 }4 B, o% m8 ?
  38.   uint16_t secremain;- O: E) C0 S) l: d! e6 ^4 j1 B
  39.   uint16_t i;
    % T7 |  r/ I. \) w: V8 T- u
  40.   uint8_t *W25QXX_BUF;
    " o# e/ j6 b9 f, [$ b) _# G
  41.         - w/ R" X( t$ `
  42.   W25QXX_BUF = W25QXX_BUFFER;
    ) O9 E2 q& D$ h, G9 ]. n& M: M
  43.   secpos = WriteAddr/4096;        //扇区地址
    ) Y& h/ N: K- c, z
  44.   secpos = WriteAddr%4096;        //在扇区里的偏移+ ]$ R; v$ k: v8 G3 k8 k$ z- o+ w
  45.   secremain = 4096-secoff;        //扇区剩余空间大小
    ! \% _+ `! N+ ^" Z; z" W
  46.   printf("WriteAddr:0x%X,NumByteToWrite:%d\r\n",WriteAddr,NumByteToWrite);1 h) ?6 J# ~% D. E
  47.   if(NumByteToWrite <= secremain)  //不大于4K字节# w) O6 E9 ]3 {' v* r3 o) r6 j
  48.     secremain = NumByteToWrite;4 |" `5 {; H; {$ E* W% k3 E5 I
  49.   while(1){: M$ |5 ]+ F- D( L+ I
  50.     W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//读取整个扇区内容7 K4 ]4 z7 h5 H2 Z
  51.     for(i=0;i<secremain;i++){//校验数据2 p' R, m& o+ X; M; O
  52.       if(W25QXX_BUF[secoff+i] != 0xff)//需要擦除5 R" ]5 h! I7 E  g
  53.         break;
    : \8 C% r* o, E& H' x) y0 t
  54.     }
    - d% a# n% Z* B% z1 T
  55.                
    0 ^" Z6 I9 Z9 E9 U; T2 U
  56.     if(i < secremain){//需要擦除( w6 K9 g; ]+ ~' ^3 F2 i
  57.       W25QXX_Erase_Sector(secpos);//擦除扇区
    6 b2 t2 h: d& O) p0 P+ j, z7 Z/ s( E
  58.       for(i=0;i<secremain;i++){
    9 ]& D% B8 v! G' d: ]2 n
  59.         W25QXX_BUF[i+secoff] = pBuffer[i];
    5 u9 q9 K9 Q$ \) e" w
  60.       }, G9 _4 U3 b. F+ E, Y- ^
  61.       W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区
    4 q: }/ E$ F! C) o8 T6 S* D* T4 X
  62.     }! Y' r) g, J& v0 L4 u; ~
  63.     else{7 v+ X9 P- T6 b; ]
  64.       W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写入扇区剩余空间
    ' R" b" a- I% T7 l% b& X# m
  65.     }
    & x5 Q( J3 e0 y: U
  66.                 ' A6 j7 r3 @' ^" |6 q( ?5 V
  67.     if(NumByteToWrite == secremain){//写入结束了% |  W$ a1 b. D+ X& D2 E
  68.       break;
    # s1 e. ]$ H: Z  |9 C" K$ H7 T& ^
  69.     }5 h+ X/ D- |( g" n
  70.     else{        //写入未结束
    5 _' }+ ^& P) W$ j8 q
  71.       secpos++;        //扇区地址增18 ^7 l( d9 E' Z/ K
  72.       secoff = 0;                //偏移位置为0                ! W( W7 m3 `0 O3 [, c
  73.       pBuffer += secremain;        //指针偏移9 l7 b6 N4 u* Q' g
  74.       WriteAddr += secremain;        //写地址偏移
    8 C6 l- ]' ~% p- L. c
  75.       NumByteToWrite -= secremain;//字节数递减3 \8 l5 ?4 K4 a- h7 R% q. H
  76.       if(NumByteToWrite > 4096)                % l: R; s- V5 b# N; a4 a4 s
  77.         secremain = 4096;        //下个扇区还没是写不完# q4 k: m; z0 C$ b: Q; w* R
  78.       else# j* x5 I# P, p2 o  y7 C7 h5 F2 I
  79.         secremain = NumByteToWrite;//下个扇区可以写完了. K5 u+ W0 D$ S
  80.     }  c  M7 Y. m  k4 d: E* \
  81.   }7 ?6 n. c; Q0 Y& G3 r% [4 Y
  82. }
复制代码
; C' \8 ]- \8 h4 H7 r3 G9 X7 a
➡️ 在main.c文件下编写SPI测试代码
  1. /* USER CODE BEGIN PV */" d9 ~/ R# x: R: g+ k% S
  2. uint8_t wData[0x100];. D* V0 z, B' O9 ?2 U6 O
  3. uint8_t rData[0x100];/ h# n: y4 }! c7 C% g2 T
  4. uint32_t i;
    * a/ A. k- E" c$ C3 N
  5. /* USER CODE END PV */# E7 I( U' m2 l' t: T% u; o, j
  6. int main(void){' P4 Q1 ^# W, A. L9 }# B
  7.   /* USER CODE BEGIN 1 */
    2 |7 z) U0 z4 ?7 ?/ h. R
  8.   uint8_t key;9 C) T, s4 Q4 n. l5 k6 {
  9.   /* USER CODE END 1 */) g; s) d. m' D6 s0 v- H
  10.   HAL_Init();5 h9 P  s2 e; V. w
  11.   SystemClock_Config();
      F6 l* E. ~, u# l8 s
  12.   MX_GPIO_Init();$ T. z) A2 G; S- a0 a2 ]
  13.   MX_SPI2_Init();9 l# m0 ?) g7 h4 B
  14.   MX_USART1_UART_Init();
    $ W+ X) Y3 x2 N9 w
  15.   /* USER CODE BEGIN 2 */* d+ A: o2 h( S: O3 R6 h) M6 w& w
  16.   W25QXX_Init();
    ' J5 n- }  X& R  Y, Y6 P0 g; W
  17.   for(i=0;i<0x100;i++){
    1 w$ X6 A/ v' F% }( E' K- y
  18.     wData[i] = i;
    $ ^2 `- A7 s) g2 J5 B( m2 Z. W+ }
  19.     rData[i] = 0;+ p3 p& `+ o! R# p  U
  20.   }        ; ~5 y# k: p' a! i8 l9 e/ b
  21.   /* USER CODE END 2 */
    : A  x1 C6 j; {6 I
  22.   while (1){' T' H! p# x1 Q3 j
  23.     key = KEY_Scan(0);
    . n9 p4 d+ a' s4 S
  24.     if(key == KEY_UP_PRES){1 ^' g! m& u" m' `# y% Y
  25.       printf("KEY_UP_PRES write data...\r\n");3 F1 ~; f; ^" ^/ R% E
  26.       W25QXX_Erase_Sector(0);3 q- H: N( }8 Z- Q$ W4 d
  27.       W25QXX_Write(wData,0,256);               
    ( u5 v) T* ]- X2 M
  28.     }
    + C' @" l; o% p7 d. \% o
  29.                        
    ' `4 A* L' ]! g) E1 t' B
  30.     if(key == KEY_DOWN_PRES){/ Y% I3 c! c% B4 l5 a
  31.       printf("KEY_DOWN_PRES read data...\r\n");
    0 f) Y0 R3 C7 v" n
  32.       W25QXX_Read(rData,0,256);5 Z- `# n# p( ^/ E) e
  33.       for(i=0;i<256;i++){
    6 ]5 P3 X1 @! e7 Q7 G' v; [' z
  34.         printf("0x%02X ",rData[i]);) E8 ~! ~' y7 Z9 x' F
  35.       }
    1 Z/ [* m( i% L; z8 t
  36.     }
    " t7 m6 I  T, a
  37.                 # }' {7 m) R1 b& o
  38.     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
    + P; z# Z! X3 B! B
  39.     HAL_Delay(200);
    $ N& P5 }2 Y! Y4 W7 y6 F9 Y, N! \
  40.   }( @7 X6 [: a9 @3 X
  41. }
复制代码

3 `! {1 h  A/ o; R0 f
4.下载验证
编译无误下载到开发板后,可以看到D1指示灯不断闪烁,当按下K_UP按键后数据写入到W25Q64芯片内,当按下K_DOWN按键后读取W25Q64芯片的值,同时串口打印出相应信息
* |: _. P" ^  b' _
微信图片_20230701185521.png 5 ~4 y2 X0 M# a3 y9 ~' {: z8 Y
( _/ L- K: x' F! U1 D# A
转载自: 嵌入式攻城狮# ], U* ?: q" r% f' W* E
如有侵权请联系删除. m# _3 x# R" E1 g, O1 M

$ V* a5 o. f+ A
  t0 W4 W6 u: S' f& g+ U/ h8 z0 r
- [9 t  N  t, S4 p9 l. t' X' |6 n
赞 收藏 评论0 发布时间:2023-7-1 18:56

举报

0个回答

所属标签

相似技术帖

官网相关资源

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