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

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

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

$ E2 |9 z8 q. o6 _
4 v/ W" R, e  x% P$ j; Y

2 Q$ `( a1 U' T) b很多STM32芯片里往往内置了专用的ADC通道,比方用来测量Vrefint,VBAT的分压或温度传感器的输出电压信号。不同系列所内置的模拟信号通道可能有差异。这里以STM32G4系列为例,它内置了对应于Vrefint,VBAT的三分之一分压和温度传感器的输出电压的专用模拟通道。
9 c, Y9 b8 w2 ?* M! D! x
/ a7 i) b5 R9 p- b/ ?" c
微信图片_20240118190028.png
# _( S; [) g  B% z& c

* p7 p9 M4 K# j: i
微信图片_20240118185948.png
1 `1 o; X# C: x% V
# s! c% G$ u7 z! A1 e
下面的示例就是针对上述3个通道进行ADC,并测量相关电压和片内温度,最终得到3个结果,分别是VRefint电压,VBAT的电压,片内温度。
* K  e' v! L( R& U2 t
* W) ?! G) f8 O, @# l
微信图片_20240118190017.png
6 ?% z; b, f' L, A6 \( b% A! s: ]

9 g3 k1 G7 S: F! n' u( [实现过程是这样的,大体分四步:【有点点麻雀虽小五脏俱全的味道图片】
  B2 H+ f+ i6 i& x9 h4 B* H" Q+ _: g5 \7 I
1、TIMER1 更新事件触发ADC的转换;
) i5 n5 x, O  r. x* E- u0 h
. M& ]& s# U) c+ g( W2、CPU基于EOC中断获取ADC结果;/ m1 d1 |8 i  ~" n' z0 I7 O2 `- [
9 Q% o) z  X5 n$ Z) V% @& ^: V( A
3、对ADC结果进行换算,得到电压值和温度值存放在特定内存位置;# O  B  N4 o7 K  p! L0 Q' W
& C* g7 [6 \5 s: s
4、基于DMA传输通过UART将最终结果在串口终端显示;3 R$ a8 A, g# Z7 D

1 j) E; b, n  M+ `4 j" n其中,TIMER1的CH1输出PWM波形,其更新事件做ADC的转换启动信号。每次的TIMER更新事件触发ADC,3个通道扫描方式转换。这里的UART使用片内LPUART,使用它主要是考虑它跟板载虚拟串口直接相连,没有其它特别用意。
! d! A% O7 @7 D; G8 {8 b3 T, v* d' q
微信图片_20240118190012.png

1 L3 u! B0 v% n3 N: k! Y" X; q( D8 N. J
, K, y/ k, ^" u% @2 n4 _& x我使用STM32G474Nucleo板来进行下面实验。其中VDD=3.3v,VBAT与VDD相连。另外,ADC模块的参考电压也是3.3v.' H* ]0 e4 [: n6 H3 O* l" [  s
/ o7 K* m; T* [8 b" Q" m5 b; o! r
使用CubeMx图形化工具进行配置,先看TIMER配置:, B( S5 W6 Q1 u( [: M7 p
0 w, X  ~8 ]) j4 S) ?
微信图片_20240118190009.png

: F5 E! z, X- ]& Z" K7 G3 l+ L4 E* D
再看看ADC的基本配置:
6 K$ [7 Q% p+ B/ D% O4 C0 |6 z6 i& w, e1 @2 s. k- P6 l
微信图片_20240118190005.png

& e' j3 t  S/ R
9 G" s6 X1 g4 f5 b5 CLPUART的基本配置:
4 P6 A/ @/ P  f$ b8 u
8 j+ m2 R: p: W+ ~8 ^
微信图片_20240118190002.png

. ^1 O: M2 ^/ F9 e; P
- R: {5 J* S8 ?4 Y2 Y因为要使用ADC中断和UART的DMA传输,记得做ADC的中断响应使能配置和LPUART的DMA配置,这里只使用UART的TX DMA功能。
, J1 Y7 Y( p: H) m
/ ~  V  S: j" w& }9 A; q* L: C
微信图片_20240118185959.png
5 ~, h9 k2 u" F' y8 E! l) }% O. P

! X, c6 C: ]8 T) G使用CubeMx主要配置主要是上面这些。
! x& u" s, I" j; F
$ k8 \+ u/ H$ S! K9 b; {2 I) ?在组织用户代码前,先简单介绍下片内温度传感器的内容。该温度传感器针对不同温度有不同电压输出,其输出电压跟温度呈线性关系。ST公司针对片内温度传感器在两个特定温度【30℃和110℃或30℃和130℃】、基于特定参考电压【3v或3.3v,不同系列以数据手册为准】生成了1组校准值并存放于片内特定FLASH位置。
' [% O+ [) J. f$ o7 i4 D
, i2 H2 Z4 ?, OSTM32G4系列的校准值是在参考电压为3v,30℃和110℃条件下的两个值,在数据手册里还给出了校准值的片内存放地址。- |3 z- p+ x6 D, W
9 U- @# {" l/ `- P- [
微信图片_20240118185956.png
8 P3 I, t3 S$ L7 E& s: i' ]
" M  h* T4 w8 u
针对这个温度传感器的使用,ST公司在参考手册里还给出了计算公式。其实,有无这个公式无所谓,我们不难自行推理出来。【TS_DATA代表某时刻测得的传感器输出电压对应的转换值,TS_CAL1/TS_CAL2分别表示在30℃和110℃条件下基于传感器输出电压的转换值。】
8 T) g4 u5 r' u5 `& l' w7 V
4 {( f" p4 l2 g) c
微信图片_20240118185953.png

2 D$ @+ s7 i/ ?3 Q' K

5 Q" G2 h( w2 V- ^1 u, I) w另外,前面提过,ST公司在手册里给出了温度传感器的两个温度下的校准值,但要注意生成校准值的ADC模块所用参考电压跟我们实际应用时AD模块所用的参考基准电压可能不一致。如果不一致,就必须将ADC值换算成同一基准参考电压条件下的数据。目前在ST手册里也特别强调这点了。我把上面一副图再贴一遍于此【见黄色语句提醒】。
% U# x- U9 j, h4 H4 \4 C4 X6 c% P# T
, R: M4 I, M% i
+ V! J3 M% S4 k5 ~( p) H
关于这点,我们也不难理解。同一待测信号、同一ADC模块在不同基准参考电压下转换值往往是不一样的。见下面示意图加以理解。
! a  Q9 U% h/ J5 }- X) f6 l, H
) X  d/ B/ R% w4 ^, T% e4 S
微信图片_20240118185944.png

& V" W$ u/ U# w8 U8 w- I

% M! a$ ]+ Z( P/ h完成各项配置后,创建软件工程。添加必需的用户代码:
4 V" P$ s3 J" h7 W/ A5 c1 G/ Y7 c4 H1 \2 S' g
  1. #define TX_Timeout (9999)  Y5 ~5 L) \# O4 F3 A# d# ]+ a, r0 U
  2. & s' I1 o9 f! o1 o9 l/ Z
  3. #define TS_CAL1_ADDR  (0x1FFF75A8)  //用于计算温度传感器数据
    : h# W( a; G. ~+ z  `7 [: }
  4. #define TS_CAL2_ADDR  (0x1FFF75CA) //用于计算温度传感器数据) P8 I) c0 {8 T( h8 O6 u  G( S8 T: A! l

  5. # W3 e" K  G2 w1 M- C% ]# F0 \% V1 O% o
  6. #define size1 (40)
    - S5 _9 N2 }6 M
  7. 6 R0 O* a5 F$ f7 n
  8. char WDVol[size1],BatVol[size1],InVol[size1];
    + }; v. _1 L( }+ Y7 s* S/ f
  9. / [& T7 h0 Y# n& C
  10. uint16_t ts_c30,ts_c110;
    7 N( H/ X2 y% \$ h7 [2 w% X! f4 U
  11. 8 G2 y1 o/ j6 ]/ D0 _8 u
  12. uint16_t ADCResult[3],convCNT;3 h7 i0 M1 k$ a4 }  @
  13. 8 ?+ _9 U4 c5 z. v4 ?
  14. volatile  uint32_t Completed,EndofCon_Flag;
    9 _! e  g3 w7 F, S0 @0 o  p' B9 V

  15.   b. R. F1 {4 @& M" G8 m- K0 U) V
  16. float    VBATVolt;//存放BBAT电压最终结果
      x+ d; ]+ g* \. f/ R  H
  17. float    VRefint;  //存放Vrefint电压最终结果* [2 c0 w1 _* A5 {. c. X
  18. float    Temperature;//存放片内温度℃最终结果
      K- U& L/ W6 b# V0 V- p/ I" R7 Y2 q% I
  19. * ?. B1 A( @4 I
  20. int main(void)+ Y& h, a) Y: u: A8 v$ C
  21. {" e$ n% P$ x9 x: l- [# s6 a' J
  22. /* USER CODE BEGIN 1 */
      [/ {: T5 k' ^' H% K2 m* K: F7 f

  23. $ z# w- Y  Y3 h: g
  24. /* USER CODE END 1 */- @/ }6 H/ U/ y# [% q

  25. & @! B" p* K% A- x! ~* e# r9 v5 z+ r
  26. /* MCU Configuration--------------------------------------------------------*/
    - I  q+ x3 ^2 ^0 \- j0 I+ {

  27. * }7 |0 r$ L/ n  N8 v+ f
  28. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    ( ^8 |! O, `- s. b7 C7 P
  29.   HAL_Init();
    - T9 x0 i  B6 O9 H3 U
  30. 4 ?2 U  P2 B! V2 U6 I' z, I
  31. /* USER CODE BEGIN Init */
    7 J8 t, z& v. e

  32. 2 K% o. W7 X5 w/ ]
  33. /* USER CODE END Init */
    , S& N% E5 ?7 A8 r: U0 T4 z

  34.   c- k' b8 P/ Z" T0 M& j
  35. /* Configure the system clock */
    : o8 `* U1 b' t
  36.   SystemClock_Config();: r: P0 l, H) G

  37. 5 r7 q9 L* f/ m6 g
  38. /* USER CODE BEGIN SysInit */
      g. K2 `# Z% n. ]5 ?* H

  39. 8 N3 ?0 B9 X7 p* r- e+ C. [- U
  40. /* USER CODE END SysInit */
    : Q0 t% z1 \0 L9 v# U
  41. 5 E' H- a6 J  P% k
  42. /* Initialize all configured peripherals */. l. r2 L  x6 L
  43.   MX_GPIO_Init();
    + V/ R0 |9 e( x; E6 t, v
  44.   MX_DMA_Init();
    ( f0 O  A; T) v$ m: \% t5 Y
  45.   MX_ADC1_Init();" R! j5 _4 v: U( k6 x$ g0 y
  46.   MX_LPUART1_UART_Init();: n6 H( m+ T: j' R8 n/ |) _! r
  47.   MX_TIM1_Init();' S/ B% Y( p* t- G, D# P
  48. /* USER CODE BEGIN 2 */* ~2 M, P7 |0 Z( ~$ M5 y# D9 U0 `! v1 a
  49. ! O( t- J: O5 B/ F4 d( i8 `
  50.    ts_c30 = *(uint16_t *)(TS_CAL1_ADDR); //读取30℃时的ADC校准值9 U5 z( u1 L2 C. {2 h' [+ p

  51. ) o2 {; V2 i: u6 k. r. \' d
  52.    ts_c110 =  *(uint16_t *)(TS_CAL2_ADDR);//读取110℃时的ADC校准值
    + w8 D* v7 i# n7 [+ J. y0 q
  53. ' b6 b6 F0 L# g
  54.   HAL_ADCEx_Calibration_Start(&hadc1 , ADC_SINGLE_ENDED);//ADC校准
    0 v) I3 Z6 u) O+ }( Y

  55. ) Y; l$ S: \+ p8 p* s8 T- Z; a* }
  56.   HAL_ADC_Start_IT(&hadc1);//启动ADC并开启转换中断3 M1 N& z8 m: S* Z% z1 m- d- x9 x
  57. , t- i4 b0 ^" T4 w; o  g1 P' o
  58.   HAL_TIM_PWM_Start(&htim1,  TIM_CHANNEL_1);
    9 R$ q. e3 a/ y. N
  59. + L2 G8 Q' o1 O4 B$ f% ?  {* {
  60. ' s3 a; a9 {1 Y$ }( M2 V
  61. /* USER CODE END 2 */
    - B- c4 \" v# s4 q% l

  62. 0 G6 n% l( F+ W
  63. /* Infinite loop */2 G4 P- a2 U1 w
  64. /* USER CODE BEGIN WHILE */
    4 T6 v" C% x: A" r" j2 p+ S( J
  65. while (1)/ }, L  X* b* j7 u
  66.   {
    6 z5 B+ U% x" f+ ^' e, [1 c
  67. /* USER CODE END WHILE */& v# q+ g& p, M% V; X4 q, i5 M4 v
  68. " u" v" w; E' B
  69. /* USER CODE BEGIN 3 */) w% D# ]1 x; E3 S3 ?* N5 k/ K
  70.   d7 H9 w1 V; q( M# ?8 Q, z& e
  71. if (EndofCon_Flag!=0). l) e+ C9 [# t0 j
  72.   {6 P/ u) G# E; i* x
  73.     VBATVolt=(ADCResult[0]/4095.)* 3.3 * 3.;  9 F6 X6 T6 ?5 N- F5 @" t5 v1 Y0 ]
  74. 4 V* ]7 [" l! o, O( j8 R; m1 ?
  75.     VRefint=(ADCResult[1]/4095.) * 3.3;  # x* P) U- x5 T1 U( Z

  76. , i( T# A2 Q( p& Q3 g  K
  77.     Temperature = 30.+ (88.*(ADCResult[2]-((ts_c30/1.1))))/(ts_c110 - ts_c30);% H4 a( c! c* S: |$ X; r( l

  78. $ \! T# q4 e! ]+ e0 v: C4 E
  79.       EndofCon_Flag=0;
    ! m3 }  |4 R2 w/ e# Y

  80. : ~, ~" T5 E, n# [  N
  81. //HAL_UART_Transmit(&hlpuart1, (uint8_t *)WDVol ,sizeof(WDVol), TX_Timeout);4 w; e) X# e/ H( P2 ]. I2 |( }

  82.   m  L+ _) a. h8 E  B" c* P' T* M/ ]
  83.       HAL_GPIO_WritePin( GPIOC,GPIO_PIN_3,GPIO_PIN_RESET);  //for auxiliary test
    - \0 s9 D) P; S5 \+ \. V4 z
  84. : K$ n1 w, j8 Q/ F( u" r1 L! {
  85.       HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)WDVol ,sizeof(WDVol));
    2 Y7 A4 q/ a* Q  L* o) {$ N" i7 g

  86. & |4 P- [* a+ M
  87. while(Completed==0){}
    9 c9 p' d( m* n3 Y+ f  L
  88.       Completed =0;
    5 J: V- o, ?' |4 `2 v) G' B

  89.   j- s- J2 n5 D7 w
  90. . [' D+ s! P, K' W' [& m0 f+ @
  91. //HAL_UART_Transmit(&hlpuart1, (uint8_t *)InVol ,sizeof(InVol), TX_Timeout);' }7 z' K+ y. z7 q
  92.       HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)InVol ,sizeof(InVol));9 t  q( g. C8 X5 h3 K
  93. 3 L3 Y6 s$ b2 f' X4 I% @
  94. while(Completed==0)  {}! z/ P' }; a" |* x# i. Y
  95.       Completed =0;# A# o) L5 e4 K, a3 P" n; N! c+ I

  96. 3 B* w( J# N  o# l) M% V- _
  97. 9 D  K/ x& ?8 n
  98. //HAL_UART_Transmit(&hlpuart1, (uint8_t *)BatVol ,sizeof(BatVol), TX_Timeout);# M1 l& b) x! `  I9 B; R, `
  99.       HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)BatVol ,sizeof(BatVol));/ f: c4 K5 A) A  F2 n8 I* f) Y6 H

  100. ( ]# `" J% M) q& Q; f
  101. while(Completed==0){}7 J1 ^& \' s4 K; c* M, t, A* D% l6 A
  102.       Completed =0;
    ) \/ q# u" z: [0 h# d2 X7 ]
  103.   H4 m  [8 J$ R) d
  104.       HAL_GPIO_WritePin( GPIOC,GPIO_PIN_3,GPIO_PIN_SET);  //for auxiliary test
    ! E( P* i" [3 b

  105. 6 B; E; Y( }5 d' z' L- Q2 V& F" F  n
  106.    }   0 d; f) m8 W# t9 f
  107. " W5 u! D: n9 O5 \
  108.   }+ h; j3 V7 m9 h
  109. /* USER CODE END 3 */
    * A* t" C) j3 r- `6 v& b4 P5 z
  110. }
    / |; J, n6 q4 _* k$ z
  111. 6 Y6 M) ^% F; C( n
  112. //ADC EOC 中断回调处理函数; k( ^: G: D- {6 ^4 ?: a
  113. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)5 N8 [# n1 q% L) U6 y
  114. {
    1 A/ j- X4 ]2 ?% x8 Z
  115. 8 Z" E0 ]' U2 `! E! `! A
  116.   ADCResult[convCNT]=HAL_ADC_GetValue(&hadc1); //获取转换结果并存入数组
    ; n$ W- T8 t1 l; t
  117. - i2 r% e$ c) a5 z
  118.   convCNT++;, C8 O, \5 N0 W) ?" z! D

  119. ( M, V5 @$ C/ r$ r
  120. if(convCNT==3)  & H4 a* b8 F- R" u; m
  121. ) j  x) U" h$ x, X
  122. {
    $ c3 r% K2 `& Q) @, M  ^
  123.     convCNT=0;
    9 {5 ~+ B3 P, R9 N
  124. - h/ ~4 b4 G5 {& E0 E8 @$ k
  125.     EndofCon_Flag=0xff;
    # {1 Z9 y. X: \, s/ K# S

  126. 4 z( f4 s& j( E8 v% z* v
  127. sprintf(WDVol,"Internal PN Temperature: %5.3f  \r\n",Temperature);  & l5 J7 m/ k! s4 Y. P' n
  128. 8 ?0 X0 {8 ]3 j$ d
  129. sprintf(InVol,"Internal Reference Volt: %5.3f  \r\n",VRefint);  
    3 R; `. l' x4 ^8 G
  130. 2 p3 m+ j# t& G* p6 V  o: l! p
  131. sprintf(BatVol,"Current Battery Volt:   %5.3f  \r\n\r\n",VBATVolt);
    * X$ _4 ?; G  z( y

  132. 9 |& B5 l, Q& _0 F( f7 I" b- J
  133. }- ]7 l% o8 Q& K( K3 e

  134. ; K; r7 ~8 K, b
  135. }2 l% F  j0 {/ M- h

  136. ' r& @; M; Q$ i
  137. //UART DMA 传输完成中断回调函数
    $ h5 ^4 A' D. ]. T, _% K* ?
  138. 0 R, i! B0 ]; Z. m
  139. void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)# j" ]2 l2 S1 s! {" g
  140. {
    9 L( h2 P: t# t/ V3 g- k4 Q7 A
  141.   S1 K2 a9 {( n  y
  142.   Completed=0xff;
    * O. I! }& N! _+ D, s, T
  143. }
复制代码
8 G1 T; u3 I  ^' a
基于上面的配置和测试代码,我们就可以看到最终的结果了。定时器周期性地触发ADC,每得到3个ADC结果就进行数据处理,然后通过UART以DMA方式传输到串口终端。注意VBat电压是测量结果再乘以3得到的。
# }4 e1 |& Y* [' l
6 Z; L! C+ X) ?! ?: h  {
微信图片_20240118185941.png

/ l4 y( x( S: b: @' {) t7 q7 F! F/ o% j/ e4 c, _. d
微信图片_20240118185938.png
6 O9 V+ {. N5 R' G- A' t' n: L
0 c/ e' J: X( M( p% i/ V1 C" a
针对上面的应用演示,最后给几点相关应用提醒:. B! e, p5 `/ |: s* ^2 x) ^) h# I

7 C" p9 s. Q9 `- U6 N1、针对温度传感器做测量时,校准时使用的参考电压与实际应用不一致时要做换算,换算成相同参考电压的数据后再做计算。这点前面也提过了。
  B/ f9 x8 L" ^9 ?' W2 W) F; M; T
% l1 p. I' O* `/ S2、使用TIMER的TRGO触发ADC,如果选择类似比较事件、更新事件来触发ADC时,此时ADC对触发极性的选择是无效的,或者说ADC的转换仅依赖于触发事件时间点。如果是选择TIMER的Ocref信号作为触发源,此时ADC的硬件触发的极性选择是有效的,可以是上沿或下沿触发,甚至是双沿触发。这时就得根据需要选择合适的触发沿。【可以进一步阅读本公众号文章《STM32定时器触发ADC的时序话题》】) F/ e1 E# d7 v/ w5 a
7 K1 s5 V0 K8 L" U# b) S* U$ e
3、这里使用UART的DMA传输依次显示三个结果于串口终端,三个启动UART DMA传输的函数须保留适当时间间隔,即等上次传输完成后再启动下一次传输,因为这里每次传输使用的是同一DMA通道。否则没法全部正常输出。比如若把上面3次UART DMA传输的代码改成下面这样子:+ Y2 y% b  j* `9 c$ Q+ \: D
+ D6 \4 w% Z" t1 L$ ]" s* l; T
  1. HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)WDVol ,sizeof(WDVol));3 d$ t3 l( w8 m6 S. q

  2. 2 d% W1 C$ G0 m* _6 z3 L+ B+ }
  3. HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)InVol ,sizeof(InVol));
    8 ^1 |9 I( C( l( D
  4. , Z8 G4 h6 d& g, B) f3 `4 R
  5.   HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)BatVol ,sizeof(BatVol))
复制代码
3 _  V; ~- |8 a
这时输出结果会变成下面的情形,总是只能看到一个结果的输出,即第一次启动的DMA传输结果。" K3 G# n* a% p

/ F+ M2 F2 h( y! K$ z: S
  F: @0 s6 v) j9 K

" R3 m- g# _1 F8 a如果想省事点,直接在相邻2次DMA传输间加上合适延时也行。我这里根据DMA传输完成事件来决定执行下一次发送。在DMA传输完成中断里设置Completed变量为非0值表示当前一轮DMA传输完成。
* o' j' J6 ]1 T; G- ^( }& c' m9 X* ~7 Z; `$ W
4、对于那些在中断和主程序里都会被访问的变量,记得将它们冠以volatile。% y# b! F3 ?: x  R* u

  o9 N  [, C; [8 q0 J下图的三路波形是我调试时辅助使用的。8 N( [! W( p7 |7 M4 r
+ M& Z" Y7 F0 Q  M
第一路表示计数器的计数变化,显然是单向向上计数模式。: J3 P1 X1 j9 V! Q
; }; l+ r/ A8 Q0 K4 n/ ~* N
第二路是TIMER1通道1的PWM输出波形。& P, |3 o; t! S! T& T

$ A* A# @- Z, e0 y' m8 c  H第三路是我每次基于DMA实现UART发送时拉高拉低的波形。平常管脚电平为高,在实现DMA传输过程中拉低。
  x6 f6 K/ n( J: c0 G1 {) j/ {- d$ C- l' t
微信图片_20240118185918.png

, N, k0 S' R* P2 `! P& [6 ~+ g; }& r4 C* V" z2 h7 Q/ W* h
如有侵权请联系删除: N1 R' y5 J% J4 Q
转载自: 茶话MCU
7 k4 l/ c  `4 z. [! E5 T
( g! p8 E7 I; |* C% i
& d  o2 [; b+ @

7 e% O* p* p3 J/ }$ K+ |
微信图片_20240118185921.png
收藏 评论0 发布时间:2024-1-18 19:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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