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

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

[复制链接]
戈壁滩上的辉煌 发布时间:2025-5-10 23:38
       我们板子第一次上电的时候看到的就是LED的闪烁实验,而且还可以通过按键来调整闪烁的频率,这个板载demo的效果,两个LED交替闪烁,一般板载的demo都是通过延时的方式实现的。这次我们将通过定时的方式实现两个LED的同频闪烁,通过外部中断的方式采集按键,调整同频闪烁的频率。) Q  H# g! c$ ~, M7 v1 q
       我们先看一下需要使用的硬件资源:* n% u; Y! q$ J
       LED:% a9 B1 q1 h6 s; n( z& b# l9 T- _
1.png % z# E# ~, X5 y9 U- A& q8 ^# [

& s- ~0 Z4 Y& ?7 Z7 w$ ?       按键:
8 Q" B9 S% s) A) c6 s2 y  x  B
2.png 6 K. Q. T3 l1 ]7 ]/ A1 ]! ]
& j; K( q  e5 u% ~$ i& u+ a" F. z, }
       GPIO的功能专注于具体引脚的实现,涵盖输入与输出两大核心方面。输入功能主要用于采集外部器件的状态信息(例如按键状态),而输出功能则实现对外部器件的有效控制(LED的控制)。本开发板装备了两个LED灯作为可操控的外部器件实例,同时配备一个用户按键,用于输入信号的检测。简单分析一下原理图,LD1事业绿灯,想要点亮需要PA5输出高电平,LD2为蓝灯,要点亮需要PC9输出低电平。按键按下的时候另一端是地,也就是低电平,所以对应PC13引脚的初始状态要为高电平,不过硬件中R34并没有连接,我们需要通过引脚配置内部上拉。
7 D$ c, X& H  _! m6 `& g& R       定时器是MCU的内部模块,通过精准计数进行计时,这就涉及到时钟的配置来计算定时器参数。
8 T$ D. k( p3 d& }# `0 F       接下来我们基于板卡创建工程:2 }- x& n( ~% i1 T# c6 ^& X0 d' S
3.png 4 U9 q' @" {- h$ o9 a7 Y1 G/ f

* M4 [" t! x8 r3 g4 h       我们先看一下基于STM32Cube的模块配置,由于引脚的多样性,我们可以在引脚上直接操作:  g0 V3 f) q5 r9 x3 u, c3 [2 H' x
4.png
$ c. K$ e9 t! G% f5 r
* W  N0 [( N2 O/ N
       接下来配置三个引脚,一个按键,两个LED:
  ~6 k& ?: u! I* k2 Y, ^) E' Q
5.png 7 a+ D/ V9 b) d. ?

, c  f" |" v- d       配置定时器模块前先看一下时钟配置,并修改为24M,最大支持48M:. N4 a* P$ t. |% i" v8 Y6 F
6.png
8 {4 V8 ~+ \- B- l# N
4 U0 M- T, t! B( K6 A$ ]8 i
       接下来配置定时器,我们选用的是定时器14,是一个普通定时器,配置的参数也比较少,定时1ms:
5 I9 L8 C( F- E
7.png 5 y/ K! f+ `) _/ T

' C& P5 h/ o7 ]& p3 V( U       接下来是中断配置,实际上我们在上面的具体模块配置的时候就可以进行中断配置,也可以统一开启:
, ]2 _# U9 E3 n& p0 b  C: t
8.png
, K* q, N1 V& W4 P  c

8 |8 ^2 u, M0 J1 O- L       到这里硬件方面的配置已经基本完成,我们开始软件方面的操作,实际上我们实现的功能也是非常基础了,初始化和定时处理部分都已经添加了:
- `+ u: y5 u7 E* {# D" L
9.png
. A* S3 g  h9 j4 ?
       我们创建两个变量:( {8 |1 u" u" {) p/ T7 t

: \& n$ F8 S; Y& _, t1 ~+ l5 A1 u
  1. uint16_t LED_TimeCnt_limit = 0;
    0 |' d" F+ w0 h) X7 Y4 u% f
  2. uint16_t TimeCnt = 0;
复制代码
      LED的闪烁就是通过判断TimeCnt是否等于或者大于LED_TimeCnt_limit进行LED的状态翻转。  k& Z* C, \% t$ G* Q' M
       我们需要做的就是编写对应的回调函数:) X, ~+ Q: j$ n6 s6 ^% g" [: U( e
  1. void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)6 U0 ^( [. l! A' }5 U
  2. {  @; e+ n! g  \# i+ }- s7 v( G+ n
  3.      if(GPIO_Pin == GPIO_PIN_13)
    $ F* f; s6 }( B8 t
  4.      {
    6 Q! o0 L+ S  s0 a) ~
  5.                 LED_TimeCnt_limit += 500;
    ( v3 T1 M9 B' a. Z
  6.                 TimeCnt = 0;
    ( ]0 k3 t+ t3 B' h
  7.                 if(LED_TimeCnt_limit > 1500 )
    4 k0 e$ |# d, l1 [  M. `2 V6 ?$ ^
  8.                     LED_TimeCnt_limit = 500;
    1 }( l+ l; f' e- v4 ~+ P
  9.      }) D: B' d6 E2 ^: V7 Q0 k
  10. }2 p8 Y) m" h1 L
  11. 5 }' \! T' [& [  B& h" [2 B$ q' n
  12. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)! C& a( e% `/ g* a. {& h
  13. {6 P* s% A7 [" \7 U! g
  14.   if (htim->Instance == TIM14) {% X- n& D, I$ N/ n
  15.     HAL_IncTick();& `# h4 a2 B# k/ C) ^
  16.         TimeCnt++;
    ! U, I* a8 @! P3 {
  17.         if(TimeCnt > LED_TimeCnt_limit)& H: S9 b; D" Y0 {8 B, u! p
  18.         {
    : t1 T3 }$ S" u% M0 ^) R6 Q0 E* H
  19.             HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);" b$ i; q& Y! f
  20.             HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);- ?$ L* `. h9 I
  21.             TimeCnt = 0;
    , Z& c1 @! L0 [- c0 u9 `" p
  22.         }, A) `. C. A4 D
  23.   }0 s6 U+ h5 z- _) l0 x+ |
  24. }
复制代码
      这样我们就通过定时器实现的了LED的翻转控制,这个时候我们加入串口的控制,实在是串口和这种多模式的控制太搭了,我们可以通过串口实现同样的翻转控制命令,同时也可以通过串口打印当前状态,我们试一下加入模式变量,因为要实现同步控制,必须按键和串口命令控制的对象是同一个。: Q! U/ V" K+ N  L1 p
       配置串口2模块:; ~/ b; W2 ?& Q$ i. O# V* |3 m
10.png
* n+ b8 f( T$ C

, A) j, ?2 h7 C       实际上在生成工程的的时候这个模块就配置了,估计当成必备选项了,行为这个串口连接的STlink:- t" m: y8 k2 G8 {; u; m
11.png
& k! W9 @" y6 l& I1 l) i. K
& H* @7 D# v1 Q2 ^
       我们先实现一下printf打印功能,加入一下代码即可:! Q" j- v2 O2 i2 P6 V( D5 w
  1. #if defined(__ICCARM__)8 a$ T$ x  U/ D. J3 K. ^
  2. __ATTRIBUTES size_t __write(int, const unsigned char *, size_t);
    9 O) V* s$ |4 h7 e
  3. #endif /* __ICCARM__ */
    & ~9 j. `4 p( [6 J6 @
  4. 2 |2 m  [1 w8 o: z
  5. #if defined(__ICCARM__)
    . B8 n3 x' f" {7 A' ^
  6. /* New definition from EWARM V9, compatible with EWARM8 */$ l: d) X' r2 S- F% A  Y
  7. int iar_fputc(int ch);
    $ [+ j; \. c  I; c" X
  8. #define PUTCHAR_PROTOTYPE int iar_fputc(int ch)6 U: E( x2 X; o( {- t! j8 `3 V6 R: X# @
  9. #elif defined ( __CC_ARM ) || defined(__ARMCC_VERSION)2 P. l; V4 T" r9 W, f% x9 i
  10. /* ARM Compiler 5/6*/
    8 c1 M0 Z( k9 n) A
  11. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    1 e9 v* M" w4 `# F2 L8 C( A
  12. #elif defined(__GNUC__). D% F$ R7 o% W8 K/ b% B
  13. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    ; [4 J, ?8 ^5 L5 z1 n' Y
  14. #endif /* __ICCARM__ */
复制代码
      然后将printf与串口2关联:
) C- I; L8 w. |0 t" u9 W% [
  1. PUTCHAR_PROTOTYPE
    + ~0 z3 E: Y4 H% X/ K3 t
  2. {) K/ Y- D0 v2 I# q
  3.   /* Place your implementation of fputc here */
    * m2 j& [) V" C/ n. a3 S; ^
  4.   /* e.g. write a character to the USART3 and Loop until the end of transmission */
    ) }' V/ j; U  S0 ]2 f# d2 Y
  5.   HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);& y0 }0 j& s, x

  6. 9 A3 N8 H; y) Y4 M$ Z3 ~/ w0 X4 c; z( u
  7.   return ch;- z  E; H" l) S& y1 H! m! h6 s
  8. }
复制代码
      这个时候我们就可以用使用printf打印功能了。7 o# x  f. y2 j5 C4 F8 ?
       串口的接收依然使用的是回调函数的方式,同时修改按键控制内容:
: |) z. U, \/ Y4 b) M& s; g
  1. void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
    1 ~: u  W0 Y  L$ C( @" i
  2. {  S7 ~( A9 p$ u+ O7 t( ]& l& n3 q
  3.      if(GPIO_Pin == GPIO_PIN_13)6 l  {" H$ z% W+ A2 M" A
  4.      {
    5 l- ~* s6 ~# f  k4 l1 }
  5.                 LED_Mode++;3 l  V; M5 F# o; k2 v/ K
  6. . R7 k4 ~; M# V. c# j9 _  Y: f$ h
  7.                 LED_TimeCnt_limit = 500+500*LED_Mode;
    ! s+ ]+ _/ y2 {5 d% c7 t
  8.                 TimeCnt = 0;' ~) k: Y; M& l8 D7 I; n7 n
  9.                 if(LED_TimeCnt_limit > 1500 )
    4 }3 n, y8 F% r6 R1 i* N) V
  10.                 {
    # G6 T2 ^: _; C: K
  11.                     LED_Mode = 0;
    0 m+ q8 v2 q" q* D: A" T5 {
  12.                     LED_TimeCnt_limit = 500;
    + I8 g+ X2 \" R, s4 J8 _# t2 |
  13.                 }
    ! a  M9 N6 d) u" E+ F% S0 ?
  14.                 printf("New Mode:    %d\n\r",LED_Mode);
    + b; q( }/ a9 Z; v
  15.      }
    . Z* R' n& m& N
  16. }
    7 O+ {! {, |& X; D
  17. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); t; l, g8 y3 K7 J8 H/ x
  18. {
    6 b/ }& I/ H7 G) D* \
  19.     if(huart->Instance==USART2)( h% M# D. k' ?
  20.   {
    * d) S. S% U8 v' w/ n) {
  21.             if(UART2_RXData == 0x00||UART2_RXData == 0x01 || UART2_RXData == 0x02)
    : X+ ?5 q/ F: W
  22.             {4 ^$ h" I1 q/ z
  23.                 LED_Mode = UART2_RXData;4 F' x# A) s6 `" \% d
  24.                 printf("New Mode:    %d\n\r",LED_Mode);8 s" x" x+ F& ~* X' Y3 o/ }  @& Q2 q0 x
  25.                 LED_TimeCnt_limit = 500+500*LED_Mode;
    2 H" R' k! w4 _( w% k
  26.                 TimeCnt = 0;
    # Y: d' u; x+ X
  27.             }
    7 q( b9 N! y  F0 J' i
  28.             HAL_UART_Receive_IT(&huart2, &UART2_RXData, 1);, C+ M. r7 X. I/ H2 P. P' M
  29.   }, M8 d: b3 a( y3 f/ N4 p$ X
  30. }
复制代码
      整体的效果如下,我们将操作过程和串口控制过程通过动图的方式进行展示:
- R6 a# ^) ^% Y* O/ S
74502b93f6b77b2dc011d0d08f253a74 (1).gif 9 C8 e) X: E3 z, n9 r; {

6 v& g- D+ `& m4 ~  {% K* l       整个对应的串口反应:- D; o# p" [$ w$ R
12.png
, H; t6 E4 ^' V) L1 G9 s& e

" X3 S! S7 R5 @" N" ]: ?3 z8 _" G# Y) G# F% u

4 a+ G# D& ]& G- G1 z: Q# v
! Y5 F8 z2 y4 K! D% {/ }0 ^3 r# D# |3 h- F7 k1 T/ W/ h

* a' ^# v9 m/ k& n9 _' M. W1 o# Q# j- O! t0 h5 u7 U

( e6 Y; |1 K1 }: w* ]( ]. a4 b$ B* N
' v0 Z- U% G# ^- S2 @
9 h( u7 M) h. {/ e

  N7 [$ q/ ~9 B. b+ n1 k, l$ ?  A, _( A) w9 E

8 {8 L( y: y2 m5 A; j, @
5 B* B# p" w7 c  F  E$ O6 M: g8 Z3 v# y5 I: U' S! D/ h, u
+ w9 ]9 u1 L9 s9 `3 x. B' h
收藏 评论0 发布时间:2025-5-10 23:38

举报

0个回答

所属标签

相似分享

官网相关资源

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