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

基于stm32的流水灯简单入门分享

[复制链接]
攻城狮Melo 发布时间:2023-3-26 17:59
前言
2 t: H/ y. H  @& K8 o3 p解决了驱动问题以后终于可以开始学习STM32了。学习过程中参考的资料是《STM32库开发实战指南》,板子用的是正点原子的NANO开发板,具体型号是STM32F103RBT6。废话不多说,记录一下自己写的流水灯实验。
* E8 j3 i) N6 s( |$ A

4 l" b$ R/ F4 |, M! X* W一、开始前的准备——初步了解STM32时钟系统、学习GPIO工作模式及初始化的过程
! i6 }* k5 a* @, U% k1、STM32时钟系统
3 Y* x& ~: w5 S; R' K8 U& g4 X5 sSTM32有四个时钟源,具体为HSE(高速外部时钟)、LSE(低速外部时钟)、HSI(高速内部时钟)、LSI(低速内部时钟)。其中,HSE由外部晶振提供,一般作为STM32主时钟;内部时钟(HSI&&LSI)均由内部RC振荡器产生,HSI一般为8MHz,STM32启动时默认使用HSI;LSI主要给看门狗提供时钟源,一般是40KHz;LSE一般给RTC模块(实时时钟)提供时钟源,频率为32.768KHz。' H& J4 l8 x: A2 j
* w" J+ _. j. J* J( T7 Q

1 ^9 I' I5 |3 y% q- i2、GPIO工作模式7 e( @/ q' a" P6 y- N0 C
0 }( c6 l. U9 S9 p+ j; o$ h( f
GPIOx工作于输入模式:2 \; e4 _& y" m& W7 q
! ?% U) L! C7 A2 r, q
模拟输入模式、高阻输入模式、上拉/下拉输入模式;
0 g: r/ D0 K9 ?# B& J0 m' k: W  i' o; |* f6 [% t
GPIOx工作于输出模式:
% W( y6 c. [! G8 W
推挽输出模式、开漏输出模式、复用推挽输出模式、复用开漏输出模式。
3 S# z% r+ u5 ^# r" F, C. m; J- R
注:$ {$ K, N. }; `# y! L8 H
推挽输出即输出真正的高低电平,外设于IO之间不加上拉电阻;
6 G0 Z+ w1 Y: e1 F) r开漏输出即输出高电平时无驱动能力,需加上上拉电阻才可驱动外设。
3 l* A# v' `, y
  r2 R0 n8 k& a' L5 s6 M
# U" s0 b8 H7 L: h
3、GPIO初始化流程
+ z. f- ?' K$ K* [6 A/ q4 l定义一个GPIO_InitTypeDef结构体变量(若定义为结构体指针变量,需自己开辟内存空间!!!!)--->调用库函数开启GPIO外设时钟(GPIO挂在APB2总线上,因此需找到APB2上的GPIO时钟)--->初始化结构体变量(选择待控制的引脚、设置引脚模式、设置引脚速率)--->调用库函数GPIO_Init完成初始化3 V1 h9 \6 S) y4 c# j" n, \
, v$ C: w) `" _: N9 B  w
注:
% R. m5 v' q) ~& B! c! B0 G7 O若需同时使用多个引脚,则应直接给 GPIO_InitTypeDef.GPIO_Pin赋16进制值,确定该值的方法是写出一个16位二进制数,将待使用的引脚号对应的二进制数置1(如需使用引脚2,4,8,9;则该值为0000 0011 0001 0000B)。1 B  S2 B2 _0 w! z& i1 X
  H7 Q$ V$ D: m
! ^# y( N4 h, h) w
二、明确硬件资源
2 ?6 A& }8 E0 A5 q* w8 d" T6 @$ ?- x$ \# ^
0e3432c94c340d014c092c04bce53974.jpg
: x, a* n2 M$ P8 \
: ~3 _  I* G* e8 K+ j% F( R0 m开发板附赠的LED原理图如下,是一个非常简单的电路。. G/ G, v1 h0 P5 T) I3 u
; m" p$ i/ M* b+ f
如上图所示,8个LED灯的阳极已经接在了3.3V电源上,它们经过限流电阻后分别引出了8根线:LED0~7;想要某个LED亮起来,那就必须使引线输出低电平(二极管单向导电性);同时我们知道STM32上是没有这8根同名引脚的,因此我们需要查看MCU的引脚分配图,如下所示。% k  {0 R: L4 `: M7 ~

1 {( n' V6 G) N# f! p
d76f0395886438ee65ff042211a55d95.jpg
( J; J' T2 j; B" o+ i$ u, k
5 \0 {4 e) V* k1 v9 N0 Z简单明了0 m7 I9 @$ W0 [2 U; Q
2 e# `' M$ j- A
可以看出来,LED0~7分别连接在PC0~7上。
: \* F  U! s& p& K) j( U: D, X0 {' M3 G9 {" m* d+ u& }
: g! B7 ?* g8 U: L: h: ~* Y
三、程序编写
3 N+ @( X- {; f; C- w# w有了以上的分析和学习,下面的内容就是水到渠成了。8 }. h) Q6 ^& ^
1 e$ c2 U# W" a2 c
1、辅助函数
) C3 v/ s$ Z! s5 B/ q9 g' E: x4 FGPIO初始化函数
( t9 _0 `. \% O
  1. void LED_Config(void){% z  Q2 V3 }3 E, S- Z+ v
  2.         GPIO_InitTypeDef LED;//定义该类型结构体
    " m7 H" F2 G' Y! q" r
  3.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//使能GPIOC外设时钟
    0 H/ j/ J0 ?# F. d" h1 p  L6 [
  4.         LED.GPIO_Pin = 0x00ff;//选择引脚PC0~7( l% p- C$ N/ Z+ f  Z6 p
  5.         LED.GPIO_Mode = GPIO_Mode_Out_PP;//选择工作模式为推挽输出+ f, U! ~( ~, {# l" l& M5 m
  6.         LED.GPIO_Speed = GPIO_Speed_50MHz;//设置GPIO速度为50MHz
    2 a3 I4 }1 }; v$ W
  7.         GPIO_Init(GPIOC, &LED);//调用库函数进行初始化
    5 Z2 E  k. w. K- t
  8. }
复制代码

- y! s& t' T' A; Q* h引脚选择函数
: w/ Q/ o2 J6 h! N考虑到流水灯是要不断选择下一个引脚的,我觉得不如设计一个函数把选择引脚的操作封装进去(不过位操作更简洁,直接左移)。
( j8 T( Q: u4 h+ H: g8 V0 S6 z7 F
  1. uint16_t ChoosePin(int n){/ x5 b) t3 r7 t  r% r
  2.         uint16_t pin;
    ; P; v# d0 r1 W+ t3 i5 Z# i# C
  3.         switch(n){  u/ W+ s2 B) P
  4.                         case 0:
    8 x0 K4 I* t$ ~1 Z
  5.                                 pin = GPIO_Pin_0;  |9 b/ [( V; W2 f4 Y
  6.                                 break;
    0 [# S! E+ f/ M
  7.                         case 1:
    ( Z0 q* R; x8 G  F; P
  8.                                 pin = GPIO_Pin_1;( Z  U# F7 o$ p* C6 q$ o6 f9 g# C+ D
  9.                                 break;
      ?3 l, A  x! E9 t; U; V
  10.                         case 2:
    3 G. u: i! o. N$ q
  11.                                 pin = GPIO_Pin_2;
    + y2 ?6 q" `. x: G- H4 k8 [/ b
  12.                                 break;
    7 B6 W/ K5 ^% }/ I3 a, X
  13.                         case 3:
    . l0 v2 \5 N; c4 E$ v
  14.                                 pin = GPIO_Pin_3;! ^$ l; v$ T+ f% L# [, T5 [0 K
  15.                                 break;. M4 e) ^' c' ^1 x! }. W
  16.                         case 4:
    9 K; V  C* Q, d% _$ X7 O( ]- u
  17.                                 pin = GPIO_Pin_4;
    % o" N( `! k  X, j- w/ l6 ^) }+ |
  18.                                 break;0 H! v0 U" ~/ u9 a
  19.                         case 5:
    " J- j5 r) E" C; p
  20.                                 pin = GPIO_Pin_5;( N; T: \# j* }# k& y+ _5 y; E7 f
  21.                                 break;2 j0 ]# t( u- c* g. J0 X
  22.                         case 6:4 ]+ w/ j. G0 V8 z& L
  23.                                 pin = GPIO_Pin_6;
    ! U! q) A" I! a! L/ h, G+ U+ G% W% J5 s
  24.                                 break;
    1 r7 }' G' F. }* N/ e
  25.                         case 7:
    & b1 y' c% V& v% C  F- I, d3 L
  26.                                 pin = GPIO_Pin_7;
    4 t8 k! V: T7 N. V; j. r$ @
  27.                                 break;7 n5 y9 S, {6 p& B2 u
  28.                 }2 T5 ]+ i1 h; e! A) T: M
  29.         return pin;* r* d3 `- k' ?3 ^% t& c. m
  30. }
复制代码

4 n6 Q8 C7 Y/ M) }' [延时函数
6 v. h- i( F3 Y还没学定时器,所以就粗略延时了,调用一次大约延时1s3 T# Q6 ~- @" c  x: H0 ]
  1. void Delay(unsigned int time){
    1 X. L4 b3 g4 o# T5 ?3 w
  2.         for(;time!=0;time--);$ w- Y: F2 v- O- y9 p) s
  3. }
复制代码

' g4 ?% K. B! j2、流水灯主函数
& q! Z* ]. O4 t8 G$ y/ W
  1. void Run(void){
    ; O1 u2 c( D8 H* \% H
  2.         int i;" k9 [. s8 G: q6 o+ {# p- c
  3.         for(i=0;i<8;i++){
    " P) g8 h: Z# [  @4 z! P
  4.                 GPIO_SetBits(GPIOC, 0x00ff);    //灭所有灯
    1 O  c( u/ o! J; V$ W7 \
  5.                 GPIO_ResetBits(GPIOC, ChoosePin(i));  //点亮指定灯
    + q& D/ g7 M2 A, r
  6.                 Delay(10000000); //延时大约1s- e5 P; v! T' X1 Q/ Q
  7.         }1 P- A9 h% }: X8 y
  8. }
复制代码
1 J# u+ K, ?' F0 g6 u3 G
四、结语
% t  [" I3 Y+ }' t9 c7 [6 Q第一天的学习还是比较轻松的,除了时钟那一块,看的我眼都花了。一开始犯了个大错,我想着GPIO_Init既然接受指针,那我刚开始的结构体也定义为结构体指针多好,然后忘了给这个结构体指针分配内存空间,直接就用了......盯着没量灯的板子发呆,突然反应过来指针是NULL哈哈哈。
/ E- E+ D0 h# M1 w3 B+ Q' W————————————————  U1 P* u6 Y) L5 H5 T. N
版权声明:被大佬糊弄的只会点灯的小菜鸡
0 I" J" @( g: h' j+ N如有侵权请联系删除
3 M2 V9 S" Z/ Z' v" m* v7 S' p( F4 i9 ?$ O1 M
赞 收藏 评论0 发布时间:2023-3-26 17:59

举报

0个回答

所属标签

相似技术帖

官网相关资源

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