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

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

[复制链接]
戈壁滩上的辉煌 发布时间:2025-5-10 23:38
       我们板子第一次上电的时候看到的就是LED的闪烁实验,而且还可以通过按键来调整闪烁的频率,这个板载demo的效果,两个LED交替闪烁,一般板载的demo都是通过延时的方式实现的。这次我们将通过定时的方式实现两个LED的同频闪烁,通过外部中断的方式采集按键,调整同频闪烁的频率。: C4 t+ w8 M, o: T% r
       我们先看一下需要使用的硬件资源:2 i6 ?/ x( C" w  H5 N; \) |
       LED:
9 b* u  F) g9 ^
1.png
4 s: Y$ X0 ^9 [% r5 f6 J+ }

& Q" ]. X! j8 X4 ]0 O       按键:3 V# x: |+ K5 R) G3 g
2.png 8 k  Y' U! _" |7 V4 I  c

) j1 c) z; `+ ?; c2 q       GPIO的功能专注于具体引脚的实现,涵盖输入与输出两大核心方面。输入功能主要用于采集外部器件的状态信息(例如按键状态),而输出功能则实现对外部器件的有效控制(LED的控制)。本开发板装备了两个LED灯作为可操控的外部器件实例,同时配备一个用户按键,用于输入信号的检测。简单分析一下原理图,LD1事业绿灯,想要点亮需要PA5输出高电平,LD2为蓝灯,要点亮需要PC9输出低电平。按键按下的时候另一端是地,也就是低电平,所以对应PC13引脚的初始状态要为高电平,不过硬件中R34并没有连接,我们需要通过引脚配置内部上拉。( }2 ^# h! N5 u+ G
       定时器是MCU的内部模块,通过精准计数进行计时,这就涉及到时钟的配置来计算定时器参数。
4 R+ q6 W% J1 P& a3 Z& \6 v       接下来我们基于板卡创建工程:
# g, Q5 a& ~4 D
3.png $ H" {/ h1 r7 e

$ O9 q' h6 X4 U6 J       我们先看一下基于STM32Cube的模块配置,由于引脚的多样性,我们可以在引脚上直接操作:2 g" d( Q% q1 \" Q, d- h5 N. |
4.png + X: B# [" J9 E2 |
# ?: q  u3 P, D; ^
       接下来配置三个引脚,一个按键,两个LED:
+ ^3 _* V. T( N
5.png : [. v7 s8 a# R/ r/ `3 }

- i, S( j7 \1 b3 z       配置定时器模块前先看一下时钟配置,并修改为24M,最大支持48M:
  u  c4 y1 Z- g, {) E" L/ V
6.png
) u; U* z) |% w- L; i  @

* u. S# c# z6 N7 \& b5 d* D$ Q; R       接下来配置定时器,我们选用的是定时器14,是一个普通定时器,配置的参数也比较少,定时1ms:+ v$ X" M! o3 Z; y0 B( j0 B1 ]* R$ Y; y
7.png
" m8 g6 N1 r! H: O0 |7 D

6 J( W+ R. m+ }* W, \       接下来是中断配置,实际上我们在上面的具体模块配置的时候就可以进行中断配置,也可以统一开启:9 }4 o9 {. A( S( v$ T% U  T, q, z, U+ r
8.png
" \; v3 d* E8 }, z) ?$ t0 d7 P5 q/ n

) O, G1 W1 @, Q- ~& W* y       到这里硬件方面的配置已经基本完成,我们开始软件方面的操作,实际上我们实现的功能也是非常基础了,初始化和定时处理部分都已经添加了:8 }! ^. P: y( T  P: J0 _
9.png

# S$ X8 l: y+ T0 k, G# v9 N2 E2 r! n       我们创建两个变量:
3 [9 [7 N2 h; x4 h: v$ `; F% C, J
' F* I& l% s5 P3 _
  1. uint16_t LED_TimeCnt_limit = 0;
    ) d( d) j; G0 R) }. }# ^# {0 H4 y
  2. uint16_t TimeCnt = 0;
复制代码
      LED的闪烁就是通过判断TimeCnt是否等于或者大于LED_TimeCnt_limit进行LED的状态翻转。
& @5 r5 s" u0 ]% A       我们需要做的就是编写对应的回调函数:
. L7 c4 O* Z& {  k0 `0 |
  1. void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
    2 B% A( K/ S7 M: U3 m7 z# ^* ?
  2. {
    5 W, ^) f/ }. f7 I5 Q
  3.      if(GPIO_Pin == GPIO_PIN_13)7 r% f$ F$ @* w7 z1 C# Z% v
  4.      {
    & J' J2 ]& k# m* V  p) C7 U. P
  5.                 LED_TimeCnt_limit += 500;3 i9 b6 E) Q: W& g9 C
  6.                 TimeCnt = 0;+ m1 I! n8 @/ _) V: K. x: y
  7.                 if(LED_TimeCnt_limit > 1500 ): t; @, w3 n; x4 X9 [
  8.                     LED_TimeCnt_limit = 500;; z: z& s: e" {2 [
  9.      }! c6 E) A2 A4 j/ f8 p; w* j+ g; w. Y
  10. }2 T5 b! d1 l( ^/ {, z( x
  11. $ x8 l' S. {4 s; B1 w) u& e
  12. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)* a" z3 k+ D6 ?3 l. j' \
  13. {
    . h$ y: \9 h9 y+ X) q: q
  14.   if (htim->Instance == TIM14) {# {; E5 |. G3 ~# `
  15.     HAL_IncTick();
    ; N. r, s9 `; b4 |" u
  16.         TimeCnt++;
    $ ]8 q; {) G$ z" s; M
  17.         if(TimeCnt > LED_TimeCnt_limit)5 d/ u/ P# ~/ J  p4 [
  18.         {
    + _4 J( V! L5 _+ b4 _2 y& B
  19.             HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
    , W+ L5 i3 S( U, ?9 n" R, B
  20.             HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
    " l. o+ a: ~( f
  21.             TimeCnt = 0;
    5 n+ ~* j& _" I# ^
  22.         }
    $ n* n3 s& ]4 v& N% O8 Z8 @9 c
  23.   }
    2 |' W) W% n2 }# t
  24. }
复制代码
      这样我们就通过定时器实现的了LED的翻转控制,这个时候我们加入串口的控制,实在是串口和这种多模式的控制太搭了,我们可以通过串口实现同样的翻转控制命令,同时也可以通过串口打印当前状态,我们试一下加入模式变量,因为要实现同步控制,必须按键和串口命令控制的对象是同一个。7 \" N0 r5 H: I- x6 k
       配置串口2模块:
. t6 B3 z. I2 K8 E0 O9 Y; H7 R
10.png
+ \+ P: t: P) [- e% F* Q5 r

; ^$ c% r9 ?! L8 j; a       实际上在生成工程的的时候这个模块就配置了,估计当成必备选项了,行为这个串口连接的STlink:
5 G7 s1 X4 Z6 y
11.png
1 \7 Z8 n' d) k; x
4 ?# Z2 k5 s! r: P, h; y. ]
       我们先实现一下printf打印功能,加入一下代码即可:
2 {* N+ O+ [/ \" I4 E5 v
  1. #if defined(__ICCARM__)- L( H8 S7 @. ^7 E* A7 J' G
  2. __ATTRIBUTES size_t __write(int, const unsigned char *, size_t);1 w/ I5 f/ }! O, V. \3 @' C
  3. #endif /* __ICCARM__ */
    - ^- n: j( E0 y1 |9 w% V$ y
  4. 6 c! `, O; u& A
  5. #if defined(__ICCARM__)
    : o" s1 T1 X4 p2 q! a
  6. /* New definition from EWARM V9, compatible with EWARM8 */
    " {, D9 j: M: o1 X2 u5 ]
  7. int iar_fputc(int ch);& _' m/ `4 ]& S1 m6 G
  8. #define PUTCHAR_PROTOTYPE int iar_fputc(int ch), l3 |) @) N% q
  9. #elif defined ( __CC_ARM ) || defined(__ARMCC_VERSION)* Q, p8 B0 S5 c- V( x7 Q( k& j
  10. /* ARM Compiler 5/6*/' F0 v" s6 g$ d, z+ r! b% Q4 ^
  11. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    8 {. F/ G( G: F
  12. #elif defined(__GNUC__)
    . P$ x/ X, c& A; N) \
  13. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)6 i7 G+ A' @4 p' W
  14. #endif /* __ICCARM__ */
复制代码
      然后将printf与串口2关联:
/ R; N& s6 c4 b2 K
  1. PUTCHAR_PROTOTYPE' }, v2 I% w  L2 _7 ]" n4 t
  2. {2 H9 I* x/ ^) K8 d7 Q
  3.   /* Place your implementation of fputc here */
    ; ~* C$ G* k4 r, V( m1 d% w
  4.   /* e.g. write a character to the USART3 and Loop until the end of transmission */1 j: H2 k- a& g7 w8 I
  5.   HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);
    8 [5 F3 T. P; A, {& s! F
  6. . F' M4 g$ V( |/ U  G/ p( E9 K
  7.   return ch;
    : S& x6 L: R. y" A# {" g
  8. }
复制代码
      这个时候我们就可以用使用printf打印功能了。. d( ^* d( Z( E  v& E8 m5 m
       串口的接收依然使用的是回调函数的方式,同时修改按键控制内容:) F7 P2 P* X. |$ T% \( _  l
  1. void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)$ U+ v/ ?- B% Q) y5 V0 l
  2. {
    + B4 Q' V' i2 R* k# \3 d/ i$ I4 `+ I
  3.      if(GPIO_Pin == GPIO_PIN_13)& n" _- s* H/ v* a
  4.      {
    - L) |0 B/ g  l' v& P+ ~
  5.                 LED_Mode++;
    ' v0 R) M$ O4 C% i; A/ c

  6. % {, Z* N+ Y2 d- _( ?/ a
  7.                 LED_TimeCnt_limit = 500+500*LED_Mode;2 a5 s& z% ^8 F8 h# |7 C0 l
  8.                 TimeCnt = 0;
    ( U% m5 V; s1 R# Z* g* [# V/ c
  9.                 if(LED_TimeCnt_limit > 1500 )
    / _5 C9 a) U- b/ V8 q7 `% E
  10.                 {0 t* t+ m4 r) s4 V2 M. C
  11.                     LED_Mode = 0;% P6 \8 ~' w8 d. p' W# v( u$ v
  12.                     LED_TimeCnt_limit = 500;
    " t. y3 \, N& T% p9 @. U
  13.                 }
    4 v% @$ \7 L- w. R( z" q8 f
  14.                 printf("New Mode:    %d\n\r",LED_Mode);
    ) C. G: D" K" Q7 l. ~
  15.      }1 @* s, s! d' |1 o+ h4 E6 Z
  16. }- k7 b" ]$ d1 i! ~$ L' {5 }8 n
  17. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    & ]% C% w. S- O
  18. {) n" z: E2 c) R4 d7 p
  19.     if(huart->Instance==USART2)4 Y  ?& G0 b1 p$ S( W5 S0 ~* y
  20.   {
    ; E# x0 O) t  P3 C& ?0 p
  21.             if(UART2_RXData == 0x00||UART2_RXData == 0x01 || UART2_RXData == 0x02)
    & ^' Y  g' t) N% B. O
  22.             {
    2 M* z9 A! H$ c7 Q7 r$ U% v
  23.                 LED_Mode = UART2_RXData;2 P' K; s% D# d' V: U/ T0 N/ ]6 T
  24.                 printf("New Mode:    %d\n\r",LED_Mode);9 ?/ n! U. L, ]3 _( W6 S
  25.                 LED_TimeCnt_limit = 500+500*LED_Mode;1 |- f( c7 h) A8 C( N' p
  26.                 TimeCnt = 0;. C8 K+ w( [  P2 ~7 ~3 S2 {$ \- {- j
  27.             }3 k; u5 t  Z6 u- A8 ]
  28.             HAL_UART_Receive_IT(&huart2, &UART2_RXData, 1);' K! B% D5 K" y/ d) P/ F
  29.   }; A6 ]& R+ k7 _4 }
  30. }
复制代码
      整体的效果如下,我们将操作过程和串口控制过程通过动图的方式进行展示:
7 O& N* @- v1 Y, `
74502b93f6b77b2dc011d0d08f253a74 (1).gif + q$ @- T1 U9 b8 L4 c% M# z9 X

  i8 g) B/ s, u; s3 U2 }2 J5 X) W       整个对应的串口反应:
3 X5 x4 n! W( g# M7 i
12.png 7 _+ a( [1 K5 a7 Q; d
1 m  X6 ~' |# l! z
* M9 I6 V7 v& |

( C) v* D, ~! |; ]; u0 F
$ V+ T0 h1 g- u/ r; R7 I9 \3 ?
$ j! g: `# r! C' j- i, @! s' B) }9 S2 @

! K3 v5 j# b9 B! W! j4 w: j7 r5 w  h2 H9 [( F' F0 s, |
4 ^" |; l( |3 r' W
5 h1 n) e/ D7 C+ T3 ?  ^* R; ~

* b( ^$ x% A% ~; |& P
( I8 C* w" [- f' d! x, M' K0 P2 M  D( ~  N3 z

/ l4 |6 G/ I: }) M; r( D' ~* S8 ]. A0 [$ S6 F1 G3 d( c3 {

# Z8 O" h- T1 }4 H. L* n8 K' ^( M. K( j2 y
赞 收藏 评论0 发布时间:2025-5-10 23:38

举报

0个回答

所属标签

相似技术帖

官网相关资源

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