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

【经验分享】STM32固件库文件编程结构思想的理解

[复制链接]
STMCU小助手 发布时间:2022-1-30 01:00
STM32的固件库文件功能相当完善,提供的API完全能满足一般的项目需要。刚从51单片机转到STM32的人,肯定会被这么庞大的东东吓到,51单片机上对IO口操作,简简单单几行代码就搞定了,一个C源文件就搞定。假如用STM32,对IO口进行简单操作,远不是几行代码能搞定的。(其实直接操作寄存器也能搞定)。
   废话不多说,这就带你解剖固件库文件,包你看完之后豁然开朗。
   首先,请看一段简单的C语言代码
  1. #include <stdio.h>
    ; z0 V* L: b+ Z8 o% S
  2. 1 D: w  i1 |* H  S. ^, S, B% t! C
  3. #define base  0x0012ff609 }* b7 L8 U( y' M
  4. #define flash ((TestType *)base)' y) I7 o$ o+ t2 k! M
  5. % c, V" K1 h9 B  b- F& H; \

  6. 1 z/ K5 H% Y  [9 c  x
  7. typedef struct
    6 o3 M8 `' R& i4 L. v
  8. {
    & G  U! c0 y8 r
  9.       int i;
    9 Q0 ^2 f* l" m: P
  10.       int j;
    ' A* P, S1 P/ c  |% N: O' [
  11.       int k;
    % x: E: u( T$ n) b7 `4 O( ]
  12. }TestType;0 ?; r1 Y7 Z0 y
  13. ( ^- F+ n( P9 c7 e4 [1 W! u
  14. void main()9 ~2 A3 V: B  l: j7 {4 L: q7 _
  15. {
    + Q7 A6 I4 L! c
  16.        flash->i = 0;
    - _( K1 I7 P) c: B
  17.        flash->j = 1;8 s% F7 r& |; _& ~9 B$ q/ e
  18.        flash->k = 2;( s+ [* \; p% x/ P; c" E0 m
  19. ' @5 i9 g4 w- C9 q2 u" c
  20.        printf( "%x \n", flash->i);
    ( d6 w5 H0 C1 a/ P& Y$ C
  21.        printf( "%x", &(flash->i));# N% G& Z& |& e5 P
  22. }
复制代码
. c0 ~; Q, L2 l4 C3 C
有人会问了这段代码有什么用?我告诉你ST的固件库都是按照这种方式编写的
上面程序打印出来结果为   0
                                  0x0012ff60
把上面的程序分析几分钟后,我再给你揭晓。就拿GPIOA口来说吧,你看stm32f10x.h中能看到
  1. #define PERIPH_BASE            ((uint32_t)0x40000000): Q: i0 W( G# [7 P7 E/ }! A
  2. #define  APB1PERIPH_BASE                 PERIPH_BASE
    & B. }9 R. R5 O0 `  F* {! i2 J" b
  3. #define APB2PERIPH_BASE     (PERIPH_BASE + 0x10000)7 ]/ k/ w: v+ v$ K1 d
  4. #define AHBPERIPH_BASE       (PERIPH_BASE + 0x20000)/ K4 [8 z  B$ l& w1 D1 i% k
  5. #define GPIOA_BASE             (APB2PERIPH_BASE + 0x0800)
复制代码
* f+ S& a: ?2 t5 k5 x
小学学的加减法就能把GPIOA_BASE 算出来,为什么是这么多呢?看ST的手册,人家就是要规定这样,没办法。
有了地址之后,GPIOA的各个寄存器怎么办涅,它们是控制IO的关键所在。GPIO的各个寄存器都是连续排列的,为什么要连续排呢,方便找啊,用结构体就能很好搞定了
在stm32f10x.h中
  1. typedef struct
    * W0 l) K) V6 P$ a4 t( L* p
  2. {( M; v% l- A# {1 l" k* \( n( \
  3.   __IO uint32_t CRL;: |5 M. u* K( a- a9 Q2 S
  4.   __IO uint32_t CRH;) F, y$ f! H& l" |& |# w* @
  5.   __IO uint32_t IDR;
    6 H4 f% D. j2 k4 v! ^( i- `
  6.   __IO uint32_t ODR;2 N6 i4 j* \$ h. c2 b" x9 @) W
  7.   __IO uint32_t BSRR;
    0 R5 Q. V: A) Q
  8.   __IO uint32_t BRR;
      r; _) c; A+ l' |5 |
  9.   __IO uint32_t LCKR;% ]6 z/ _) M* _
  10. } GPIO_TypeDef;
复制代码

) Q. e( i# h/ [5 u8 R
每个寄存器都是32位的,所以很方便用结构体寻找每个寄存器,准备工作都做好了,接下来就要开始针对GPIOA设置了
在core_cm3.c中
  1. #define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)
复制代码

, ]+ @3 `- _0 r  ~
把地址强制转换成结构体指针,这样就能很方便对寄存器操作。
寄存器搞定了,接下来就真对用户操作了,要很好的让用户使用,就得人性话点,所以用enum枚举变量就能实现,你就再也不用为想输入的值去烦恼了,直接输入名称就行了,拿IO口的输出速度来说
  1. typedef enum
    # K6 x! r! g0 ?8 E* |
  2. {
    7 J, H9 n' b9 @6 b1 V
  3.   GPIO_Speed_10MHz = 1,7 ^. o* F0 z: Q1 |
  4.   GPIO_Speed_2MHz, , G" h3 Z# M' [0 P
  5.   GPIO_Speed_50MHz. b; C1 J8 [! A
  6. }GPIOSpeed_TypeDef;
复制代码

: f6 q3 `% y, Q1 C8 l
要说人性化,ST还有一点不得不提,那就是位带操作,改变了 写地址-取地址数据-位操作-数据写入地址的操作,直接改为写地址-数据写入
,直接位操作。
ST的编程结构是很值得借鉴的,使得编程序时结构很清晰,脉络很清楚。至于如何去发挥,得看个人水平了
7 D* W. J6 x1 H
收藏 评论0 发布时间:2022-1-30 01:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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