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

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

[复制链接]
攻城狮Melo 发布时间:2024-1-18 19:00
微信图片_20240118190031.png

* }& |% j  Z. L4 L. A% `7 J
8 m' F0 m* a/ G! O
4 F, A9 g9 x7 W  F5 x+ N. d
很多STM32芯片里往往内置了专用的ADC通道,比方用来测量Vrefint,VBAT的分压或温度传感器的输出电压信号。不同系列所内置的模拟信号通道可能有差异。这里以STM32G4系列为例,它内置了对应于Vrefint,VBAT的三分之一分压和温度传感器的输出电压的专用模拟通道。
; f; V- {% ?* n9 s2 Q" }% o
$ v2 R4 J* E0 P
微信图片_20240118190028.png
0 {) W  [* F8 ^/ j# p

6 _. _+ e# P/ u6 P) ?+ H
微信图片_20240118185948.png

) R! R4 M- \/ \" @4 `+ `' B. N2 W$ E
. l, W8 D9 Q3 e8 t) S
下面的示例就是针对上述3个通道进行ADC,并测量相关电压和片内温度,最终得到3个结果,分别是VRefint电压,VBAT的电压,片内温度。
  U) _' r4 C. n) r. i, r; O; Q& P( l* m. n2 ]
微信图片_20240118190017.png
# V: N$ v) g5 ^4 u$ \5 q/ [2 n! B

4 ~8 T+ A% x! ~; g5 z; Q$ U( o0 e实现过程是这样的,大体分四步:【有点点麻雀虽小五脏俱全的味道图片】
2 {" I2 E# r; V+ }# n6 D1 C9 ]# g2 C, ~" Y. g' S8 D# U
1、TIMER1 更新事件触发ADC的转换;; W2 o/ d/ R$ c+ W

0 }- n0 S9 e5 o/ G2、CPU基于EOC中断获取ADC结果;
8 G0 k4 N# O) r+ s  G* \+ b& q9 ~5 h7 B- @
3、对ADC结果进行换算,得到电压值和温度值存放在特定内存位置;
) t; u6 O+ @+ \: T5 Y4 @( k4 g* H1 g$ n! ?$ c; P4 `
4、基于DMA传输通过UART将最终结果在串口终端显示;/ n3 }0 Y  ?& N7 x& F% k
; @+ {$ A/ J* [% k& }6 X% x
其中,TIMER1的CH1输出PWM波形,其更新事件做ADC的转换启动信号。每次的TIMER更新事件触发ADC,3个通道扫描方式转换。这里的UART使用片内LPUART,使用它主要是考虑它跟板载虚拟串口直接相连,没有其它特别用意。% f4 o7 {* ^; O& N+ W4 Q. \

9 W1 F0 U# h& f) g
微信图片_20240118190012.png
+ p4 Z/ H. q" `  y- }! j3 W9 N

: i1 f" Z( W; @% g5 R. P我使用STM32G474Nucleo板来进行下面实验。其中VDD=3.3v,VBAT与VDD相连。另外,ADC模块的参考电压也是3.3v.2 w0 J- u' R9 U6 O6 F! `# S1 ^0 X1 h
% W& q" a& q+ \$ T
使用CubeMx图形化工具进行配置,先看TIMER配置:7 N* Q/ S" u( v

, O; @  y  b. f
微信图片_20240118190009.png
! }1 {7 `* X* w; S
+ F: A2 V- U1 J# P( y7 z
再看看ADC的基本配置:* q% N$ P0 b) y  o6 G0 |

. y: P2 h! S" n( i
微信图片_20240118190005.png
, u5 |7 Z: M% H! @
6 L6 [. v2 [  U7 _( q
LPUART的基本配置:6 v" ?' j! q# N& p
& Y9 S0 S( K/ X* s1 j& G$ o7 \7 e
微信图片_20240118190002.png

, l. F. \+ f, Q, t
# Y* A/ X& u) W9 Q3 q: W因为要使用ADC中断和UART的DMA传输,记得做ADC的中断响应使能配置和LPUART的DMA配置,这里只使用UART的TX DMA功能。9 e$ a  _+ j3 q( x: l8 v
6 f; r6 S2 e5 z% s$ b9 u3 F
微信图片_20240118185959.png
+ s) H) P0 P, N1 H% |: i
( g" o+ i, A7 g! B
使用CubeMx主要配置主要是上面这些。2 u4 u6 \0 o  t3 d9 _; L# p) G( S! _

  s% g) G2 r( J2 A在组织用户代码前,先简单介绍下片内温度传感器的内容。该温度传感器针对不同温度有不同电压输出,其输出电压跟温度呈线性关系。ST公司针对片内温度传感器在两个特定温度【30℃和110℃或30℃和130℃】、基于特定参考电压【3v或3.3v,不同系列以数据手册为准】生成了1组校准值并存放于片内特定FLASH位置。& B6 D. Q# o) ~0 R2 q
2 u' z/ L4 D% d! O, i9 r
STM32G4系列的校准值是在参考电压为3v,30℃和110℃条件下的两个值,在数据手册里还给出了校准值的片内存放地址。
0 j2 A( Y" g( f. l2 q, G/ I0 Z. c, G. r: p9 v
微信图片_20240118185956.png
8 g. _/ V+ L* U. B( [6 q
% s) s" u+ G8 n% P8 v" g
针对这个温度传感器的使用,ST公司在参考手册里还给出了计算公式。其实,有无这个公式无所谓,我们不难自行推理出来。【TS_DATA代表某时刻测得的传感器输出电压对应的转换值,TS_CAL1/TS_CAL2分别表示在30℃和110℃条件下基于传感器输出电压的转换值。】
* X$ O+ c9 x: h7 ^2 k
. T3 ]1 q  \. ?
微信图片_20240118185953.png
4 b  l! J- v, i, H

7 l! }- ~2 z$ J另外,前面提过,ST公司在手册里给出了温度传感器的两个温度下的校准值,但要注意生成校准值的ADC模块所用参考电压跟我们实际应用时AD模块所用的参考基准电压可能不一致。如果不一致,就必须将ADC值换算成同一基准参考电压条件下的数据。目前在ST手册里也特别强调这点了。我把上面一副图再贴一遍于此【见黄色语句提醒】。4 i: V' c1 G* y" v
* i4 }8 I, z4 i2 q3 X* q0 X

/ p* F7 F# q4 W, w5 R3 q
  p* m: N" K0 f5 _
关于这点,我们也不难理解。同一待测信号、同一ADC模块在不同基准参考电压下转换值往往是不一样的。见下面示意图加以理解。" `+ h, j" p# S1 O% m

$ q: g, R! c# w  e! D2 T
微信图片_20240118185944.png

  \6 l; L/ q8 \, h. e

! ]( l. f" B4 s1 [' R+ `完成各项配置后,创建软件工程。添加必需的用户代码:
. x5 D6 O3 e# H& d: o6 W) ^2 |- n& u, Z4 k" g% A1 l0 `7 h
  1. #define TX_Timeout (9999)0 L. m! h! m% ^1 V& K% T
  2. 4 X$ M& w1 R0 ^
  3. #define TS_CAL1_ADDR  (0x1FFF75A8)  //用于计算温度传感器数据& O7 F: a# F& {3 C
  4. #define TS_CAL2_ADDR  (0x1FFF75CA) //用于计算温度传感器数据
    ' w3 O9 P" q( U0 j' b
  5. 1 Z8 w6 Y) n3 }0 }& H0 T
  6. #define size1 (40)
    % l( U: E+ `' d9 x' @
  7. # D3 N8 V% e; _# u8 D
  8. char WDVol[size1],BatVol[size1],InVol[size1];
    4 t/ j: E; e: F1 z* t8 t; ]' H

  9. ' \1 d; l% n; Y
  10. uint16_t ts_c30,ts_c110;4 ?. A5 A  [" I
  11.   H9 `* M+ e  Z; ]" {! W0 _
  12. uint16_t ADCResult[3],convCNT;+ Q# ~4 {" a1 }. ^
  13. . {& F3 S) U# {; }8 U5 p! m
  14. volatile  uint32_t Completed,EndofCon_Flag;. ~5 [( b! ?- W5 a+ u
  15. 4 |0 G0 W$ \4 E* x
  16. float    VBATVolt;//存放BBAT电压最终结果$ U4 r& Q5 P0 c# l; v, V, R  a
  17. float    VRefint;  //存放Vrefint电压最终结果$ w& l+ l6 i3 A- D, Y6 `- q: I
  18. float    Temperature;//存放片内温度℃最终结果5 X7 o0 H# t$ q8 E. Y/ M

  19. / e; q+ F. n4 f# h; z9 V: Z
  20. int main(void)
    * p; d5 R# G, G9 P  B8 d: M
  21. {. v) w4 m4 i& p' i0 V. V) C4 r
  22. /* USER CODE BEGIN 1 */
    9 [/ L4 e, J* x5 ?% `' U

  23. # z! X% G5 E5 r1 K6 n6 N3 u" ^
  24. /* USER CODE END 1 */
    + o. r1 o0 j( N$ N  U  i! ]% \

  25. / a' H% j3 a# k
  26. /* MCU Configuration--------------------------------------------------------*/. C9 W* P# \" c# ?

  27. - y1 S  U) v! Q+ w5 }7 p& Q* E! o
  28. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */5 o. T# F, y( U3 D! l4 m& B
  29.   HAL_Init();
    . h( @! p& O4 H: D$ V4 F
  30. / X3 ~8 L! J0 o, r$ O
  31. /* USER CODE BEGIN Init */2 s+ ~& [. r% n% X- [
  32. * Z8 g( y, j9 H, J
  33. /* USER CODE END Init */
    4 i: l( V5 `* g, q# u' i3 C

  34. - d* Y- X  U  _0 v; u7 {% F
  35. /* Configure the system clock */0 k, R, d% t" k
  36.   SystemClock_Config();
    " M, ~6 h" n- p# Y* X

  37. 7 M  ]; @& R/ w6 A  p
  38. /* USER CODE BEGIN SysInit */' u: X9 e, `% K. a4 g* z2 @9 y  ?

  39. , [4 f0 \' s' ?+ n
  40. /* USER CODE END SysInit */
    + j# U0 }) k$ _% K3 B
  41. % H4 R  A, U: [' x) L6 U' K
  42. /* Initialize all configured peripherals */
    $ U% J9 N% s5 D* b+ S2 C! g- c: i1 W
  43.   MX_GPIO_Init();7 c/ ^% s  }( x# h! Q
  44.   MX_DMA_Init();; k, x- S/ V9 k
  45.   MX_ADC1_Init();- ?- Q) A% y7 t
  46.   MX_LPUART1_UART_Init();
    3 x8 f* Q% W. x9 a3 A5 {! p) {
  47.   MX_TIM1_Init();
    2 c4 L" J" W: K4 C) u
  48. /* USER CODE BEGIN 2 */0 {! T2 k, l& R' U6 w/ j6 R
  49. 0 h- Z9 ^9 `" R; @9 b
  50.    ts_c30 = *(uint16_t *)(TS_CAL1_ADDR); //读取30℃时的ADC校准值
    3 ^, Z' G3 ?) [
  51. 5 D  }, c/ k6 u& x, S
  52.    ts_c110 =  *(uint16_t *)(TS_CAL2_ADDR);//读取110℃时的ADC校准值2 ?$ B7 n! N( |* j% O

  53. 7 C. ], n$ l& U5 r# P7 f$ Z
  54.   HAL_ADCEx_Calibration_Start(&hadc1 , ADC_SINGLE_ENDED);//ADC校准
    1 k" n8 ~- N2 l& l" B6 C) p

  55. - r& ?3 e7 l5 ]4 y' W, G& a' w
  56.   HAL_ADC_Start_IT(&hadc1);//启动ADC并开启转换中断/ U1 ]4 b$ J  x& m1 |& w+ @8 q

  57. 8 @4 ^% v" B2 X' f4 t0 N" Z
  58.   HAL_TIM_PWM_Start(&htim1,  TIM_CHANNEL_1);
    " c7 C$ V" g: w  D

  59. ( v7 [: ?# E& `+ s
  60. % Q  Q0 U) C9 m. W5 P: {, f! `" _
  61. /* USER CODE END 2 */& J1 T1 d7 I$ z! d6 y* U1 Z
  62. & _  ?; T& n1 N" R4 g
  63. /* Infinite loop */+ X& c( b& ]: W8 P' |
  64. /* USER CODE BEGIN WHILE */
    2 B# q5 F% s. ^% M) J
  65. while (1)$ T6 U; b; n9 Q: ]
  66.   {7 K, v3 v# e1 g* \0 Y, G
  67. /* USER CODE END WHILE */
    ( s" f" ]9 G) x; \

  68. % d* G0 q+ H: X; r; l+ H  {, M
  69. /* USER CODE BEGIN 3 */2 z1 S  U% d: |4 i

  70. & u) j0 e8 o4 l/ S
  71. if (EndofCon_Flag!=0)+ U" B: x5 P. V( s* l& B' ^  o8 B
  72.   {
    5 R3 w( C! J/ x+ @1 n; \
  73.     VBATVolt=(ADCResult[0]/4095.)* 3.3 * 3.;  
    9 U& P( h7 I2 t" B  Q9 ~

  74. 7 I) i/ f5 v; Z
  75.     VRefint=(ADCResult[1]/4095.) * 3.3;  + W5 W3 u6 Y# s, z, U( c' y* w. V
  76. ! c' u$ }! q: o0 G7 r) F1 L
  77.     Temperature = 30.+ (88.*(ADCResult[2]-((ts_c30/1.1))))/(ts_c110 - ts_c30);
    5 B0 q' |) M  ^- Q6 @; j

  78. 1 r5 y2 K( @7 J8 |
  79.       EndofCon_Flag=0;
    % |4 I; l( Y- ^1 D) g, V1 Q( t
  80. . Y4 s4 ^3 j" X6 \. [! Q
  81. //HAL_UART_Transmit(&hlpuart1, (uint8_t *)WDVol ,sizeof(WDVol), TX_Timeout);
    1 x$ l" l& p( {

  82. 9 f+ C  b# ^  C
  83.       HAL_GPIO_WritePin( GPIOC,GPIO_PIN_3,GPIO_PIN_RESET);  //for auxiliary test; ?& _  h: f1 ~. m
  84. 4 ]8 }2 Z  o* ?3 M6 P
  85.       HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)WDVol ,sizeof(WDVol));
    $ v: J: J7 j4 N, _0 |; r! R
  86. ) a4 C3 L' U  R3 k, C
  87. while(Completed==0){}
    4 q2 y3 s7 p2 q7 `
  88.       Completed =0;
      ^8 V. c' Q3 _3 e9 A) @

  89. , D- J" r* n& x) }1 i
  90. ! }- D  @8 T+ k( w+ e& `
  91. //HAL_UART_Transmit(&hlpuart1, (uint8_t *)InVol ,sizeof(InVol), TX_Timeout);) ^; Q5 m; G: j4 p4 a  X# L
  92.       HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)InVol ,sizeof(InVol));
    ' Y% z& n( m- p8 a2 u6 W- \# f* o1 |

  93. : ?8 t- F  |! F
  94. while(Completed==0)  {}
    2 `) S" T1 r# n! j" C$ p: |7 a
  95.       Completed =0;
    2 b/ C- Z9 E$ G4 N0 M+ k

  96. , h0 e8 m: k/ g& b
  97. " S: V) R( c8 T  E# @
  98. //HAL_UART_Transmit(&hlpuart1, (uint8_t *)BatVol ,sizeof(BatVol), TX_Timeout);2 ^3 O$ O8 _  |
  99.       HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)BatVol ,sizeof(BatVol));
    $ H" ^$ U+ n: N7 r! b# H: o" E
  100. . j/ A: ~7 D" z/ N3 I# D0 L
  101. while(Completed==0){}) ^7 P5 |+ }6 S4 _8 v3 e  e
  102.       Completed =0;
    ) F: I+ Z! Y6 ~1 C( n1 b

  103. & o! z( P  e! l
  104.       HAL_GPIO_WritePin( GPIOC,GPIO_PIN_3,GPIO_PIN_SET);  //for auxiliary test# Z4 J1 T' S  v$ ^9 q' c3 l

  105. ' s$ v5 }3 O* y
  106.    }   
    - m; E2 S  ]4 [  A' H, t

  107. ( y9 J1 z5 D7 p$ o% K
  108.   }
    : V' f( L3 M* c8 k
  109. /* USER CODE END 3 */$ y) ^+ q  w# ^+ e0 J& r
  110. }
    . z( z. t% H: D' e, x

  111.   Z3 t% X0 i9 n+ ]3 r0 X
  112. //ADC EOC 中断回调处理函数
    9 L$ ?- _4 t) k4 ]2 T, j, U( k( T
  113. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
    - t) x5 w' c  o9 M1 F
  114. {
    # b5 S. n& d1 i8 l- U
  115. $ D2 Z. O! @: W+ _4 O* C
  116.   ADCResult[convCNT]=HAL_ADC_GetValue(&hadc1); //获取转换结果并存入数组
      C' ]: R2 p+ M. ^/ [$ l+ B6 q

  117.   m8 z" _9 N4 A/ o' q& r
  118.   convCNT++;
    ! `# x1 G9 N* g0 U5 c, y2 v1 p# Q
  119. & \8 U' L% F( `* `, f: F
  120. if(convCNT==3)  
    1 E$ o" q& Y" ^# ?! }, `5 [' t

  121. 4 h1 I; F3 {. e/ C
  122. {
    9 |8 V/ E" f9 w1 L1 h! P
  123.     convCNT=0;
    1 J1 m. X$ n1 i4 p

  124. 4 r# O: h. S  M2 A. R0 O& z
  125.     EndofCon_Flag=0xff;
    : a8 z' |$ o  D6 g3 E

  126. 4 ]/ Q2 _. `1 t' W& e* w" v: K
  127. sprintf(WDVol,"Internal PN Temperature: %5.3f  \r\n",Temperature);  
    9 y' E/ Q0 U$ o! |
  128. * Q6 a5 d- Y& B' G7 Y7 M
  129. sprintf(InVol,"Internal Reference Volt: %5.3f  \r\n",VRefint);  
    5 E  t  ~# T) m5 d# j7 |- x
  130. $ G$ s! ~- ]7 L) w7 H
  131. sprintf(BatVol,"Current Battery Volt:   %5.3f  \r\n\r\n",VBATVolt);
    % n& @3 u4 M' M5 ^; f6 u

  132. ( `. w9 P+ s; `; B/ B( |. O
  133. }
    . F6 K& z" M1 A4 C

  134. ) E& }! K8 D; R1 Z0 z1 \7 O
  135. }) ~1 R" }' p, i4 {- b- b7 f
  136. 2 j- b! I. ^4 j; B: K5 C
  137. //UART DMA 传输完成中断回调函数
    8 E' |# m; l  |6 M2 \1 \
  138. , {3 r% t3 Q9 w3 Q% A
  139. void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
    1 ~# K4 }) ^- w
  140. {, h# H5 i# P' |4 n3 L2 r+ J

  141.   F6 I8 R/ |5 u- F9 _2 P
  142.   Completed=0xff;# n3 `, F3 R6 n  f3 E% K
  143. }
复制代码
0 f/ U5 B+ I" g4 R
基于上面的配置和测试代码,我们就可以看到最终的结果了。定时器周期性地触发ADC,每得到3个ADC结果就进行数据处理,然后通过UART以DMA方式传输到串口终端。注意VBat电压是测量结果再乘以3得到的。
: A) h0 G) M: h6 k5 O8 g# t: f  m2 G4 [: \" c, p
微信图片_20240118185941.png
0 h4 J$ J( g9 U; Y# }' @# T5 K

1 o- C& K2 i7 w) H
微信图片_20240118185938.png

0 m5 v: H0 e7 y# K8 _4 z- |" i: z; `& `7 h% h
针对上面的应用演示,最后给几点相关应用提醒:' [, h2 Q* h- ?) g$ J2 N0 E
1 @7 m* u5 Q) m; I' U3 n- C
1、针对温度传感器做测量时,校准时使用的参考电压与实际应用不一致时要做换算,换算成相同参考电压的数据后再做计算。这点前面也提过了。
% f1 O3 m- D7 q9 [
+ U+ x0 b+ ?+ x3 v5 Q' c/ [2、使用TIMER的TRGO触发ADC,如果选择类似比较事件、更新事件来触发ADC时,此时ADC对触发极性的选择是无效的,或者说ADC的转换仅依赖于触发事件时间点。如果是选择TIMER的Ocref信号作为触发源,此时ADC的硬件触发的极性选择是有效的,可以是上沿或下沿触发,甚至是双沿触发。这时就得根据需要选择合适的触发沿。【可以进一步阅读本公众号文章《STM32定时器触发ADC的时序话题》】2 d- @; \+ ?. h0 x
- M9 b" q  t# ?7 {7 M9 x4 ]
3、这里使用UART的DMA传输依次显示三个结果于串口终端,三个启动UART DMA传输的函数须保留适当时间间隔,即等上次传输完成后再启动下一次传输,因为这里每次传输使用的是同一DMA通道。否则没法全部正常输出。比如若把上面3次UART DMA传输的代码改成下面这样子:
' s6 r3 m6 I, d( q7 p3 G! b  S4 @, \; W% x, t
  1. HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)WDVol ,sizeof(WDVol));+ v, p: {6 e! d5 D, R; R0 |

  2. ; o$ B5 S% W" s, \5 D+ M' h
  3. HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)InVol ,sizeof(InVol));
    9 v- F0 r* v3 q7 O8 r
  4. 1 Y2 E" [- H& j  \! S) u
  5.   HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)BatVol ,sizeof(BatVol))
复制代码
2 j# `( C' I* `5 l, O$ A6 X1 \/ ?
这时输出结果会变成下面的情形,总是只能看到一个结果的输出,即第一次启动的DMA传输结果。0 ^$ X5 f# o  p3 x$ Q, q% S; e

0 o9 W+ g' E: u- j4 e3 V: x

( l8 X3 S; R5 j2 e6 L% ?2 T- D0 s
$ ^5 c$ a2 v8 a$ Z, L! n4 O如果想省事点,直接在相邻2次DMA传输间加上合适延时也行。我这里根据DMA传输完成事件来决定执行下一次发送。在DMA传输完成中断里设置Completed变量为非0值表示当前一轮DMA传输完成。
+ ?# I& G2 ^0 d% Z) [
' D1 s' }. O4 U. H/ u9 W  f4、对于那些在中断和主程序里都会被访问的变量,记得将它们冠以volatile。+ P$ r9 C9 r. g5 L% p
+ m6 E% v4 ]' R9 i' `3 e, W0 H3 g
下图的三路波形是我调试时辅助使用的。
8 f. {6 F3 P. [3 e! Q0 E
, g8 r( i% b" v8 t% x, v1 Z8 r第一路表示计数器的计数变化,显然是单向向上计数模式。, `$ B( s( N; J

% @: r5 v, e0 n8 j! |* j第二路是TIMER1通道1的PWM输出波形。
0 Q; b+ _! I! C1 H
, |. j8 v, Y- p7 j5 A! c9 d; @: ~第三路是我每次基于DMA实现UART发送时拉高拉低的波形。平常管脚电平为高,在实现DMA传输过程中拉低。$ H8 q' V. Q2 `8 {  _4 n

  m8 I- _9 y; e- c
微信图片_20240118185918.png
/ b) A. u, Y$ }* Z
' B1 l7 o1 }- m" E4 q4 n; m
如有侵权请联系删除
% ~! C/ u1 a! B; {转载自: 茶话MCU' N0 W3 y+ z" Z; c% {. q& i

/ V) u  J5 I! n
& ]# q. D$ @1 R6 Z, l2 S& b  e

  a  u& n; W7 ]: }) i7 _
微信图片_20240118185921.png
收藏 评论0 发布时间:2024-1-18 19:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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