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

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

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

! i" G+ v1 C% F$ ?7 Z$ o- [$ y* d) x, U9 n2 X. d2 ]0 Z/ n

1 H- |7 I, m- G! P, S很多STM32芯片里往往内置了专用的ADC通道,比方用来测量Vrefint,VBAT的分压或温度传感器的输出电压信号。不同系列所内置的模拟信号通道可能有差异。这里以STM32G4系列为例,它内置了对应于Vrefint,VBAT的三分之一分压和温度传感器的输出电压的专用模拟通道。
" R) j9 f: [; W' x  k! ?5 W) |1 O+ y
  g  S4 |' ]4 R9 [6 g
微信图片_20240118190028.png

( Y" L2 U, W0 n  L& _% @0 u; Q4 S  A9 D& J: Q
微信图片_20240118185948.png
- U" z, S! q5 G' R/ E! c3 b
% Z  e) q' U* q( X  V( T5 O- }3 g( `
下面的示例就是针对上述3个通道进行ADC,并测量相关电压和片内温度,最终得到3个结果,分别是VRefint电压,VBAT的电压,片内温度。
0 j3 k% @: X" ]* {4 J, f; G% X: ^% y& G4 z) N0 j7 l
微信图片_20240118190017.png
1 F" Q- I& u5 M9 D3 p
* t+ c. k  y) ]8 t
实现过程是这样的,大体分四步:【有点点麻雀虽小五脏俱全的味道图片】
4 t7 C0 ~4 w, Y0 n- m' A2 j
% |* `: G- U9 p; S1、TIMER1 更新事件触发ADC的转换;
3 s8 g0 G+ t+ d- o0 W8 @" N% b3 P# x* P# k1 G8 X! Z" C
2、CPU基于EOC中断获取ADC结果;6 F8 K1 f( g/ u: i5 C5 \- q- H2 r# n
; d4 b1 U) T- l
3、对ADC结果进行换算,得到电压值和温度值存放在特定内存位置;4 g) k# ~1 J7 X4 M9 W
2 X; {; ~$ R( T$ M
4、基于DMA传输通过UART将最终结果在串口终端显示;7 q' a  ^- V, R

* @1 q8 @- N& X8 V4 b  N6 N! U其中,TIMER1的CH1输出PWM波形,其更新事件做ADC的转换启动信号。每次的TIMER更新事件触发ADC,3个通道扫描方式转换。这里的UART使用片内LPUART,使用它主要是考虑它跟板载虚拟串口直接相连,没有其它特别用意。
, d% a4 G5 \. ?: ?7 r/ `3 x  z8 I& d( [1 q
微信图片_20240118190012.png

3 R& o/ J5 P$ y8 I1 [' O; H! f& b- P
我使用STM32G474Nucleo板来进行下面实验。其中VDD=3.3v,VBAT与VDD相连。另外,ADC模块的参考电压也是3.3v., H- h# x, l1 g( o. y

) R9 y* W2 B5 M  W% f使用CubeMx图形化工具进行配置,先看TIMER配置:
: ^# F+ L9 T7 l
) F4 l/ k, P3 \' z0 p1 k: N# J
微信图片_20240118190009.png

# n- i0 l! j0 I' j, u% A
5 W; k; u4 n5 F8 p; `& Q1 Y2 F( _再看看ADC的基本配置:
3 I. @9 d: O5 Z* f: b
& q: U' ?6 x/ O( ^+ ?* H
微信图片_20240118190005.png

0 |* S3 h, X7 h0 E4 b( X8 L# X! z6 U- K, V& \) B
LPUART的基本配置:2 L- L/ M6 t" `9 ^2 l# R7 H! p

2 ?$ G5 L. j& M# L3 p  n
微信图片_20240118190002.png
7 r+ A3 `; k$ ?9 _/ \

4 \9 @5 K; \* B$ T因为要使用ADC中断和UART的DMA传输,记得做ADC的中断响应使能配置和LPUART的DMA配置,这里只使用UART的TX DMA功能。
/ [/ `! Y: c2 ~. p, D- n1 o$ g9 j' f7 l! ~' C- N+ `/ F0 n
微信图片_20240118185959.png

/ p( l$ M( u# g$ y  e0 F* D9 M& D

; h1 k0 O1 s) G0 Y  F使用CubeMx主要配置主要是上面这些。) H  s. h5 ^: u2 R6 L: T8 J0 e7 p9 `
- q) g, `3 r5 p- f$ I2 u
在组织用户代码前,先简单介绍下片内温度传感器的内容。该温度传感器针对不同温度有不同电压输出,其输出电压跟温度呈线性关系。ST公司针对片内温度传感器在两个特定温度【30℃和110℃或30℃和130℃】、基于特定参考电压【3v或3.3v,不同系列以数据手册为准】生成了1组校准值并存放于片内特定FLASH位置。
0 W5 K! W: w7 @" f" e  y# _* ]2 S. m$ |5 c) ^4 m0 A) J
STM32G4系列的校准值是在参考电压为3v,30℃和110℃条件下的两个值,在数据手册里还给出了校准值的片内存放地址。
# T4 b- K' x8 P2 p  l1 h
' _* E" b$ [3 F
微信图片_20240118185956.png

; W2 ?$ h5 b% H! i+ V. \* N
6 b8 s2 T! \1 e7 n+ j* d
针对这个温度传感器的使用,ST公司在参考手册里还给出了计算公式。其实,有无这个公式无所谓,我们不难自行推理出来。【TS_DATA代表某时刻测得的传感器输出电压对应的转换值,TS_CAL1/TS_CAL2分别表示在30℃和110℃条件下基于传感器输出电压的转换值。】# h9 D9 F/ F8 u& v% Z. m7 _) S# A
% |% m* w7 W& y3 D. g! D$ G/ k
微信图片_20240118185953.png
1 [! G; b6 N+ L1 ]$ R" L) h! Q* e3 |

. S3 T& H9 [, d* `另外,前面提过,ST公司在手册里给出了温度传感器的两个温度下的校准值,但要注意生成校准值的ADC模块所用参考电压跟我们实际应用时AD模块所用的参考基准电压可能不一致。如果不一致,就必须将ADC值换算成同一基准参考电压条件下的数据。目前在ST手册里也特别强调这点了。我把上面一副图再贴一遍于此【见黄色语句提醒】。
0 f/ b; i" J  ^5 u3 b# l
/ F* ^" H5 M/ \4 M$ }

: D+ w+ Z  Z! N+ i  z5 D- y

1 y" S6 i7 x; M* Y9 d关于这点,我们也不难理解。同一待测信号、同一ADC模块在不同基准参考电压下转换值往往是不一样的。见下面示意图加以理解。* C+ A5 i. P2 U6 e; M

! I& S0 l8 o$ a1 ^3 G: `
微信图片_20240118185944.png

  K8 S! P" |: o) i

" u; s8 x- a) J, ^完成各项配置后,创建软件工程。添加必需的用户代码:1 N3 N9 x8 ?7 e2 O0 O

0 b0 e) H  n) \$ d/ `+ T' R) p
  1. #define TX_Timeout (9999)
    ! u1 E/ H- q5 g% v% X* s, d
  2. 0 g7 m/ k& |  R( v
  3. #define TS_CAL1_ADDR  (0x1FFF75A8)  //用于计算温度传感器数据
    ' f! A& `( V* g% \. P- b+ u
  4. #define TS_CAL2_ADDR  (0x1FFF75CA) //用于计算温度传感器数据' D. b2 z2 R/ Y! g$ z# J

  5. - P% q6 U' v. x
  6. #define size1 (40)
    1 E: j( ^) I  ~0 ?% U
  7. 2 D* {( B/ B- }; d
  8. char WDVol[size1],BatVol[size1],InVol[size1];
    2 [$ E2 M5 X" b. g
  9. 9 C+ ?+ ]! l4 a4 C5 [5 r
  10. uint16_t ts_c30,ts_c110;  Z) s: G) x' S/ [# A

  11. 0 g& ]/ D8 ~! |! o/ B2 W
  12. uint16_t ADCResult[3],convCNT;
    # v- T# p7 W+ c' M; b6 B
  13. ( Y  k8 \  x0 Q3 v. Z0 \, H
  14. volatile  uint32_t Completed,EndofCon_Flag;
    % N" H4 u# p: Y- ^* ?
  15. . c9 ^) q# L2 r  E. @% Q: L
  16. float    VBATVolt;//存放BBAT电压最终结果
    4 I2 y5 p. A3 j; @
  17. float    VRefint;  //存放Vrefint电压最终结果! A% u9 P! ?- _! M- F% U# O
  18. float    Temperature;//存放片内温度℃最终结果$ w& g  I% P$ ?3 q; Q- i( x2 c) `
  19. 3 h  D' b  d& U- Y8 i& |5 `( j
  20. int main(void)/ f+ j8 S* T3 K; t- H% Z
  21. {+ E3 E5 Z% m1 w
  22. /* USER CODE BEGIN 1 */
    0 ?* v  W+ Y  ^' F

  23. 5 h% q+ i, C4 g. _" u, v- W* e- X
  24. /* USER CODE END 1 */) \  {! I7 _4 l' v* E
  25. 9 f* Y8 g. T/ b6 Y
  26. /* MCU Configuration--------------------------------------------------------*/8 V. k7 o6 c  [; Y7 N

  27. , G! g4 B/ X  w" x! p( t8 j( D
  28. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    " h/ [" p# _" L. w: R5 o1 X- i/ N
  29.   HAL_Init();
    $ \! T9 x( Q& O( C' r
  30. 7 `2 ?+ }0 o. s" E  x
  31. /* USER CODE BEGIN Init */4 h( P' a" w0 `1 M( a9 C

  32. 6 T. {. n3 U$ l  u7 Y) T' y3 A
  33. /* USER CODE END Init */
    7 q! @" U0 n) V( |! E

  34. 2 @) e$ r; p3 i
  35. /* Configure the system clock */
    - F: d2 ~( z' j: P  ~7 W$ _7 C
  36.   SystemClock_Config();) I$ p* W# i6 c) C# m' r* m7 p
  37. & k9 o3 `) D% c
  38. /* USER CODE BEGIN SysInit */
    - P8 l8 l6 a1 p9 R0 g. Q

  39. 9 f$ R- l5 v7 r2 Q" `
  40. /* USER CODE END SysInit */
    : t# D+ A1 b6 z: ]) |- W% J- ~
  41. 4 @, P/ [% `6 P
  42. /* Initialize all configured peripherals */, m- H) s& G5 j# R9 ?7 ~, p& x
  43.   MX_GPIO_Init();
    # |" P( w4 I; {) Q' G
  44.   MX_DMA_Init();. D! {: e; d* y7 @. ?  b
  45.   MX_ADC1_Init();
    + G* }/ k: [& r: b* c- h
  46.   MX_LPUART1_UART_Init();5 w1 u1 h9 u0 ?$ f  }- S7 O3 T* k
  47.   MX_TIM1_Init();$ b$ g  b$ I# n$ F
  48. /* USER CODE BEGIN 2 */
    - i$ U" _9 H8 b2 a/ a( d, |* W! [

  49. ) x% x; N" R1 {" ^9 a) @
  50.    ts_c30 = *(uint16_t *)(TS_CAL1_ADDR); //读取30℃时的ADC校准值
    / H! J* |" b4 s
  51. ! a# u4 i8 @% a' U+ h; `2 T* H
  52.    ts_c110 =  *(uint16_t *)(TS_CAL2_ADDR);//读取110℃时的ADC校准值
    6 ]0 r' d- j! C; o' a

  53.   \; s% p* i/ K6 y0 |* d6 O
  54.   HAL_ADCEx_Calibration_Start(&hadc1 , ADC_SINGLE_ENDED);//ADC校准' W8 I$ c2 }2 w. `
  55. 3 ~3 r9 l. o% q) I* d2 Y* H& q
  56.   HAL_ADC_Start_IT(&hadc1);//启动ADC并开启转换中断% S$ t3 o, d( Q& y

  57. ' r8 F1 i$ \( t3 d
  58.   HAL_TIM_PWM_Start(&htim1,  TIM_CHANNEL_1);, E/ m- S( [" b
  59. 9 e7 H/ C3 ^) Q  b: E: E$ L

  60. : J) c# H% q% Y/ p. m" a( B  ~7 R5 B
  61. /* USER CODE END 2 */
    8 H) M: t/ h. ?9 n, R% T2 G: F$ L) Z

  62. 9 e2 @3 Y9 w& A) M& o( ~
  63. /* Infinite loop */
    & K! P! T$ ?' y
  64. /* USER CODE BEGIN WHILE */
    * q& d. m3 `9 N- D
  65. while (1)
    5 _/ V0 X& u: v  I: g5 g
  66.   {9 ]+ L! a! q5 h, h8 y
  67. /* USER CODE END WHILE *// f6 W1 m/ K7 {. n5 q6 A' E% T
  68. % H3 L0 A/ r+ U; G
  69. /* USER CODE BEGIN 3 */+ t5 B  ?+ F1 G
  70. , R4 U9 A; Q* j# P
  71. if (EndofCon_Flag!=0)
    2 P- i# ]( _; Q; k0 }# H
  72.   {' V. z: t. J  X% H' @
  73.     VBATVolt=(ADCResult[0]/4095.)* 3.3 * 3.;  
    ) X) n! Y( Z4 m5 ]" i
  74. ( M6 v( w7 d, p6 G
  75.     VRefint=(ADCResult[1]/4095.) * 3.3;  
    + x, _( U& x7 e+ M4 B
  76. 4 D$ n% R$ e5 _, |- J
  77.     Temperature = 30.+ (88.*(ADCResult[2]-((ts_c30/1.1))))/(ts_c110 - ts_c30);
      A& m6 x0 p* r5 h# K7 O: |
  78. + e5 D. W7 F$ [9 a, c- \9 m
  79.       EndofCon_Flag=0;
    " K8 @  S. [2 w4 z# Y

  80. ) E7 Z+ l, y; N/ `% G0 i$ s, H
  81. //HAL_UART_Transmit(&hlpuart1, (uint8_t *)WDVol ,sizeof(WDVol), TX_Timeout);+ ^6 O" h7 ?& q) }# L8 ~

  82. # v* h: l/ F! `; s
  83.       HAL_GPIO_WritePin( GPIOC,GPIO_PIN_3,GPIO_PIN_RESET);  //for auxiliary test3 }9 z. u0 ?; o: [/ \
  84. 0 `3 @9 S% @- D4 @5 y
  85.       HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)WDVol ,sizeof(WDVol));; J( }4 d( ?; T% A7 D$ N
  86. 8 K" c7 u& E  g7 E3 ]" Y
  87. while(Completed==0){}
    3 h8 L6 {1 ^% b
  88.       Completed =0;
    9 J& k: ?7 Z7 X
  89.   N! `- @: \8 C% K

  90. # F1 X. K0 p& v5 ~4 s8 G
  91. //HAL_UART_Transmit(&hlpuart1, (uint8_t *)InVol ,sizeof(InVol), TX_Timeout);3 M. \- {3 j1 o+ H" J; T
  92.       HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)InVol ,sizeof(InVol));" G5 L9 A2 A% n
  93. ( J  c" h5 c/ @. u: Y3 V$ L
  94. while(Completed==0)  {}- b/ M) e3 ~$ F! I) j
  95.       Completed =0;
    . W5 T: p3 e' z$ ^

  96. , Y6 {- q$ G0 [3 f
  97. " r! l/ l6 [% _
  98. //HAL_UART_Transmit(&hlpuart1, (uint8_t *)BatVol ,sizeof(BatVol), TX_Timeout);
    0 t/ m1 o( x" Z7 q6 Y# m
  99.       HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)BatVol ,sizeof(BatVol));+ E* [- k! \) ]6 X

  100. / y/ Q; C0 R7 _# J' J# [, Z8 |) }% D
  101. while(Completed==0){}& J9 L& U. `: ?; g
  102.       Completed =0;5 v* E0 }0 v! F" E

  103. + h" T# [% m; G1 E' [% k
  104.       HAL_GPIO_WritePin( GPIOC,GPIO_PIN_3,GPIO_PIN_SET);  //for auxiliary test# h% K0 R  x+ s7 \8 S

  105. 8 ?" T" S6 e# i) @0 R
  106.    }   4 k% H0 R( k" i1 B
  107. , Y! Y  @- p6 V9 t! g/ M
  108.   }+ D% U2 V( Z) E1 T3 ?9 u( x+ m
  109. /* USER CODE END 3 */
    , x4 }3 H; ?+ h6 c- Z+ e# c# j2 O
  110. }: V5 e4 y. C) G/ [

  111. 3 q( s) R' r0 t7 ]
  112. //ADC EOC 中断回调处理函数0 f* e, D  s9 J# ~* f5 |3 O
  113. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)! [8 A% l. V/ u2 M3 W9 r
  114. {
    % k- C# q( `& |5 ?

  115. 5 x; E3 N. u5 P% r
  116.   ADCResult[convCNT]=HAL_ADC_GetValue(&hadc1); //获取转换结果并存入数组
    2 n8 j' n% [5 A8 Z; [& \
  117. . w( P' s) U* f5 T( m, \2 f# k
  118.   convCNT++;
    1 E" \/ {1 k2 `$ Y' }0 `
  119. 7 G/ u+ `! H  `, h5 Y
  120. if(convCNT==3)  
    6 Y1 e( Y1 T$ L9 N* d. O
  121. 4 g# v3 i! q4 ^( L# B- u3 o
  122. {
    1 o$ \7 i) a5 y8 f, a9 d1 u
  123.     convCNT=0;& O0 R, H& a( a6 n2 M7 v; T  N
  124. 3 Z. Z, z4 x5 B
  125.     EndofCon_Flag=0xff;# j+ @9 R9 l- w* o% J! M1 [
  126. 0 A/ {/ L5 ^: b) ^- |
  127. sprintf(WDVol,"Internal PN Temperature: %5.3f  \r\n",Temperature);  
    " ?  y7 o2 t; J
  128. : G$ t  ]. @0 e1 c4 H  ?
  129. sprintf(InVol,"Internal Reference Volt: %5.3f  \r\n",VRefint);  
    9 i: i+ b. V% z9 |8 w; P) W5 f

  130. 7 @# j/ c* k1 q% q* R
  131. sprintf(BatVol,"Current Battery Volt:   %5.3f  \r\n\r\n",VBATVolt);! z$ o9 q; V9 o, K4 G% f, t
  132. ( a( ]  U' Z$ U2 _9 }
  133. }
    ! e% e' S! K; H% b8 f
  134. ( Q8 |8 Y( b1 ~4 y3 n7 k: _
  135. }. {0 H. r+ ?, a* E% Y1 E

  136. + o4 J& J6 [" B- W
  137. //UART DMA 传输完成中断回调函数
    : w& V6 ^8 d1 l' \" t
  138. ; S8 ~& K4 X) l, ^( y: r! A
  139. void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
    , q4 A! U- J, `! t+ Y
  140. {" Q' |2 A( a( h
  141. : }0 s3 [" m% U! [* j1 [
  142.   Completed=0xff;
    4 u, K/ Y- t+ }" D/ D/ c
  143. }
复制代码
' g% R4 }8 r- a5 N! t9 E  N: L7 z
基于上面的配置和测试代码,我们就可以看到最终的结果了。定时器周期性地触发ADC,每得到3个ADC结果就进行数据处理,然后通过UART以DMA方式传输到串口终端。注意VBat电压是测量结果再乘以3得到的。/ q9 O' h7 [* x7 L6 U3 m

* C' p, F* L/ V
微信图片_20240118185941.png

+ M7 [1 b6 {, I- \9 h/ \7 G% T) k5 C! U
微信图片_20240118185938.png

3 G8 t) I( f1 J$ F3 f
3 U, }2 w4 M, D+ M; l针对上面的应用演示,最后给几点相关应用提醒:4 l3 ~) F% O, p6 H# c' S5 G$ g) |- Z4 L

. ?+ x4 E) J# [! k2 `  _2 h1、针对温度传感器做测量时,校准时使用的参考电压与实际应用不一致时要做换算,换算成相同参考电压的数据后再做计算。这点前面也提过了。. P7 `+ J3 J: ^& w9 V/ l# M* p
+ I: n/ L: M  Y# ?) ]' n7 {
2、使用TIMER的TRGO触发ADC,如果选择类似比较事件、更新事件来触发ADC时,此时ADC对触发极性的选择是无效的,或者说ADC的转换仅依赖于触发事件时间点。如果是选择TIMER的Ocref信号作为触发源,此时ADC的硬件触发的极性选择是有效的,可以是上沿或下沿触发,甚至是双沿触发。这时就得根据需要选择合适的触发沿。【可以进一步阅读本公众号文章《STM32定时器触发ADC的时序话题》】
$ r9 U3 O  a! i) ]- Y6 r7 C) {' i, f9 I, R  W1 B6 q8 ^" n
3、这里使用UART的DMA传输依次显示三个结果于串口终端,三个启动UART DMA传输的函数须保留适当时间间隔,即等上次传输完成后再启动下一次传输,因为这里每次传输使用的是同一DMA通道。否则没法全部正常输出。比如若把上面3次UART DMA传输的代码改成下面这样子:8 N' V5 \8 _( F, m5 ^0 I! O. X8 g
( ~, D( K  X7 M9 f" D& b
  1. HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)WDVol ,sizeof(WDVol));' J2 Y. D; S+ o) B0 ^3 q5 F

  2. 2 E* T  F8 i' S( G% P
  3. HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)InVol ,sizeof(InVol));- k; h: Q- f3 n  r

  4. " F" Q) ~6 U! `. e& [# X
  5.   HAL_UART_Transmit_DMA(&hlpuart1, (uint8_t *)BatVol ,sizeof(BatVol))
复制代码
, e: z* y6 G( m* h
这时输出结果会变成下面的情形,总是只能看到一个结果的输出,即第一次启动的DMA传输结果。3 Y: s# M* s0 Q1 j

1 [0 u" d* x" v% [- E' f
  f1 }2 @7 }; G" h

: r2 _+ l  T9 R- F1 v如果想省事点,直接在相邻2次DMA传输间加上合适延时也行。我这里根据DMA传输完成事件来决定执行下一次发送。在DMA传输完成中断里设置Completed变量为非0值表示当前一轮DMA传输完成。
% V8 N! K* z) A0 o$ o4 j8 T, R% _- _* q4 d* A$ L
4、对于那些在中断和主程序里都会被访问的变量,记得将它们冠以volatile。
: Z6 c% h9 J8 ?. H7 l  ~9 ?0 ^+ b
9 e6 u# Y3 u3 y' q( A( {) r! t下图的三路波形是我调试时辅助使用的。
" ?, }- U( P# u
5 \. L. [# K& k* \7 \- v- Q第一路表示计数器的计数变化,显然是单向向上计数模式。
4 @/ X$ l2 P$ I1 r! X& b. _) A* {3 m; e! a- d; o0 P8 {
第二路是TIMER1通道1的PWM输出波形。5 U2 n$ P. U6 R8 c
8 }; A  k( u6 B0 Q
第三路是我每次基于DMA实现UART发送时拉高拉低的波形。平常管脚电平为高,在实现DMA传输过程中拉低。: t3 P& a( u5 U3 Z5 z
; q! r; n  a  F1 S" m" ?, r
微信图片_20240118185918.png
' C, D, `% k) P# o$ z6 I) K* o
+ G0 k  E  Z; U5 N4 e' r. k
如有侵权请联系删除
: D' \* r. x5 B2 d9 M1 Z9 T* m3 A转载自: 茶话MCU
! a1 M$ e% y1 n; l) a) O* z
5 `( \+ {% j/ F6 M1 G

7 s1 B$ d" s6 V( f& u8 |

4 k/ _+ J% B7 c+ g4 D9 n
微信图片_20240118185921.png
收藏 评论0 发布时间:2024-1-18 19:00

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版