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

【STM32C0评测】C071:GPIO+定时器+串口

[复制链接]
戈壁滩上的辉煌 发布时间:2025-5-10 23:38
       我们板子第一次上电的时候看到的就是LED的闪烁实验,而且还可以通过按键来调整闪烁的频率,这个板载demo的效果,两个LED交替闪烁,一般板载的demo都是通过延时的方式实现的。这次我们将通过定时的方式实现两个LED的同频闪烁,通过外部中断的方式采集按键,调整同频闪烁的频率。2 K' z5 s4 K# C
       我们先看一下需要使用的硬件资源:$ G, o( L! E( h7 \
       LED:1 K, M* e/ G) ]/ N7 ]
1.png
4 r. _# Y7 f. b* s4 i$ b

# I3 Z* V+ d$ S6 |6 o4 V       按键:% b5 k) e% T3 p) ?( w' f' _6 D7 Y
2.png 0 @3 `' U3 r9 B) n" C, d  h1 X' o9 Q
3 ?$ K: E& _  V( }, V
       GPIO的功能专注于具体引脚的实现,涵盖输入与输出两大核心方面。输入功能主要用于采集外部器件的状态信息(例如按键状态),而输出功能则实现对外部器件的有效控制(LED的控制)。本开发板装备了两个LED灯作为可操控的外部器件实例,同时配备一个用户按键,用于输入信号的检测。简单分析一下原理图,LD1事业绿灯,想要点亮需要PA5输出高电平,LD2为蓝灯,要点亮需要PC9输出低电平。按键按下的时候另一端是地,也就是低电平,所以对应PC13引脚的初始状态要为高电平,不过硬件中R34并没有连接,我们需要通过引脚配置内部上拉。
5 C; t( o" ^5 I       定时器是MCU的内部模块,通过精准计数进行计时,这就涉及到时钟的配置来计算定时器参数。8 M1 S( |9 X* M# O% ?$ \
       接下来我们基于板卡创建工程:4 \! f! X4 p# \8 a
3.png
$ o* h# R  v+ M! U" o

( K' D- P; G- {, ~3 q! |$ x       我们先看一下基于STM32Cube的模块配置,由于引脚的多样性,我们可以在引脚上直接操作:5 Y  M- o( b2 \/ |* _2 J# @
4.png 3 ], r; ^' m1 [- O* K) E) n! e7 d

1 V4 r0 l6 C3 H: Y( a       接下来配置三个引脚,一个按键,两个LED:# H& g2 p* s6 E
5.png
$ y8 v* y; y2 w1 Q

) }9 z+ K8 U( @9 t, X       配置定时器模块前先看一下时钟配置,并修改为24M,最大支持48M:
1 M0 N2 m" s) l6 L, F$ `
6.png
: o1 A) W- R0 V. G4 ]$ p
- {2 L1 k/ `5 h' x
       接下来配置定时器,我们选用的是定时器14,是一个普通定时器,配置的参数也比较少,定时1ms:- t& Q, v4 u3 J' \
7.png
" \  y5 G% V8 o& S6 d, z" f

( u4 E7 z5 l$ f7 X8 s. q8 p       接下来是中断配置,实际上我们在上面的具体模块配置的时候就可以进行中断配置,也可以统一开启:7 \5 {: p9 o' H4 B9 h4 f8 m+ J
8.png
7 X& e4 `& i$ [1 b, z/ v6 A

0 n3 y" |2 f% ~; {- o$ v" O, |       到这里硬件方面的配置已经基本完成,我们开始软件方面的操作,实际上我们实现的功能也是非常基础了,初始化和定时处理部分都已经添加了:
' ^& V$ I4 |) K+ ]8 K' V# L  a6 n
9.png

, {. k9 |8 I: }3 v% O; c       我们创建两个变量:$ |% j- |) F5 l0 f5 E3 L6 ~* R
/ \; A7 b1 L0 @2 \  _* z
  1. uint16_t LED_TimeCnt_limit = 0;% @3 Y, c% p% M- P
  2. uint16_t TimeCnt = 0;
复制代码
      LED的闪烁就是通过判断TimeCnt是否等于或者大于LED_TimeCnt_limit进行LED的状态翻转。# L3 C0 m9 X5 r* z% o  Z
       我们需要做的就是编写对应的回调函数:
  T; X% N1 N. @0 g
  1. void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)3 S5 z  R* R/ X
  2. {
    1 ?* w) N  D- @4 x
  3.      if(GPIO_Pin == GPIO_PIN_13)
    ! C  T4 H  e) K4 l$ o3 \7 L
  4.      {
    3 q: p" t0 f* ?$ O5 P! d9 [
  5.                 LED_TimeCnt_limit += 500;3 x' g4 `0 Y; ]/ x
  6.                 TimeCnt = 0;7 {% J6 T& x+ W
  7.                 if(LED_TimeCnt_limit > 1500 )
    - [, N4 x+ M2 g" [) D$ f8 V* z
  8.                     LED_TimeCnt_limit = 500;* j+ I3 v" O- g% v: n; c$ b
  9.      }
    9 g% M7 |6 j2 a
  10. }
    ' O5 @. s' f* f- g. w

  11. ' c  }8 ?& \* ^: N. f+ ^0 c
  12. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    5 ^! a& W% P8 ^: p4 y' ]+ X
  13. {* H/ I8 E- S5 K' `  |- z
  14.   if (htim->Instance == TIM14) {
    ( M( m# M9 s8 [  ?& r
  15.     HAL_IncTick();
    . V+ ~  j; k% q( }) ?
  16.         TimeCnt++;
    ! @2 l; K* a# @2 Y8 i% X5 ]+ R
  17.         if(TimeCnt > LED_TimeCnt_limit)
    1 Q" Z  m  r& I3 i
  18.         {+ ]2 g9 v" S6 G: D, B. e
  19.             HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);! [. F% h" k: W0 s" E* L
  20.             HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
    1 h$ E4 ^( o4 Q8 z# Y8 r  J* }
  21.             TimeCnt = 0;
    $ F# G$ Y! B9 W7 j; q1 T) w- @: u8 ^6 |
  22.         }
    , Y' G8 k2 H' [
  23.   }9 h% e; ]+ R) z$ o1 `' F( b
  24. }
复制代码
      这样我们就通过定时器实现的了LED的翻转控制,这个时候我们加入串口的控制,实在是串口和这种多模式的控制太搭了,我们可以通过串口实现同样的翻转控制命令,同时也可以通过串口打印当前状态,我们试一下加入模式变量,因为要实现同步控制,必须按键和串口命令控制的对象是同一个。6 q- l: G7 h8 I/ _0 e
       配置串口2模块:
% o5 l6 i" S( @5 s5 \
10.png
# f* K& i. z3 G

& Z$ j3 \# L2 X8 t* t/ Z( G' ~' S       实际上在生成工程的的时候这个模块就配置了,估计当成必备选项了,行为这个串口连接的STlink:
9 p7 J6 v/ v9 M# _/ @/ r
11.png
. K, O5 q6 |3 q

+ {1 W& a9 i! N) t2 O" ]1 q4 Q       我们先实现一下printf打印功能,加入一下代码即可:
2 g, l+ j( a, K" ^- O  l. O* [( k
  1. #if defined(__ICCARM__)
    % u" ?) c: \) e
  2. __ATTRIBUTES size_t __write(int, const unsigned char *, size_t);
    ) w3 m/ S7 j8 y* V: @$ y" ~- B
  3. #endif /* __ICCARM__ */
    ( x% T+ [5 s3 j2 `2 o

  4. ' x+ m+ ]4 K" D* R* X  l2 b
  5. #if defined(__ICCARM__)/ i; p4 z8 d# s3 p) K6 m8 i; w/ w
  6. /* New definition from EWARM V9, compatible with EWARM8 */
    + @3 D4 A$ }: X* p+ s
  7. int iar_fputc(int ch);) g/ I: Z, E0 U; T+ G7 z+ B, A
  8. #define PUTCHAR_PROTOTYPE int iar_fputc(int ch)/ j1 }3 R- \5 D, x3 a
  9. #elif defined ( __CC_ARM ) || defined(__ARMCC_VERSION)
    0 }# s7 L* X, d, T
  10. /* ARM Compiler 5/6*/: \2 L7 T, |. @& O5 k, e- J9 K
  11. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    ! h9 K9 U4 \9 U! B9 r
  12. #elif defined(__GNUC__)
    ! `1 O8 i. D" N# E. ]! b
  13. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)) }$ k9 C+ e5 T* i9 }' F* I# S
  14. #endif /* __ICCARM__ */
复制代码
      然后将printf与串口2关联:
6 d" S" }5 D6 @  z: X, B
  1. PUTCHAR_PROTOTYPE1 ~8 T  d: w' ?, t% u. M
  2. {
    ) s6 e: C( U4 y$ R. L/ A
  3.   /* Place your implementation of fputc here */
    7 C+ w$ W# r% {: Z6 _4 m
  4.   /* e.g. write a character to the USART3 and Loop until the end of transmission */; ]2 v0 ~) _7 Z" A! Z
  5.   HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);9 Z5 P. O9 R) M$ r) B+ c- z
  6. / M6 e' s( M% g$ ~! Q
  7.   return ch;* a# V& i; T) U7 V& w/ w* a, Q
  8. }
复制代码
      这个时候我们就可以用使用printf打印功能了。* D7 M& G# T* T" N
       串口的接收依然使用的是回调函数的方式,同时修改按键控制内容:
: X# r% u/ W( G9 m
  1. void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)& c+ c" n! M7 \
  2. {
    - ~4 o! W1 }! i% O/ n
  3.      if(GPIO_Pin == GPIO_PIN_13)! v! r1 Y; {* I  A' x
  4.      {$ N8 i- t' |3 ]
  5.                 LED_Mode++;  C" c* \* t: e) w! e; v5 ~2 V: a* p

  6. 1 [' R8 D+ A9 h" n6 ]* l
  7.                 LED_TimeCnt_limit = 500+500*LED_Mode;
    9 |/ z0 l& v) G& p6 l" v' F8 T
  8.                 TimeCnt = 0;
    . m% h# O+ u' D
  9.                 if(LED_TimeCnt_limit > 1500 )+ R* b; r. ^- Q  n2 a# M2 r5 X& Z
  10.                 {
    + K$ \. }7 Z9 {& x  {
  11.                     LED_Mode = 0;9 Z! x8 {+ u" G& \6 H/ N& {
  12.                     LED_TimeCnt_limit = 500;
    9 [  p- ]! \2 @
  13.                 }* B' ?) v3 z) S
  14.                 printf("New Mode:    %d\n\r",LED_Mode);
    . A& a& X2 W; h& b, ~# J
  15.      }8 A+ ?2 R7 f: r7 h% q7 W5 B9 i+ ^
  16. }
    4 Z5 o# O$ Y: E0 \
  17. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)# ]  |6 a9 \$ R7 p" r
  18. {2 T0 t3 l% I1 J) V
  19.     if(huart->Instance==USART2)# v/ ]4 [& d9 R
  20.   {
    2 @  t  Q3 |$ S! k9 y5 J  Z7 b
  21.             if(UART2_RXData == 0x00||UART2_RXData == 0x01 || UART2_RXData == 0x02), y" C$ A; |9 v0 P# i/ C
  22.             {
    8 a+ x% ^. T/ x
  23.                 LED_Mode = UART2_RXData;
    0 m2 M1 A; H2 c  s+ {& b: A
  24.                 printf("New Mode:    %d\n\r",LED_Mode);# H4 d8 |8 ~; g# Y0 r/ }* t
  25.                 LED_TimeCnt_limit = 500+500*LED_Mode;" q  ]( ]$ x  B) M# ^  g/ _, q
  26.                 TimeCnt = 0;
    % i: X5 L# F  _- O: L9 Q4 Q
  27.             }/ B* U+ E: Y3 ^
  28.             HAL_UART_Receive_IT(&huart2, &UART2_RXData, 1);: E9 [& b/ h0 D5 @! h8 Q- L3 n) b2 E
  29.   }
    5 x& f$ X6 g- ^7 i9 e3 U
  30. }
复制代码
      整体的效果如下,我们将操作过程和串口控制过程通过动图的方式进行展示:5 h3 a" {$ a6 n: o, l9 G( n5 }8 D
74502b93f6b77b2dc011d0d08f253a74 (1).gif
3 e1 P7 }0 M- R0 }  P
& b- b2 p) Z; i% z9 X8 a+ W
       整个对应的串口反应:6 `  C3 h2 A' Q8 f; t  m
12.png
* I& c, K1 H+ G" h0 a2 w3 r' ^  K3 E! n

) a2 ?3 a" ~: H; A2 T. t. P# g4 R' [9 o. P  l& }# V! O) U
9 Z; o* p) w* |0 J/ a: G* e) s

1 N+ h! \/ o" w: E3 \9 |
7 j/ E4 Z5 Q# B: V1 u
2 t$ |* A# a! j! ]
0 }, d5 @5 m/ d5 y
0 f0 o5 {9 W. }6 Q5 K: g5 j5 d' h0 X" d$ ~8 L- H5 M5 J8 {" b

. z0 V. c5 G8 p3 w6 i- D- X( P; t

" b2 M9 }! Y# E( F* K. l( t6 `9 _" p6 V; {6 X1 f* }
3 X/ s" D. w+ t3 H3 W" B
7 Z% c( S# `! i. W2 l' e% f7 ]
) k1 A7 {; A% A' o6 p/ D
. W) P" Q# |1 l
收藏 评论0 发布时间:2025-5-10 23:38

举报

0个回答

所属标签

相似技术帖

官网相关资源

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