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

基于STM32固件库语法的经验分享

[复制链接]
攻城狮Melo 发布时间:2023-3-26 18:27
查看固件库,里面有很多在通常的C语言教程中不常看到的语法内容,总结如下:8 E/ ^- X9 E; L$ T. G8 n
__I:其实是个宏定义,在core_cm3.h里面:! P& U4 z6 X& X! u
  1. [mw_shl_code=c,true]#ifdef __cplusplus9 J4 f2 ^- @  i3 L# b9 i" B
  2.   #define     __I     volatile                /*!< defines 'read only' permissions      */9 m* x: u' \7 p, {% \
  3. #else7 ~! d8 O$ Q  w2 q. ?1 d
  4.   #define     __I     volatile const          /*!< defines 'read only' permissions      */8 X' r' x; I; I- ^# U
  5. #endif( H6 h; J7 z. {: g
  6. #define     __O     volatile                  /*!< defines 'write only' permissions     */+ W- G4 V. B9 B' \+ a& M8 f7 _
  7. #define     __IO    volatile                  /*!< defines 'read / write' permissions   */
    2 f8 w6 f8 v# D7 g) z8 v. E: M/ i
  8. [/mw_shl_code]
复制代码

* s( M% U$ x* d6 Z( k8 Z0 h除了__I以外还有__O、__IO等等,都是volatile的别名,意思是要求编译器不作优化而直接读取变量的真实地址上的内容。
1 p  n( W( o) h: |1 r怎么优化呢?复杂,好比说iTempA = iTempB * 2,下一步如果使用到iTempA就会一直认为iTempB * 2的值就是iTempA的值,而实际上可能在其他地方iTempA被其他程序改变,所以如果使用到iTempA的话就不能认为是iTempB * 2而应该从iTempA的实际地址读取。
- k$ d" @# A2 R这只是类比,STM32是关于硬件的,iTempA如果被volatile修饰就应该读取它的真实地址内容不应该读取缓冲区内容。用书上的话就是“易失性”。
6 v; `! K' e4 U7 P& u. }从宏定义可以看出来,无论是__O还是__IO都是volatile,并无区别,这个只是给程序员看的,没有语法上的约束。唯一不同的是__I,是const,常量。) X2 G  P. f0 o/ b
不过具体怎么用呢?目前不得而知。
0 v$ o& s- O8 o" o1 X, Y-------------------------
" A) w) E( u! n6 u/ o) w库里面有一些很奇特的数据类型,比如uint32_t,uint16_t,虽然猜能够猜到是什么,不过具体是什么呢?& m3 _6 V; Y" z) ?6 _
使用Keil很容易找到定义处,在c:\Keil_v5\ARM\ARMCC\include\stdint.h里面定义。(可是我的项目中却没有#include这个头文件呀!!看来Keil调用编译器的时候自动包含的,Keil自带的include不是没用啊。)7 u" D$ h; O: L/ f
stdint.h里面定义了许多这样的数据类型,大多是C原生数据类型的typedef,理解为别名好了。# s* a  {  `* K$ ?4 V2 c* T
  1. [mw_shl_code=c,true]    /* exact-width signed integer types */
    ; m- r1 N% [6 l/ x( Q
  2. typedef   signed          char int8_t;: W4 y% g" J& f8 R. f
  3. typedef   signed short     int int16_t;
    1 Z1 Q9 J2 |9 v3 {
  4. typedef   signed           int int32_t;& a0 J: x$ V) e8 _$ T, s* G+ D
  5. typedef   signed       __INT64 int64_t;+ ^4 y. W+ B' a1 r2 g& }2 \) a

  6. 0 X! b7 _7 D7 H' h( L

  7. ) D8 X2 n7 N- r; n$ l& u( W
  8.     /* exact-width unsigned integer types */
    * Z8 f+ {+ p$ i, R( \# g
  9. typedef unsigned          char uint8_t;6 G# H% x6 T& W" N+ p, M# H- M
  10. typedef unsigned short     int uint16_t;+ H% o1 U& r4 s  E/ T
  11. typedef unsigned           int uint32_t;
    * K# S! r4 ?8 ?% j/ ?
  12. typedef unsigned       __INT64 uint64_t;! W% d/ O$ O( a: g( ^
  13. [/mw_shl_code]
复制代码

4 J  Q, g/ e2 s- o1 d$ F关于硬件的数据类型可能不会自动识别为int、float之类,这些都是需要使用者自己来识别来定义的,所以硬件的数据大多只和数据是存储在16bit还是32bit空间有关。
( K( N) `* F" g5 Q7 h3 G" n8位数据用C来定义就是signed char 或unsigned char ,而16位就是signed short int或unsigned short int,类似地,常用的寄存器是32位,就是unsigned int。
9 b' v1 S! p" m' X" j& }' t还是为了防止以后出现类型错误,减少编写出错几率。
% _2 ?+ J6 O5 f& j- d# D4 r-------------------------------------
7 w! D) K1 V1 |: K在stm32f10x.h中还定义了几个更精简的类型:vu32/vu16/vu8这类。
) V9 v: C% O  Z1 T9 a' T, B# C
  1. [mw_shl_code=c,true]typedef __IO uint32_t  vu32;
    & F0 r% `  a. _
  2. typedef __IO uint16_t vu16;
    ( U; o4 N) [( b: h$ \& c
  3. typedef __IO uint8_t  vu8;
    0 A7 }  r& |% A* Y7 O/ A
  4. [/mw_shl_code]
复制代码
% }, _; X) _- ]! {2 U" e! d/ w6 V$ V
这是在uint32_t的基础上加上了__IO修饰,定义了这么多,记忆是个问题。我现在的理解是:如果有__IO等修饰,那么就是从硬件读或写数据,不能用简单赋值。# @6 m+ X- T! x% h" k0 f. ~, [
————————————————
2 z& f6 O5 Q$ ~. x# _' y8 @; {版权声明:被大佬糊弄的只会点灯的小菜鸡. S5 f8 c$ n+ H1 S8 y' c
如有侵权请联系删除
1 N* B, S& ?" r4 ]1 y9 E% L4 u% W

& j5 Y/ N; s9 x, i9 }1 |
赞 收藏 评论0 发布时间:2023-3-26 18:27

举报

0个回答

所属标签

相似技术帖

官网相关资源

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