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

基于STM32的ADC片内信号经验分享

[复制链接]
攻城狮Melo 发布时间:2024-1-18 19:00
微信图片_20240118190031.png
& w% N: |- _1 E- q, _
- n0 @1 b& F. _, ?
$ S* A6 A* L- H+ C0 ?
很多STM32芯片里往往内置了专用的ADC通道,比方用来测量Vrefint,VBAT的分压或温度传感器的输出电压信号。不同系列所内置的模拟信号通道可能有差异。这里以STM32G4系列为例,它内置了对应于Vrefint,VBAT的三分之一分压和温度传感器的输出电压的专用模拟通道。* T1 t) z6 J* q) p; {7 [; \: |

* N4 R1 Q& K3 {3 i* u* y
微信图片_20240118190028.png

+ F' ^& t2 T4 T9 d3 X1 ~/ g5 `6 W2 N: i
微信图片_20240118185948.png

) k9 a, V# r' k5 @. s' f; o4 f

, \" i0 M1 ?, C8 R6 K4 v6 p# a% Y* s* M下面的示例就是针对上述3个通道进行ADC,并测量相关电压和片内温度,最终得到3个结果,分别是VRefint电压,VBAT的电压,片内温度。+ `3 E2 v: z' j" [1 U3 G

9 q$ E$ s& O1 h
微信图片_20240118190017.png

9 Z4 P% l! J/ i; X* q$ {& D

) g2 T( L/ X' ]- G5 r! f& f实现过程是这样的,大体分四步:【有点点麻雀虽小五脏俱全的味道图片】
  I) @. K% V7 U9 z- R$ r6 H9 ]( D1 l( ~* v! V/ |( {
1、TIMER1 更新事件触发ADC的转换;7 Y, M) R; L+ f' q- D

$ n4 y- G& ~6 Y4 k3 v2、CPU基于EOC中断获取ADC结果;2 g" b5 X& Q, R

/ Y7 k2 p  A% X- ^- x3、对ADC结果进行换算,得到电压值和温度值存放在特定内存位置;* m* t& W: \) S  s( e5 y

+ h/ K+ C, _4 p, b( a% t4、基于DMA传输通过UART将最终结果在串口终端显示;! g. j) e. k# @5 V* s* Q. F  i; H

* i9 }3 V" m8 ~; X& a" U, B其中,TIMER1的CH1输出PWM波形,其更新事件做ADC的转换启动信号。每次的TIMER更新事件触发ADC,3个通道扫描方式转换。这里的UART使用片内LPUART,使用它主要是考虑它跟板载虚拟串口直接相连,没有其它特别用意。' m, E: n5 _' c. ^" t

) ], b# o: w* Y
微信图片_20240118190012.png

$ s0 p2 Y* f* M% X# n  H) r
# E, @% u! j; `7 ], C7 ~. J我使用STM32G474Nucleo板来进行下面实验。其中VDD=3.3v,VBAT与VDD相连。另外,ADC模块的参考电压也是3.3v.5 K" w; @% s. r' s9 @4 ]; s
4 r, V1 E& A! l1 N
使用CubeMx图形化工具进行配置,先看TIMER配置:+ _+ c5 g' e/ R7 M+ k, Q* L

! M. u) X  I$ b% X2 G
微信图片_20240118190009.png

+ q" Z- _) D# j! H- W& v: X" m. c' W* M: F( @
再看看ADC的基本配置:
( s3 M0 a% C- o( O7 k# q/ {4 ~7 G8 K0 b4 Z
微信图片_20240118190005.png

5 G" n% h' n  R# c
* S" O3 a4 @+ E, b& h6 H4 \7 fLPUART的基本配置:
* [: P' K* C& u- {: p6 k
# B5 O' ?! V% o
微信图片_20240118190002.png

; F9 \/ f$ O8 X
" c4 p. W3 W( z$ o4 X! g6 z% E因为要使用ADC中断和UART的DMA传输,记得做ADC的中断响应使能配置和LPUART的DMA配置,这里只使用UART的TX DMA功能。
. Y- V6 F& `) y- Y- g2 W
" h3 q% Y  s* R8 Y2 R: [& {
微信图片_20240118185959.png

+ @. X4 S  x6 g8 U

% u9 o' m. |/ M使用CubeMx主要配置主要是上面这些。( M1 D9 z  [8 _) G' e* H
6 H. x" c; J+ H5 _0 N4 U: @
在组织用户代码前,先简单介绍下片内温度传感器的内容。该温度传感器针对不同温度有不同电压输出,其输出电压跟温度呈线性关系。ST公司针对片内温度传感器在两个特定温度【30℃和110℃或30℃和130℃】、基于特定参考电压【3v或3.3v,不同系列以数据手册为准】生成了1组校准值并存放于片内特定FLASH位置。6 H  A0 J8 k2 @$ _5 X% [/ t/ I2 Z( @

7 g- ]# q" s! O; zSTM32G4系列的校准值是在参考电压为3v,30℃和110℃条件下的两个值,在数据手册里还给出了校准值的片内存放地址。
- z" u* p, V1 x$ c
, i- e3 _/ p  S6 f1 z
微信图片_20240118185956.png
. x; |/ L; ~! q& ^- f$ {9 H4 L$ M
7 ?2 t( \5 ?0 M1 m
针对这个温度传感器的使用,ST公司在参考手册里还给出了计算公式。其实,有无这个公式无所谓,我们不难自行推理出来。【TS_DATA代表某时刻测得的传感器输出电压对应的转换值,TS_CAL1/TS_CAL2分别表示在30℃和110℃条件下基于传感器输出电压的转换值。】
9 }* `8 _# L( p7 j7 l; R( F3 p: T* E2 B1 p# k! m
微信图片_20240118185953.png
: N' [. H" e6 L

: H9 r7 e' B8 z1 S另外,前面提过,ST公司在手册里给出了温度传感器的两个温度下的校准值,但要注意生成校准值的ADC模块所用参考电压跟我们实际应用时AD模块所用的参考基准电压可能不一致。如果不一致,就必须将ADC值换算成同一基准参考电压条件下的数据。目前在ST手册里也特别强调这点了。我把上面一副图再贴一遍于此【见黄色语句提醒】。3 a& T: b* ~" o& o
1 k+ I8 ~( a$ [3 N+ f" a
. e% x+ Z& t2 o$ j+ D

$ m; O$ f; S1 @1 v关于这点,我们也不难理解。同一待测信号、同一ADC模块在不同基准参考电压下转换值往往是不一样的。见下面示意图加以理解。
! U4 Y4 v( c: K0 Q( @+ `( D' H; a) D
6 C" w; ^+ K9 f  ?1 [
微信图片_20240118185944.png
1 a! {# R6 n) K
! f& m3 c  m& q! w
完成各项配置后,创建软件工程。添加必需的用户代码:$ O8 h: X$ P+ D7 F5 f
  j- Q+ A6 c; r: V# @+ G
  1. #define TX_Timeout (9999)6 I% f8 V0 n0 \- m: C& E) v5 f( `
  2. ) _- }# E; X: z2 m8 N4 Y' y; z
  3. #define TS_CAL1_ADDR  (0x1FFF75A8)  //用于计算温度传感器数据
    ( W$ S0 A& u# b4 R
  4. #define TS_CAL2_ADDR  (0x1FFF75CA) //用于计算温度传感器数据
    . G* J4 X1 p6 p

  5. 1 D' \3 B" {5 O! f8 R
  6. #define size1 (40)
    3 [0 o( i' i  y7 n* B
  7. - `3 P7 ~3 \( C+ m
  8. char WDVol[size1],BatVol[size1],InVol[size1];
    , u4 P* e8 X! \( R

  9. 4 \2 b0 R1 _$ \& G/ `' V! h" k
  10. uint16_t ts_c30,ts_c110;
    6 z6 l1 ?. b! R. g$ y( ^$ C5 V! }
  11. / P( v- e2 Y9 I$ l
  12. uint16_t ADCResult[3],convCNT;
    - j3 E( F) o* q' w9 H3 t# @) u0 n
  13. * b% T3 D, Z) f9 E. \) s; t
  14. volatile  uint32_t Completed,EndofCon_Flag;
    7 s) T, O2 L( S' d4 q( [, V1 M
  15. % x, a# n$ ]2 ?2 }
  16. float    VBATVolt;//存放BBAT电压最终结果
    / R# C7 U, x$ W- A  z$ p
  17. float    VRefint;  //存放Vrefint电压最终结果6 u* O3 I; v0 V' b  A% I  C
  18. float    Temperature;//存放片内温度℃最终结果* I8 d5 f& ]& T2 A

  19. % x( e( D  C$ e7 Q
  20. int main(void)2 W* z: ^1 x; X+ j  L: m
  21. {
    2 S: R$ I: ^2 |1 p* B3 Q5 n" A, d
  22. /* USER CODE BEGIN 1 */
    6 }: |9 m  ~( _" L

  23. 4 F+ B* }1 ?2 ]* c
  24. /* USER CODE END 1 */( g0 _! w; t( b4 {) L

  25. & j& t3 s9 ~5 T# A
  26. /* MCU Configuration--------------------------------------------------------*/
    0 o2 t8 Q/ \: Z! [1 X9 N& W  x4 }

  27. 8 X8 U5 C$ U6 S( [, ], u8 L
  28. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    7 U' E: U/ A3 t; u1 [  J# E
  29.   HAL_Init();
    ' U( n, t9 q( J$ l$ a8 v
  30. . J2 y* i9 r. h6 u6 J4 J
  31. /* USER CODE BEGIN Init */  K: H0 e; k& L- K0 X$ F2 V; m2 E4 W
  32. 4 u( D, n& ~  ]& g2 N
  33. /* USER CODE END Init */1 R& \7 h+ j6 U0 I, P3 t0 e
  34. / J, Z( n) E& v
  35. /* Configure the system clock */
    / ?( h9 g. H3 r/ H1 z- X, ^
  36.   SystemClock_Config();* z- T, a. N  h+ w: H: @8 z

  37. 1 P( H) ?1 `, s9 J6 p
  38. /* USER CODE BEGIN SysInit */
      q+ v0 P' p, Z+ ^

  39. " Y" g) c: o5 U4 K( h
  40. /* USER CODE END SysInit */% ]" b9 \  T! ~/ N) U; V

  41. ) B+ J8 x' ]% a6 K7 z( j7 Z
  42. /* Initialize all configured peripherals */
    5 g4 D) h! ?9 }& l, T
  43.   MX_GPIO_Init();+ V% u+ Q- |  Y! P8 q3 w5 X
  44.   MX_DMA_Init();' v1 ^* [% F0 D( x( P4 U4 v
  45.   MX_ADC1_Init();0 O- D. ^1 C% x) V  ?7 I
  46.   MX_LPUART1_UART_Init();
    % O/ S3 A' P4 [& R5 e
  47.   MX_TIM1_Init();$ h/ k- f7 K, F' |! K4 v8 W
  48. /* USER CODE BEGIN 2 */6 j, |  c* V& v0 B
  49. 3 `" O. W& ?8 x
  50.    ts_c30 = *(uint16_t *)(TS_CAL1_ADDR); //读取30℃时的ADC校准值
    2 _$ j% l2 j, `0 c* y
  51. 1 i2 [( b: J6 A& G$ O
  52.    ts_c110 =  *(uint16_t *)(TS_CAL2_ADDR);//读取110℃时的ADC校准值  P7 C0 j& E+ [1 e' m0 m0 w
  53. 0 x4 Q9 W* z6 S, `  a
  54.   HAL_ADCEx_Calibration_Start(&hadc1 , ADC_SINGLE_ENDED);//ADC校准
    % Y; g; U' D$ S! L

  55. 7 g2 X' U8 G3 A/ R1 A
  56.   HAL_ADC_Start_IT(&hadc1);//启动ADC并开启转换中断& n  N  |( f& }9 V0 L3 z' s
  57. 2 e1 B7 K/ V# x" M; y2 e- K# a9 k
  58.   HAL_TIM_PWM_Start(&htim1,  TIM_CHANNEL_1);
    9 z2 k9 I1 I$ l9 s4 \
  59. 9 V: c6 Z! `5 J3 [% D

  60. ! h, r/ q9 Q- x& Z' v3 m
  61. /* USER CODE END 2 */
    / G# ~5 f- i( Y+ l" B
  62. 8 o# h1 o3 k) A7 a3 x
  63. /* Infinite loop */
    - o8 `& n) u& a% P9 f5 x4 R
  64. /* USER CODE BEGIN WHILE */- E8 q% {: n0 b  F& r
  65. while (1)% H. w- h! U) U: E: M+ H; E
  66.   {1 v8 j+ e, {; s0 H- ?; a
  67. /* USER CODE END WHILE */
    : i' `8 ~' X8 f$ E5 o8 y

  68. 7 x9 q# m. q: g6 u  |/ ~
  69. /* USER CODE BEGIN 3 */
    8 J( S- |+ D2 s

  70. # d7 r5 J! F: C& {$ L- W
  71. if (EndofCon_Flag!=0); f9 M$ D" s0 q) }% ]( _
  72.   {/ v5 ~- |  F( |* U6 W) M* b
  73.     VBATVolt=(ADCResult[0]/4095.)* 3.3 * 3.;  6 S/ P* s3 q; B/ a5 S

  74. ( H" G. ~7 S; ^! F
  75.     VRefint=(ADCResult[1]/4095.) * 3.3;  $ @! d: K- x" ~

  76. * B3 T4 q8 w* q( e
  77.     Temperature = 30.+ (88.*(ADCResult[2]-((ts_c30/1.1))))/(ts_c110 - ts_c30);5 ^. X+ ?2 t# t/ s: X0 m! `

  78. - M2 ]: _6 J# X5 |* ~: l0 z
  79.       EndofCon_Flag=0;
    ; Q0 ]( R3 B! \& b$ b$ E/ ^
  80. # m  V: `- J4 M# o
  81. //HAL_UART_Transmit(&hlpuart1, (uint8_t *)WDVol ,sizeof(WDVol), TX_Timeout);; I- G+ @4 J. y; N

  82. 9 a2 U& j0 b: }, z
  83.       HAL_GPIO_WritePin( GPIOC,GPIO_PIN_3,GPIO_PIN_RESET);  //for auxiliary test
    * [, Y+ E/ \: f* n
  84. 1 N$ \; x; Z* n5 G* H4 B! G
  85.       HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)WDVol ,sizeof(WDVol));
    ' F% N: n' }/ I  K) h
  86. # f$ {8 ]0 ?8 [! B% h  R4 e
  87. while(Completed==0){}
    ' ?8 O) I' {6 D, K8 U' B
  88.       Completed =0;
    2 O- e2 N0 r2 @1 z
  89. / g& l( l. q( g

  90. , Q4 |1 T0 a: s
  91. //HAL_UART_Transmit(&hlpuart1, (uint8_t *)InVol ,sizeof(InVol), TX_Timeout);! e/ c! a7 \) ~) {1 g, e" Q
  92.       HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)InVol ,sizeof(InVol));
    ' ^5 q9 \) \8 L) O0 L  C" r9 ^

  93. 9 a- H6 B7 S! O6 L, E( w
  94. while(Completed==0)  {}
    3 {! z3 o: e$ I+ G3 n! H. c/ O4 @! J
  95.       Completed =0;! i3 A4 d/ E% F' s) T( R
  96. # d9 q! J* n3 M4 r8 b" t/ ?

  97. ) e# M" [1 R4 q
  98. //HAL_UART_Transmit(&hlpuart1, (uint8_t *)BatVol ,sizeof(BatVol), TX_Timeout);
    ' Q8 |7 {- |; c! u( g# P
  99.       HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)BatVol ,sizeof(BatVol));
    ' u8 t; x% n3 J, c, w7 T3 M" k$ j
  100. & e. L- P+ E6 A  c2 H
  101. while(Completed==0){}2 I6 u+ |  H0 j/ ]5 h# X# t, Q
  102.       Completed =0;. }$ m/ u0 [4 b2 r2 X; W# b. B- T
  103. + P$ ?" k- O5 T/ U- n
  104.       HAL_GPIO_WritePin( GPIOC,GPIO_PIN_3,GPIO_PIN_SET);  //for auxiliary test; Z5 ]/ F- u% N+ V6 B0 Z
  105.   n# @$ V! P9 Z1 z6 W: z
  106.    }   4 C6 I/ Q7 f/ g0 ?7 }. Z6 h
  107. % p6 o' v* O$ H6 E
  108.   }) ]: ?* Q) v9 Y0 m0 G
  109. /* USER CODE END 3 */
    6 j, g3 }0 v: @# }) I" F  ^( F
  110. }9 K- [& K1 h/ k" o* d

  111. ( B6 k* h2 x: V/ G: E- h
  112. //ADC EOC 中断回调处理函数' y1 [0 h, V3 w! @4 H# Z8 Z
  113. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)# A9 R* q0 Z) K7 x3 w
  114. {
    0 w- H3 g3 Q- P& d8 n/ J3 ^
  115. " P% F  N# ^. y: p8 u! i
  116.   ADCResult[convCNT]=HAL_ADC_GetValue(&hadc1); //获取转换结果并存入数组
    1 @  R' A5 V; h- e% @# ^# k* j
  117. 0 q# d+ b9 q0 _( i- {, p0 l
  118.   convCNT++;8 x1 z8 z8 f% o, F

  119. 3 R4 f  V8 M& \: A+ f: [
  120. if(convCNT==3)  8 h9 y. U( C3 Q9 r8 l; L4 ^$ p
  121. 7 U4 p6 F. {- u8 T, y
  122. {
    - v- F. {$ y- y' ]5 k9 T
  123.     convCNT=0;
    . x9 m. v" `/ Q: G# S6 \

  124. ! I6 J( b; e: R5 |, E
  125.     EndofCon_Flag=0xff;
    6 d$ T3 V5 G% E2 ~4 P4 [
  126. - W% n: c2 F0 }  m# P8 h. V
  127. sprintf(WDVol,"Internal PN Temperature: %5.3f  \r\n",Temperature);  % X# o) r& [7 L0 ~4 H& {
  128. & H7 f! J) ~7 _' ]4 A
  129. sprintf(InVol,"Internal Reference Volt: %5.3f  \r\n",VRefint);  2 G7 p1 ~+ V; D% m; x
  130. , A$ Z( }5 u) F' _
  131. sprintf(BatVol,"Current Battery Volt:   %5.3f  \r\n\r\n",VBATVolt);( l; X8 q- Z3 r
  132. 8 I2 A6 o( X! X
  133. }, E" U2 e' S( r" q
  134. $ N/ ~7 d! A& }6 n
  135. }5 h, y' c9 @  z( u

  136. : L4 x; S' U* |' t% |/ U8 Y8 s
  137. //UART DMA 传输完成中断回调函数6 c& z# c0 o9 G/ I' |8 B3 h
  138. , e; Z5 [9 U0 E* u  p4 ^5 J
  139. void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
    + w; d0 W1 F3 V7 G6 G6 j! Q. q
  140. {- w, \7 e! g, V3 s

  141. 3 h9 g3 Y$ g8 Q7 M$ D
  142.   Completed=0xff;
    1 q/ B/ W' ~+ f2 Y# Z: U! r$ ~4 D; c! ]
  143. }
复制代码

$ }6 }% J2 L* a/ {  B基于上面的配置和测试代码,我们就可以看到最终的结果了。定时器周期性地触发ADC,每得到3个ADC结果就进行数据处理,然后通过UART以DMA方式传输到串口终端。注意VBat电压是测量结果再乘以3得到的。. R. C* [) G9 T" o

  F& q/ U5 ~8 D
微信图片_20240118185941.png
( ]/ F5 N/ G0 I

& c( Z% t9 W* r5 `
微信图片_20240118185938.png

. W* S' T; ~2 B! W$ Q6 K8 R. w0 f0 W2 W( ?6 a% Z( z" g. T
针对上面的应用演示,最后给几点相关应用提醒:
1 M. p: V+ x3 a3 K' b6 d
: K5 Q9 S( H3 i, Y" l) x1、针对温度传感器做测量时,校准时使用的参考电压与实际应用不一致时要做换算,换算成相同参考电压的数据后再做计算。这点前面也提过了。
9 R$ _( T- b( h* d4 W9 K1 O
7 K& c1 E; n" B  `2、使用TIMER的TRGO触发ADC,如果选择类似比较事件、更新事件来触发ADC时,此时ADC对触发极性的选择是无效的,或者说ADC的转换仅依赖于触发事件时间点。如果是选择TIMER的Ocref信号作为触发源,此时ADC的硬件触发的极性选择是有效的,可以是上沿或下沿触发,甚至是双沿触发。这时就得根据需要选择合适的触发沿。【可以进一步阅读本公众号文章《STM32定时器触发ADC的时序话题》】$ @/ k) ?8 E1 k: c% [7 d
5 o- b; T! n) S0 h: I
3、这里使用UART的DMA传输依次显示三个结果于串口终端,三个启动UART DMA传输的函数须保留适当时间间隔,即等上次传输完成后再启动下一次传输,因为这里每次传输使用的是同一DMA通道。否则没法全部正常输出。比如若把上面3次UART DMA传输的代码改成下面这样子:
; Q9 M1 I, h! Z* i4 W  r
- a6 e( Z+ c) L; k( n6 X  J, ?( ^
  1. HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)WDVol ,sizeof(WDVol));
    0 r# ?. c1 h4 |9 p( Z
  2. 6 j! D: G0 s8 \4 \) b! I; l( i9 [
  3. HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)InVol ,sizeof(InVol));+ ]1 N: b8 b+ \8 I

  4. 4 s3 ^  I' b0 ~: V1 q8 f
  5.   HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)BatVol ,sizeof(BatVol))
复制代码

/ [  `2 D# q# p3 \9 A9 A& v这时输出结果会变成下面的情形,总是只能看到一个结果的输出,即第一次启动的DMA传输结果。
! x0 Q" f: x2 t  r3 M4 v0 c$ j; q: m/ n% `. ]# O$ d9 c1 m
6 w# _% q  y1 @
' J; G, ]4 n1 D% C% [- V) e- @9 Z
如果想省事点,直接在相邻2次DMA传输间加上合适延时也行。我这里根据DMA传输完成事件来决定执行下一次发送。在DMA传输完成中断里设置Completed变量为非0值表示当前一轮DMA传输完成。( B) s* N5 T* h0 k2 {" ?% B6 g2 A
! h3 [' b4 @  h' N6 H' e
4、对于那些在中断和主程序里都会被访问的变量,记得将它们冠以volatile。
8 t9 n; D% J7 |/ K! z1 h) e$ P$ Q: i' N8 ]: |4 Y
下图的三路波形是我调试时辅助使用的。5 E# C, t; H! b1 C$ b

# Z: X7 ~& |/ m  y! ]3 r8 {第一路表示计数器的计数变化,显然是单向向上计数模式。1 @( H" |* n9 {7 ?1 r

2 O5 w9 x/ l) i" t! H; ^" K第二路是TIMER1通道1的PWM输出波形。* b( B8 W3 P9 z# y

6 e0 w8 m3 Y# Q, T: w第三路是我每次基于DMA实现UART发送时拉高拉低的波形。平常管脚电平为高,在实现DMA传输过程中拉低。* c9 y7 `/ I' a* n
" h/ _  n: |0 k+ A) M, o6 P- }* N6 R, Y
微信图片_20240118185918.png

% I/ l* J' [. z& d& C
  N3 H1 ?! G4 Z1 m+ A3 I0 ~
如有侵权请联系删除1 N' N' c9 U* G3 X5 {6 z9 f
转载自: 茶话MCU
  h4 _4 ]; z8 G4 U' A2 ~, @
+ H* n6 {; a' B7 }" m
0 X/ P9 _5 N0 v" r
. f. K) e: b5 L) e5 T8 w( q5 v
微信图片_20240118185921.png
收藏 评论0 发布时间:2024-1-18 19:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版