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

stm32f103之滴答定时器

[复制链接]
STMCU小助手 发布时间:2023-3-8 13:00
滴答定时器:
  @5 W! N5 P$ W8 @: l  |        定时器的本质就是计数器。我们设置一个定值,然后计数器开始计数,从我们给的定值开始往下一直数,当数到0时,就做相应的动作(也可以不做什么,当把它用作延时计时的时候)。$ O  X9 W: Z7 l  \

6 x/ d, e& \3 z/ z0 s& k3 y* X& R滴答定时器systick是一个内核外设(即:内核自带的)
/ {8 Z, |* q. `& z; ~
% k% y3 E, S3 M: C$ J
        Systick是一个24bit的系统定时器(stm32F407的寄存器名字与位数都与f103一样,但是有些芯片定时器位数不同),向下计数(从定值开始数到0),当计数到0时,在下一个时钟边沿,会重复计数。所以如果我们用完定时器后,不再继续使用它时,记得要将定时器关掉,否则它就一直在重复计数,增加了功耗。% [' s4 M) u0 X: _3 a

/ \* ]0 Q. U3 j% CSystick的作用

4 J2 M" U2 o. K: V0 M+ o* ~% \1.产生一个精准的定时
% f# {9 H7 A$ h6 T. K2.FreeRTOS时基由Systick提供- R& C5 z# @) J2 `# J* t
      
3 b4 c& t: k* _在说定时器前,我们先来看一看如何计数?
@S}}FXGPMXJCVME%JJGH.png : `( G5 v; x: W* D. E$ D  ]) p
配置滴答定时器:

# L/ V, u. f  B$ x7 U) h% |* U( S+ W2 }" I3 D% c9 O
2e4242cbd0334a8dbcc333256a6d9fcb.png 0 p+ m9 Q8 l3 d! N- r) q7 t; w
. J# J$ h+ p, M0 d+ {
        红框中就是滴答定时器的时钟,我们可以看到分频系数为8,所以滴答定时器的频率为:72M/8 = 9Mhz( m1 D0 C) e8 ^, A& {3 ~; d- v+ A

, A0 B4 [- Y. l3 d$ Y* n, g配置滴答定时器我们需要下面几个寄存器:
6 T% X' l% d- O. h- S/ N* G
( W- y5 u7 }' D# b" r0 g% c3 p' _' K) n& n
fb7ea8d208f14b14975bb8c2c2b8daac.png
; q$ E9 j' V  G
' c$ D8 A1 |" n5 m9 { 注意:第16位,是定时完成标志位,每当计数到0时,该标志位就会置1。! [% n! ?; G0 i9 q/ b4 }8 N& U) T+ c

7 o9 \0 F, {5 {2 Q; |, D
439efd5325344681aa687218ae27eeac.png & ^4 G+ U. s) ]' n
# k4 S, s' z0 s* q
注意:由于定时器是24位的,所以给定时器装载的定值是有一个范围的,红框中就是范围,范围为0x000001 ~ 0xFFFFFF   
$ s. a. c9 S" T, |) @
- Z; y; U, Y( x: n) _+ U5 p即:1~     也就是:1 ~ 16,777,215,如果填入的定值不是在0x000001 ~ 0xFFFFFF这个范围,则无法定时计数。" c6 P1 I* I" f5 R5 {3 |
% q, a6 K% x) u
d1b8265cf617451caef6d6a879b01593.png ' Z0 {' c8 k! ^9 L

2 D8 U3 w( [9 V4 o& {* d编程
; Q; g2 t0 q2 a4 a产生Nms定时编程步骤:
8 V4 g" [9 c- O6 D* Y! _+ E( h        1》配置时钟源---AHB8分频,并且关闭定时器-----初始化(while(1)之前)3 z! I5 A/ Z/ y1 U
        2》设置计数值---N*9000/ C1 }6 i' i- h# X7 `$ o; l/ P
        3》清除当前值寄存器----注意:清除当前值寄存器,STK_CTRL寄存器的第16位会自动清0
; S4 J% C9 Y: X+ W& h) R' m/ P6 D2 y8 R        4》打开定时器: `" B* [6 A5 r
        5》等待定时器结束
3 o: B* \5 q$ B) z' \/ f  P8 [        6》关闭定时器, h# |# E2 A5 s: [. u: @
% P( a3 k+ J7 m% G
代码:

: V" ]9 d  D0 b) ^
  1. uint32_t fu_ms;  // 1ms需要计的次数0 I1 S. r& Z" o( l4 _3 b
  2. uint32_t fu_us;  // 1us需要计的次数
    % r% k% N% s$ E! G  L4 [
  3. ) l; O5 r7 x8 o& J# ^9 W
  4. $ v, F) p! V/ [& {! `
  5. void Systick_Config(uint32_t Sysclk)        //Sysclk就是系统时钟频率72Mhz,但是这里用72表示72Mhz( l; A5 \9 N* [0 C
  6. {# N) Q* |/ K; w. ^5 O, Y& U* I
  7.     // 1》配置时钟源---AHB8分频,并且关闭定时器-----初始化(while(1)之前)
    # F' w* j, m3 R' e- C# F. P+ Z
  8.     SysTick->CTRL  &=~0x05;        //这里关闭定时器的原因是,有可能之前没有关闭,所以一开始先将其关闭,再进行配置, Q9 k# J$ H) n- m# p3 ]  f5 O, l. d
  9. 8 S2 N* V, b: v5 r
  10.     fu_us  =Sysclk/8;                // 72/8 = 9,即:表示9Mhz$ y* ~' h. g1 B
  11.     fu_ms  =fu_us*1000;        //9*1000 = 9000,由前面知道,在9Mhz下,计数9000次为1ms
    " O3 l/ N4 Y$ T& u$ G
  12. }' v/ d, O, E" ~: _) ^( p
  13. % `1 J1 ~9 D8 P1 V/ E& a$ a$ F
  14. ! p! H* D& v+ N5 I- E
  15. // 定时Nms程序,ms级延时" c1 d4 w$ _3 D1 w% \
  16. void Systick_NmsDelay(uint32_t Nms)
    0 d; t. ~: {8 I6 S9 q# A% x
  17. {
    & [" I2 }8 [- |# |
  18.     uint32_t temp;
    + l( C( k, E3 v+ x2 j
  19.     // 2》设置计数值---N*9000
    / j% s& @! o' I2 a7 N6 K- W2 C
  20.     SysTick->LOAD =Nms * fu_ms;: e4 J4 Z# x' o" ~7 L/ D5 d) S

  21. 2 z9 N4 V' ]# v% w' I% ~
  22.     // 3》清除当前值寄存器----因为清除当前值寄存器,STK_CTRL的第16位(定时完成标志位)就会自动清0
    0 @9 D7 b  w; }/ G
  23.     SysTick->VAL =0;        //清除标志位( Z' t# o/ O: r' H! f

  24. & ^7 t( ], s% @0 Y. y
  25.     // 4》打开定时器/ n3 t. v4 k7 k" _8 _
  26.     SysTick->CTRL |=0x01;+ Q; [8 ^  P" R. Y4 _# v

  27. + t1 e. P+ U+ p5 `/ z0 j
  28.     // 5》等待定时器结束9 p7 i9 L5 z$ W: M
  29.     do{2 `" d+ v% W' r& D
  30.         temp=SysTick->CTRL;        
    & ^  M/ F8 j( P4 F4 @& y
  31.     }while(!(temp&(1<<16)));        //判断CTRL寄存器第16位是否为1。如果为1,则说明计数数到0了,此时计数完成
    * ~# ^' o$ W$ E) [9 i5 y
  32. / S% m* D* f5 g: x1 M$ v& i
  33.     // 6》关闭定时器
    4 K5 n4 x5 C+ K# H' n- K. {: U
  34.     SysTick->CTRL &=~0x01;. H. S7 I4 W, _: l/ g1 q
  35. }
    . c9 U1 D, Q( D" e% r& ^$ F
  36. 6 Y: D- K7 n& e" W$ z
复制代码

  W$ ^; Y, P. l7 L9 p解析:. P/ f" X! H) |8 ]6 [+ G% C
1.我们先来看程序,定时器程序为什么被分成  Systick_Config(uint32_t Sysclk)  、Systick_NmsDelay(uint32_t Nms)两部分来写?
% _/ R7 R' J- F3 Z, t1 P        因为,Systick_Config(uint32_t Sysclk) 中的配置,在整个程序中只需要被初始化一次就行了,而Systick_NmsDelay(uint32_t Nms)是延时函数,它会被多次使用。如果将Systick_Config(uint32_t Sysclk)与Systick_NmsDelay(uint32_t Nms)写在一起的话,那么多次调用该函数时,原本只需要被初始化一次的语句,就会被多次执行,浪费CPU资源。
0 ]: T6 G& `' F

8 K9 p1 Y+ P, c5 R4 v& G" K2.为什么程序中的这部分需要用do.....while而不用while()?) n! }' R+ v& m' X
5 s' _! ]9 S: N+ `$ v: d6 g+ t5 A
8df6add7dbcb4ca6b71a02a7ec75dea9.png 6 W5 M$ A5 D. h$ o

5 P: S5 k8 i  ]        这里需要用do....while而不用while,是因为需要先执行temp = SysTick->CTRL; 将SysTick->CTRL寄存器中的值赋值给变量temp,然后再对temp进行真假判断,即:!(temp&(1<<16))。temp&(1<<16)为读取SysTick->CTRL中的第16位是1还是0,如果第16位是1,则为真,但是由于非 "!" 的存在,所以 ! (temp & (1<<16))就为假,所以此时do.....while循环不再循环下去。如果第16位是0,则为假,但是由于非 "!" 的存在,所以 ! (temp & (1<<16))为真,所以此时do.....while循环将继续循环下去。等到第16位变为1,也就是定时完成标志位置1时,如上所述,while循环将不再循环下去,此时计数器计数完成。. |- A. o' A& u, ^

4 u3 f, {8 j1 t$ h' ?2 G

3 ]5 c* ?6 r/ L# H+ v" q3.  由上面知滴答定时器的计数器是24位的,其计数范围为 0x000001 ~ 0xFFFFFF ,即:1 ~ 16,777,215,那么如果我需要计的数超过了这个范围呢?我该怎么办?
8 \" o# `* X4 F2 [
4 ~5 \$ s% C4 \* |" n+ o0 O) S        由前面知,计数9000下,延时1ms。所以,16,777,215可以延时1864ms,即:  =  1864 。也就是说,在9Mhz频率下,将计数器计满,可以实现延时1864ms。
  ]( x% m: C; Y
+ }* U/ b: B6 g# V3 {. C" Z( N& G  P
        的确,如果我想要延时2000ms,那么由于超过计数器的计数范围,那么滴答定时器就不会正常工作了。
, `4 s  r/ ~9 A6 l; j! a# H$ M
' G. O6 b! k  F) u

! Y, t: q' j, }所以,我们改下一下程序:8 g$ X4 `+ ?5 Q( u6 H
  1. // 定时Nms程序* h6 z% z- w, e0 K+ ~3 s
  2. void Systick_NmsDelay(uint32_t Nms)
    * x0 ]1 ]9 S% O: ?# `7 e" x1 ^" p2 [
  3. {$ R4 c" ^: @* W$ A
  4.     uint8_t  systick_flag=0;  s' v6 f# o; S- q3 {, p
  5.     uint32_t temp;
    " o/ w6 Q. F; J5 [  G$ S/ X
  6. " N- Q; Y4 J  a: R

  7. 1 E9 [, e3 |- M0 T- B
  8.     while(0==systick_flag){- I# P& A1 G& W- J% p/ W
  9. ; P6 e' Q" q- \! L) Y

  10. 7 T) i  c# Z/ N
  11.         if(Nms>1864){
      g% q/ C8 ^( O" p7 c( o; k$ R% J
  12.             SysTick->LOAD =1864 * fu_ms;
    $ l  s) }+ I# t2 W8 k0 ?/ u/ T1 J$ m
  13.             Nms =Nms -1864;8 v/ }& `* r5 J" c* v- q. \
  14.         }else{
    : i9 J7 J1 V2 z4 q* p* B
  15.             // 2》设置计数值---N*9000) D4 n( i. K' r) N2 W! Z* I
  16.             SysTick->LOAD =Nms * fu_ms;
    9 T! @2 f+ J9 b) x9 W2 J% \
  17.             systick_flag=1;2 }0 q9 }; O0 z1 j+ j) w
  18.          }
    - V: p/ _1 m! n/ ?

  19. + Y2 n$ D+ }! U

  20. ' T: ]" o2 s1 N  \( }, l( E3 y
  21.         // 3》清除当前值寄存器----因为清除当前值寄存器,STK_CTRL的第16位会清0
      X" q$ n1 ^) A* x" |$ k
  22.         SysTick->VAL =0;. y! [) X- P% x7 M, z$ @

  23. % k* u! w2 c  D" ~+ |
  24.         // 4》打开定时器
    : S% e& I- a$ O, \# K- Q* ?4 @
  25.         SysTick->CTRL |=0x01;
    ! z) i6 B2 E# }( |* ~' X

  26. # d7 u/ W0 r3 ?" y) t+ @# U
  27.         // 5》等待定时器结束
    ! j7 Z! M" m! }3 D7 `/ m
  28.         do{
    / }9 ?5 a1 q% Q
  29.             temp=SysTick->CTRL;
    , Z1 w9 I# E9 a0 \) _$ S
  30.         }while(!(temp&(1<<16)));4 b, H; }2 ~5 n& N0 l1 I  Z

  31. & T' X7 _4 n! _1 N3 J
  32.         // 6》关闭定时器1 c6 ?! P+ i# E7 [1 F) t: G& o
  33.         SysTick->CTRL &=~0x01;
    & R2 v0 X' @4 J! }

  34. & ~" d" L$ d$ k) p* Q
  35.      }
    5 K+ B. J* y# {, @( b8 n( v5 t
  36. & n- m2 `/ j! f: R: L4 C  e1 O

  37. ) W3 r2 B6 G$ e" U+ [, P
  38. }6 @  P  l- k5 X$ m' V8 }  E
  39. 1 U3 Y+ V% _  Q1 F
复制代码
6 ^1 E5 s/ B& Y' h+ E1 v
这样的话,就解决了1864问题了。
0 P% h4 k! l( O$ Z# w" m: [3 H& s% ~

% |9 ^6 i! j* ^& Z2 C& w1 c0 d4.us级的延时程序是什么?6 P3 G& y' p, R' u
  1. // 定时Nus程序
    , Q3 E! Z, L+ f1 q* u8 L  Z
  2. void Systick_NusDelay(uint32_t Nus)
    ( }$ c# i# U; d0 t% A+ L9 h
  3. {1 m0 E) e9 O4 f/ l3 c: \4 p
  4.     uint32_t temp;$ a' a% ^2 M$ l' p' {. x
  5.     // 2》设置计数值---N*9" J/ Y% w! H  W" [) ?) P/ r4 f
  6.     SysTick->LOAD =Nus * fu_us;        //us与ms的程序就只有这里改变了& }- Q$ ^  N. I
  7. % Y% h( p! u) i- x* @0 Q
  8.     // 3》清除当前值寄存器----因为清除当前值寄存器,STK_CTRL的第16位会清04 r5 F  ^* {! s
  9.     SysTick->VAL =0;4 k8 O: V" @9 N- W! c% r! J, A) f

  10. ) \; W4 N, O7 o' S; D
  11.     // 4》打开定时器
    / A" K" @% K0 r
  12.     SysTick->CTRL |=0x01;
    . k$ d( ]* l- F$ L; A) b$ K

  13. 6 K/ g" k; t- K
  14.     // 5》等待定时器结束
    * i- a3 d! e6 O: L0 h
  15.     do{% q5 v" h: g$ b( a8 a
  16.         temp=SysTick->CTRL;
    7 S6 o! x' M+ u, p: w6 C* D
  17.     }while(!(temp&(1<<16)));
    $ k) H9 z/ R7 r

  18. / ]: N! K# a, h. Q0 j1 R! a
  19.     // 6》关闭定时器$ O5 w0 }$ ?8 x; I- R
  20.     SysTick->CTRL &=~0x01;
    & q0 G# L1 I! c; F! g  m/ n
  21. }0 x: b, r+ k4 X- I* O0 |7 K5 L
  22. / k9 i" r3 V: R% Z# v$ @5 p$ x, [
复制代码
& E4 W: H, Q  Q  j7 q  @4 T
注意:
, ^+ s$ |" b; j+ p        在FreeRTOS操作系统中,不能使用我们自己设置的Systick来进行延时,因为FreeRTOS时基是由Systick提供(裸机的时基是由晶振提供的)。这是什么意思?
( _4 `" R2 d& R  {
" T+ b% l9 K) `9 c
        FreeRTOS时基是由Systick提供,时基是需要保持不变的,所以Systick寄存器中的值必须是固定的,是不允许被修改的。但是,如果我们在FreeRTOS中用我们手动设置的Systick来进行延时,我们必定会去修改Systick寄存器中的值来得到我们需要的延时。所以,此时如果在FreeRTOS中使用我们手动设置的Systick去进行延时,那么就会卡死。解决办法:使用软件延时,delay()函数来代替Systick延时。代码如下:
& y/ V% Y) f, d' a; T) x+ g) G# p5 s2 i; J6 }( |# B+ [
  1. //初始化延迟函数
    ! n0 _5 O  A+ C% l& Y2 N# j
  2. //SYSTICK的时钟固定为AHB时钟,基础例程里面SYSTICK时钟频率为AHB/8
    4 z4 B# m  y' t; q
  3. //这里为了兼容FreeRTOS,所以将SYSTICK的时钟频率改为AHB的频率!" m6 x$ O0 z+ a+ ^8 J. p7 S
  4. //SYSCLK:系统时钟频率$ B) f3 K$ w# @3 @6 E( L
  5. void delay_init(u8 SYSCLK)/ E& @" a9 _9 F$ c% z! u; c  }
  6. {2 E* I( n% B# N6 Q0 |" G
  7.     u32 reload;8 w8 v- V6 `" ]1 \
  8.      SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
    5 ?6 ~7 T. s) h6 ~
  9.     fac_us=SYSCLK;                            //不论是否使用OS,fac_us都需要使用
    4 X& a; z6 C: a1 r  T) S, Z  C. e
  10.     reload=SYSCLK;                            //每秒钟的计数次数 单位为M       " x0 Z% c1 U" W: z5 ]( B) ~1 V4 Y8 W
  11.     reload*=1000000/configTICK_RATE_HZ;        //根据configTICK_RATE_HZ设定溢出时间
    1 |1 w6 G8 Z" t, i* V* x6 w7 X. E
  12.                                             //reload为24位寄存器,最大值:16777216,在168M下,约合0.0998s左右    " |( A8 B" G$ c  t2 M
  13.     fac_ms=1000/configTICK_RATE_HZ;            //代表OS可以延时的最少单位       3 B& b6 d9 Q  r7 L$ u/ Y  l
  14.     SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//开启SYSTICK中断5 {, M1 @8 N) `
  15.     SysTick->LOAD=reload;                     //每1/configTICK_RATE_HZ断一次    & z' F- Q, ]( A# U
  16.     SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK     . y; W& o$ N8 o
  17. }            
    , T# j3 P: s# m, L+ Z

  18. & }, x  n8 L6 U4 X7 a+ r
  19.                        
    1 X. S) f. G4 W0 y$ c# z

  20. 1 a9 ^/ O4 J5 _; _
  21. //延时nus
    - g; F5 Y" O9 t+ v
  22. //nus:要延时的us数.   
    * K" ~& o! j. C
  23. //nus:0~204522252(最大值即2^32/fac_us@fac_us=168)                                           / ^: V" V2 J$ M% r6 P) Q+ P* d
  24. void delay_us(u32 nus)* ]4 w# Z2 C% A/ [4 s
  25. {        8 K( R) H& |/ x# P6 Y3 x) W* Z
  26.     u32 ticks;
    8 G, w" G. N; |0 p  f
  27.     u32 told,tnow,tcnt=0;
    2 M+ ^4 x9 |% M* }: x
  28.     u32 reload=SysTick->LOAD;                //LOAD的值             ) c; }4 ]/ h3 \3 p$ T7 P: d
  29.     ticks=nus*fac_us;                         //需要的节拍数
    / _0 b6 v  ~6 h! C8 n0 v
  30.     told=SysTick->VAL;                        //刚进入时的计数器值$ v9 U0 A' Y2 C* G7 p
  31.     while(1)
    2 G. e7 n, `* j( Q; c. k
  32.     {
    - }5 T. [8 I1 s4 }
  33.         tnow=SysTick->VAL;   
    ' J5 E  t$ Y: w& n* b
  34.         if(tnow!=told)
    0 i1 @" H6 V( Y8 M4 y# X  Y5 G
  35.         {        " X4 v' |5 A' @/ P) R. l9 I2 Z9 L5 a
  36.             if(tnow<told)tcnt+=told-tnow;    //这里注意一下SYSTICK是一个递减的计数器就可以了.# B) X" e4 e7 L4 O" N
  37.             else tcnt+=reload-tnow+told;        ; K) A! y0 G$ b- b- T! k
  38.             told=tnow;( [' ^. Z0 H/ O/ |
  39.             if(tcnt>=ticks)break;            //时间超过/等于要延迟的时间,则退出.  ^1 f) B8 A; I) D* U: u. R# \& Y
  40.         }  8 w  X8 h. g& M- [
  41.     };                                            ' R: m4 d+ e; _" ^, |8 Z7 a9 w2 I
  42. }  
    3 D" h9 k% Q: }

  43. 4 |& i- G7 W4 G

  44. & c4 p& @% T; d4 |; V7 e4 U9 ^
  45. //延时nms
    % B8 Q" \3 l8 ]7 f' v) B" N! I( W
  46. //nms:要延时的ms数: v5 i& ~/ r2 e  Q1 q
  47. //nms:0~65535& h, \) a# `0 U: v2 W1 h
  48. void delay_ms(u32 nms)
    3 f) ^6 P2 J: J$ ]
  49. {   
    & f5 p( ^, j2 _- S1 k: h
  50.     if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
    2 m0 K5 I1 |9 X2 s4 ]/ t- ^
  51.     {        6 x( \1 P% _) c! C3 K
  52.         if(nms>=fac_ms)                        //延时的时间大于OS的最少时间周期
    3 ?3 u2 M" g6 z5 ?/ U4 N& P
  53.         {   _! a$ c6 C/ ~$ w2 [
  54.                vTaskDelay(nms/fac_ms);             //FreeRTOS延时- U1 N7 h# [' n% q
  55.         }
    8 O) _8 x& U7 @1 l3 H9 T% c
  56.         nms%=fac_ms;                        //OS已经无法提供这么小的延时了,采用普通方式延时    9 A4 t& |/ Y) ]3 X2 `, X
  57.     }3 O1 d% N" P4 d& ?
  58.     delay_us((u32)(nms*1000));                //普通方式延时
    : N% I) ?- d) g8 i2 ~' A' m/ N
  59. }
    3 t2 Z  p0 u$ l/ Y
  60. 8 o' _4 j, H& S
  61. //延时nms,不会引起任务调度" m0 l0 C4 t2 ?' U- V
  62. //nms:要延时的ms数
    . M; O! m+ V. C) N
  63. void delay_xms(u32 nms)
    " V$ x$ x; J4 j+ }
  64. {
    / [8 N1 `6 E! K! H
  65.     u32 i;
    ) i2 Z! |: {' ^0 f
  66.     for(i=0;i<nms;i++) delay_us(1000);& w" Z, Y$ j# I* ?
  67. }% k4 I$ r. g8 |) Q, Y+ \0 O5 x
  68. ————————————————
    8 l0 f! Z. W$ I3 G, V: C
  69. 版权声明:本文为CSDN博主「无敌小小雷」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。, D: h/ x  e$ X* ?" t" w; A) }& G
  70. 原文链接:https://blog.csdn.net/qq_39577221/article/details/125153214
复制代码

: \. h  I  _2 d" \# j————————————————$ \- G! Z& P) w( Q
版权声明:无敌小小雷
; Z/ V$ M: p% a% h/ A5 {4 `2 K: H如有侵权请联系删除: e6 r* d0 o( S$ ]( B! K

6 G& O; b: M; r. T& Y" u
收藏 评论0 发布时间:2023-3-8 13:00

举报

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