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

基于STM32CubeMX的DS18B20温度传感器经验分享

[复制链接]
攻城狮Melo 发布时间:2023-7-1 18:38
1.DS18B20简介& p2 D4 P: I( y0 A/ `/ m
DS18B20是由DALLAS半导体公司推出的一种单总线接口的温度传感器,与传统的热敏电阻等测温元件相比,它是一种新型的体积小、用电压宽、与微处理器接口简单的数字化温度传感器。DS18B20的内部结构如下图示2 ]+ c$ Q# W  V9 C( l% Z% c- \

1 K, ]. d  R! q& h- k' C 微信图片_20230701183641.png 5 t6 e3 Z% P/ a2 S* B

- N' _2 O, ?8 K1 S7 V% hROM中的64位序列号是出厂前就被光刻好的,可以看做是DS18B20的地址序列号。64位光刻ROM的排列是:8位产品类型标号+48位DS18B20序列号+8位循环冗余校验码。光刻ROM 的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20
! m0 C$ I' D8 j9 S0 D
$ y# n; u# \9 s: wDS18B20的内部存储器(9个字节)包括一个高速暂存器RAM和一个EEPROM,EEPROM里存放高温和低温触发器和配置寄存器,存储器详细组成见下图:7 P5 P, Q) ~4 W& ~+ s

9 q% z0 \. t' A6 S5 m
微信图片_20230701183638.png
. K8 h/ f$ T& ^6 d, k9 b, r; t4 J
+ F0 `9 A: U$ X1 b配置寄存器是配置不同的位数来确定温度和数字的转化,其结构下图示:低五位都是1,TM是测试模式位(设置工作模式或测试模式,默认为0即工作模式),R1和R0用来设置精度,可设9~12位精度,对应的温度分辨率为0.5, 0.25, 0.125, 0.0625℃# l  V* j: o8 s7 N2 D7 e, [

) t0 J, _8 G0 f9 Y: Q# e3 w
微信图片_20230701183635.png
7 v8 {; O/ i) ?6 {# ^8 I0 h0 T
9 j: b9 b: l$ ~" E5 B
所有的单总线器件都要求采样严格的信号时序,以保证设局的完整性。DS18B20的时序有:初始化时序、写(0和1)时序、读(0和1)时序。DS18B20发送所有的命令和数据都是字节的低位在前,下面介绍这几个信号的时序:4 p, D3 D1 x6 \3 _' J" A) [9 C/ @3 L
⏩ 初始化时序( I! g2 b$ d' G( g, H; b' {
内置闪存模块可以在通用地址空间直接寻址,任何32位数据的读操作都能访问闪存模块的内容并得到相应的数据。, v) ~, i% R) M: ~
4 T/ E# V9 N& w- l0 A
微信图片_20230701183632.png
5 v" r. L* c  `7 D8 H3 M1 O

0 b6 T' J2 s( |; G3 M# \⏩ 写时序1 R" b2 Y1 M- ^- X
写时序包括写0和写1时序。所有写时序至少需要60us,并且在2次独立的写时序之间至少需要1us的恢复时间,两种写时序均起始于主机拉低总线。写1时序,主机输出低电平,延时2us,然后释放总线,延时60us;写0时序,主机输出低电平,延时60us,然后释放总线,延时2us。写时序图如下
) V- g: S7 E) z) G, S7 H+ @3 Q  f! ^3 r" S
微信图片_20230701183629.png 2 M& a6 |" y1 C+ Y, N
; W/ [7 O5 j; F, O) Y: X
⏩ 读时序
# c1 |- ]" M+ \* s- L单总线器件仅在主机发出读时序时,才向主机传输数据,所以在主机发出读数据命令后,必须马上产生读时序,以便从机能够传输数据。所有读时序至少需要60us,且在2次独立的读时序之间至少需要1us的恢复时间。每个读时序都由主机发起,至少拉低总线1us,主机在读时序器件必须释放总线,并且在时序起始后的15us之内采样总线状态。典型的读时序过程为,主机输出低电平延时2us,然后主机转入输入模式延时12us,然后读取单总线当前的电平,然后延时50us
4 M/ x$ u! d9 ?* F% c7 g3 S+ h, Z2 u
微信图片_20230701183626.png + z: _4 g7 }" g* u$ k9 Y% a9 K

; e" V- o% O4 \2 v8 G2 MDS18B20的典型温度读取过程:复位 --> 发SKIP ROM命令(0XCC) --> 发开始转换命令(0X44) --> 延时 --> 复位 --> 发SKIP ROM命令(0XCC) --> 发读存储器命令(0XBE) --> 连续读出两个字节数据(即温度) --> 结束
5 @2 F1 k# s- L/ e) j
/ q, i+ A- Y9 r! e5 K( d6 v9 e2.硬件设计/ @. r8 Q0 q; P" w8 S' `; C
D1指示灯用来提示系统运行状态,DS18B20温度传感器用来检测环境温度,串口1用来打印温度值
; z& G. M8 m! ^: ]4 \指示灯D1
, a% c; \+ C2 g: i& B- QUSART1串口
) f! b0 l2 c% T- W/ d7 f( ?* pDS18B203 T$ X: b) b2 ]7 ^4 C; l
TIM7(提供us延时)
% T- N$ H4 f0 s6 m0 n# V% o) {
9 V% e& F9 ~) A! m. k, c: e+ \- v) H
微信图片_20230701183622.png 7 ?" q: {$ x+ T6 I( p- s. K
7 U7 N! ~+ m7 O& u  |/ ^- I
3.软件设计
' A$ V& F9 t# l3.1 STM32CubeMX设置  f2 d. \8 c3 }5 Z1 i& x: v" C
➡️ RCC设置外接HSE,时钟设置为72M! ]  Y* i- x3 b$ @0 X
➡️ PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平4 Q- v/ [1 |0 E# M
➡️ USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位1 T8 K6 c& Q3 e6 m" U
➡️ PG11设置为GPIO推挽输出模式、上拉、高速
. U1 `# g/ l3 S, P0 c4 W2 v2 [➡️ 激活TIM7,预分频因子设为72-1,向上计数,自动重载值为65535;因此计数器CNT_CLK = 1MHz,计数器周期为1us
" A! ~! l4 G! P4 t
3 n* w' Y8 i/ X* G! X
微信图片_20230701183619.png 2 b( x! B7 g. z6 v1 W$ ^. n. L
) G( m8 o! X- g& F
➡️输入工程名,选择路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码
+ U, {" r. J; ~( p* B
) B$ c3 X/ r' e3 H% t1 @
3.2 MDK-ARM软件编程
( |7 g0 N4 }4 Z➡️ 在tim.c文件下实现微秒延时(us)函数
, ~6 A) e; R: N8 _# r* l$ d
  1. void delay_us(uint16_t us){% Z* c3 T& L, N+ z( g" p
  2.   uint16_t differ = 0xffff-us-5;
    / F- J9 _  M) w; J, K
  3.   //设定TIM7计数器起始值                                / G! Q2 Y, t: t8 e: C0 b/ R
  4.   __HAL_TIM_SET_COUNTER(&htim7,differ);       
    + s2 t% D5 x0 Y7 ~; c  G2 a3 V4 g
  5.   //启动定时器: w( w9 D* C: u* Q
  6.   HAL_TIM_Base_Start(&htim7);                        5 g* K0 d; Y; g' t" X( P9 n
  7.        
    " y- c1 X- `. O) d+ w
  8.   while(differ < 0xffff-5){   //判断% X7 L0 o" x4 M" C: j0 N
  9.     //查询计数器的计数值6 m* S+ L5 [* ?( a7 q7 K3 l
  10.     differ = __HAL_TIM_GET_COUNTER(&htim7);               
    9 {/ ~' c2 h& Z5 D' q" T1 @% S
  11.   }1 F/ L  d6 c1 w
  12.   HAL_TIM_Base_Stop(&htim7);9 ?1 S( c9 B0 C# S2 _$ ~2 }& M
  13. }
复制代码

+ k! {) m$ y# Z0 r0 A' m➡️ 创建按键驱动文件ds18b20.c 和相关头文件ds18b20.h9 O( S+ X) _! T1 G$ `1 v
  1. void DS18B20_IO_IN(void){: R; ^' p2 E0 ^; }0 S
  2.   GPIO_InitTypeDef GPIO_InitStructure;
    4 W8 P8 B) r- K4 M  t8 ^/ g! [: ^
  3.   GPIO_InitStructure.Pin = GPIO_PIN_11;! J. G) T, `: F0 Z5 u
  4.   GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
    ; w+ i9 W  h. D) m8 f. a
  5.   HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);1 s/ f5 R. D( t: g
  6. }" a3 U4 ]* Y; \/ t
  7. + O8 u" e* A3 P) E
  8. void DS18B20_IO_OUT(void){( Z4 I" M, D1 s+ n
  9.   GPIO_InitTypeDef GPIO_InitStructure;, B/ g. H  ]8 C
  10.   GPIO_InitStructure.Pin = GPIO_PIN_11;
    ; }- ?% S, m( j
  11.   GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    9 T% |3 J0 {' C" ~- T# p* |2 {
  12.   GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
    ' M" b! C  q2 R7 f8 G" i1 D4 G
  13.   HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);' G+ v# L" c, H& Q* G% T9 a
  14. }; \% T% v: {0 v
  15. 4 [2 v2 k4 g3 K1 v# @
  16. void DS18B20_Rst(void){. o5 |/ x7 y  b3 [, T  r" ?
  17.   DS18B20_IO_OUT();/ O$ [3 U6 w. T6 V6 ?6 L& b) `9 E
  18.   DS18B20_DQ_OUT_LOW;
    # N) _- a0 x4 ?8 X( c4 D  X
  19.   delay_us(750);
    # ^1 a5 N; \' A4 y4 q  I6 ~
  20.   DS18B20_DQ_OUT_HIGH;1 \/ V0 G7 \! a2 t
  21.   delay_us(15);
    & ]9 W, d# l2 h4 _  a! _: u
  22. }
    + ]( @3 ^; T. @  U2 V
  23.         , y/ V# D2 o0 q- Y& }
  24. uint8_t DS18B20_Check(void){
    / \" p# {  k) k
  25.   uint8_t retry = 0;
    . c8 a+ k0 D4 v4 J5 Z# t  i% h. |
  26.   DS18B20_IO_IN();
    5 ?. D) O( c3 f7 Z% X. F! C7 s
  27.   while(DS18B20_DQ_IN && retry < 200){6 `0 L9 x# g* f. ]7 m
  28.     retry++;
    , j- F+ Z/ B. N( M+ A$ C' P* n' B
  29.     delay_us(1);
    % K7 S' {% A1 a1 W+ }1 B9 q
  30.   }
    + Q! j; ]- ]+ {' Q, Q; c- k
  31.         + U9 T! a( Q! m; o8 k3 M
  32.   if(retry >= 200)
    ! S. u0 j$ b* Q) E
  33.     return 1;
    3 D3 M! k* G! G, d4 T
  34.   else
    6 |9 H: W, z/ f; R/ b
  35.     retry = 0;
    8 _; J; G& J- g3 B! N# ~( T
  36.         9 p) X! K0 Z6 l: [0 b
  37.   while(!DS18B20_DQ_IN && retry < 240){
    # ]+ |( @$ }( J0 f/ ?1 q
  38.     retry++;0 w4 p4 g( @# `* f' w% j
  39.     delay_us(1);
    ! |7 B- {8 [" p8 g# E  o0 c* b
  40.   }
    5 C9 q8 }2 e- B: Z* B; A
  41.           `" s* Q- j0 N3 B# N* V& O
  42.   if(retry >= 240)
    + B& A) b3 N% R- `. H4 i
  43.     return 1;
    " y- t3 J0 d% U2 ?& ^
  44.        
    4 g1 y6 k: a* [( g! T+ }/ i- e3 ^3 ]9 y
  45.   return 0;. n/ R3 q" w5 t5 M7 G% z
  46. }; I( n) o% U: Q+ }9 R- K

  47. 3 p- j" W) [  l, ?, W" i7 ~7 x
  48. uint8_t DS18B20_Read_Bit(void){
    - H; [+ K( F2 ~, M" `
  49.   uint8_t data;9 n& n4 O5 u7 ]1 h2 X. Y
  50.   DS18B20_IO_OUT();5 ~1 P& C* j: I* Q6 z$ |- k3 E
  51.   DS18B20_DQ_OUT_LOW;
    ) `' M% I7 f4 r! D: e! W
  52.   delay_us(2);
    4 I! E- W% J+ w4 Z$ @
  53.   DS18B20_DQ_OUT_HIGH;
    / i, Z+ x8 F3 w/ C1 O' Q7 K# b
  54.   DS18B20_IO_IN();* s2 _/ K2 f4 j9 A7 y
  55.   delay_us(12);
    1 G1 Z/ D) d& L$ Z+ l" m: K. [( \
  56.         0 f- ~* E' ]% b/ f: s# E9 ]
  57.   if(DS18B20_DQ_IN)2 W# s& P- q8 [# o) E
  58.     data = 1;
    : q) m. J( i' y4 B! u# R3 M: e
  59.   else- G+ N$ u4 P7 X: C& V
  60.     data = 0;5 p- {- i, m' c/ [
  61.         5 s: F7 K, `7 l
  62.   delay_us(50);
    5 o8 O& s  u, W' c; g+ R4 C
  63.   return data;8 Q5 [4 o1 T! S% ?8 F
  64. }
    2 K4 N% _' L; ], _* P" U5 J

  65. 1 z$ |. I8 T% @' A. \3 `+ @
  66. uint8_t DS18B20_Read_Byte(void){
    + s7 o& d, V8 S8 P
  67.   uint8_t i,j,data;$ E' o6 g9 a. a) V+ S
  68.   data = 0;6 M  v. X& f" T
  69.   for(i=1;i<=8;i++){
    ; v$ v. K' V6 }2 H6 ^# q% I3 `
  70.     j = DS18B20_Read_Bit();
    ! L4 n$ l4 l+ t( a
  71.     data = (j<<7)|(data>>1);
    ; c  {' `7 K1 d
  72.   }4 t3 F2 s8 W: e) U6 V
  73.   return data;' h& B- z2 |0 h& x! W
  74. }. E4 D1 e+ `2 i, g* l0 M

  75. ( j) T8 L+ d1 w
  76. void DS18B20_Write_Byte(uint8_t data){
    " ^5 Y( E* ^# o$ V5 v  w
  77.   uint8_t j;5 l* L& _# [8 p  _7 G
  78.   uint8_t testb;" F" u0 L! a- d3 t% A
  79.   DS18B20_IO_OUT();
    7 X4 t1 A2 ], {' ]6 ]: b
  80.   for(j=1;j<=8;j++){
    + j% D/ l, k: J  f( v/ ], F
  81.     testb=data&0x01;/ _# S4 q8 a0 b2 `- T. {
  82.     data=data>>1;
    6 P3 X2 V) B, ~  {! x: Y8 v% `
  83.     if(testb){
    " A5 k8 [, w+ A# z* o& H$ z
  84.       DS18B20_DQ_OUT_LOW;
    & {9 h1 J$ v9 Q6 f, z, c. L
  85.       delay_us(2);4 h* W, t" B8 m# Q# K" b
  86.       DS18B20_DQ_OUT_HIGH;* h% X$ h, d" l! I
  87.       delay_us(60);
    " {. x) {* i, ]' c) @
  88.     }else{  \8 K# F/ n9 K4 v- Q6 X
  89.       DS18B20_DQ_OUT_LOW;
    & q" F# D7 k$ t
  90.       delay_us(60);
    ) U% r5 s. F) m
  91.       DS18B20_DQ_OUT_HIGH;
    , d: Z5 }3 ?7 x$ N( d
  92.       delay_us(2);
      ?( w! e' x, H
  93.     }: x1 _, L* d5 k- V$ t$ e( ~: \" s
  94.   }
    # R$ h0 b* t7 w0 Q$ F* u+ H
  95. }
    ( B8 w) a- x5 |9 k9 `! T5 I
  96. 9 |2 W+ M8 {7 A$ M
  97. void DS18B20_Start(void){& m% s! g" ^+ ]+ P. D# J4 `
  98.   DS18B20_Rst();
    ; a7 P* q7 o+ H2 K; e" E( L6 G
  99.   DS18B20_Check();1 ?' E2 |6 U; l9 N
  100.   DS18B20_Write_Byte(0xcc);
    * L3 t- J0 C9 }' U
  101.   DS18B20_Write_Byte(0x44);
    8 t4 }1 @1 Y& y5 t2 u
  102. }
    + V0 y7 o/ h" Z9 {0 C

  103. & z1 P' m- K! Z) J7 A9 c
  104. uint8_t DS18B20_Init(void){; @* w. _3 N- }
  105.   GPIO_InitTypeDef GPIO_InitStructure;& r# A1 E" U$ a1 f1 d
  106.   GPIO_InitStructure.Pin = GPIO_PIN_11;% l' V9 V: ~& B) a9 E- B: ~
  107.   GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    ; ~1 M2 O* z7 H$ _
  108.   GPIO_InitStructure.Pull = GPIO_PULLUP;
    ) [8 G5 N3 Q, c2 a7 W' b
  109.   GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;$ G, M2 U- D# g$ o) H1 `
  110.   HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);8 F) g0 o# x/ @/ K1 u
  111.        
    4 ~1 e* g+ h# q$ f
  112.   DS18B20_Rst();
    ( J  S  F. a3 E9 p# a3 V
  113.   return DS18B20_Check();$ p' o1 R* J$ Q6 @! W7 D% x0 p3 H
  114. }& N" {9 m& c5 e! {

  115. 2 z' C! J. w: h" r" I# R
  116. short DS18B20_Get_Temperature(void){
    ; O$ \* x2 \# X5 X, T, T. k
  117.   uint8_t temp;- W! ^" f; @* {8 j3 @5 m3 W
  118.   uint8_t TL,TH;
    2 b" Z9 n# u8 \/ b; C& h! I: r
  119.   short temperature;% D' |3 f+ Q  V$ x/ w$ a- s- H
  120.        
    ) `; b" L, P* x+ \7 r9 P* H3 Z2 r
  121.   DS18B20_Start();
    7 O- ?  x% k+ f& d/ A" o" b$ d0 }
  122.   DS18B20_Rst();
    ) z0 {3 w8 W8 ~
  123.   DS18B20_Check();% y0 o4 G! Z. W: `9 L# G+ L
  124.   DS18B20_Write_Byte(0xcc);6 }. ?; v' x) D
  125.   DS18B20_Write_Byte(0xbe);, ]2 Y# B0 R& j7 q& a
  126.   TL = DS18B20_Read_Byte();7 y" i( d( v7 s% T
  127.   TH = DS18B20_Read_Byte();# J+ b! W# P- F% U3 s* v
  128.         * Q; ^5 h- D5 B  p# U* Y
  129.   if(TH>7){
    , j9 C7 Y" r* O( c
  130.     TH = ~TH;
    * L1 n' f4 P6 M+ h
  131.     TL = ~TL;
    2 r( _: a! G/ j1 f+ [
  132.     temp = 0;7 H+ _* w5 a# ?- f3 Y
  133.   }else8 L4 _& \5 V( s, n- v" h
  134.     temp = 1;
    $ _& P/ Z! t' R$ ?: p  O- ^
  135.         4 q! H0 L( o: x" q8 I  u
  136.   temperature = TH;( N' I: }/ R2 |
  137.   temperature <<= 8;: d. R+ M$ ^; m- S
  138.   temperature += TL;1 b# s2 v; C9 I5 f9 p, Q% P, U; K
  139.   temperature = (float)temperature*0.625;
    + C: U6 U; [8 X: t7 c9 j4 z
  140.   if(temperature)9 d, ]+ |7 ?2 Q- Y5 `8 x2 B# c
  141.     return temperature;
    7 G9 W1 w! g; K" `! j! |: G
  142.   else
    ' F& V$ h$ E- j
  143.     return -temperature;5 D% |' g- y& m# [6 p! V
  144. }
复制代码
2 C! B6 n/ K" A1 r1 G+ o
➡️ 在main.c文件下编写ds18b20测试代码( ~1 o  Y) F* c/ k6 r- L0 |$ o
  1. int main(void){
    1 t; q, m- v0 v# ^3 c/ r& W
  2.   float temperature;
    9 t/ C; G/ y% f2 A
  3.   HAL_Init();4 e' ^" \6 D2 W" {2 |& b+ b, Z
  4.   SystemClock_Config();
    7 [7 d, m) Z) j9 N
  5.   MX_GPIO_Init();
    . ]  s6 U! f9 e3 Z% X
  6.   MX_TIM7_Init();
    * \& ]) X& {, e2 v1 n, P, s. H
  7.   MX_USART1_UART_Init();
    # C1 S5 `7 w& `; ^$ O# r& S
  8.   /* USER CODE BEGIN 2 */( n, m; k0 O2 c* z
  9.   while(DS18B20_Init()){' P1 T# V& [# Z, T5 y
  10.     printf("DS18B20 checked failed!!!\r\n");
    5 G9 n* `+ N8 d5 L
  11.     HAL_Delay(500);
    3 J3 p/ Q. V0 x$ w; X7 j4 K( ?7 V
  12.   }' u7 a  K$ M2 S% \
  13.   printf("DS18B20 checked success!!!\r\n");
    6 x1 p' o+ J+ H+ ?7 J: [& t
  14.   /* USER CODE END 2 */
      L( p9 G+ l. ^8 S) D! `* x: p
  15.   while (1){7 h" W5 m) a3 C0 ]9 C; S7 v
  16.     temperature = DS18B20_Get_Temperature();. C: C% U$ M: _" q; K4 |
  17.     if(temperature < 0)5 Q. N8 I# R1 Y; U0 U
  18.       printf("temperature = -%.2f degree\r\n",temperature/10);% j+ R2 b6 \% U: u
  19.     else
    6 J9 Q4 Y4 U0 \5 |# w. T1 c
  20.       printf("temperature = %.2f degree\r\n",temperature/10);3 d* S6 D% {) f) U, ~+ G9 I
  21.                 1 d7 V" R" ]% ~, F1 e
  22.     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);6 _& ?9 c# N. S3 {/ j" p
  23.     HAL_Delay(200);
    0 r0 H' y6 w( ]: J: u) `; y
  24.   }
    6 B5 n2 e8 w3 Q& i4 y7 H
  25. }
复制代码

: s2 }4 p2 `/ t$ ]0 D( a' P4.下载验证3 E- f! J: Y1 S  a; N7 W
编译无误下载到开发板后,可以看到D1指示灯不断闪烁,串口不断打印出当前温度值
6 Q, S9 ^# c2 E2 ?
4 R' n& r$ ~) N: _
7 |0 Q* `/ y9 m- @8 ~4 K 微信图片_20230701183615.png * \& M/ {) t: y: m

" l2 W! E& w- K# W1 U# M转载自: 嵌入式攻城狮
, e5 B4 J' m( [% s: I& t如有侵权请联系删除
# Q4 s  u3 [! u! K3 l3 _; n
0 d0 R' {9 t0 Z; c( F( D
8 l6 v! L9 G3 s5 A, {( A
赞 收藏 评论0 发布时间:2023-7-1 18:38

举报

0个回答

所属标签

相似技术帖

官网相关资源

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