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

STM32 位段详解

[复制链接]
STMCU-管管 发布时间:2020-9-8 09:59
: h" ^  T- d0 n9 |# Z
1 定义
首先需要明确下,位段,位带和别名区这三个名词
- [# T4 L% ]4 m; I; `/ k
名词定义

& ~) j- U" S3 E0 S
位段
' d) ~) `! U+ o# S8 H. A8 s
STM32用户参考手册使用的名字

; Z6 }8 \4 R3 _" O& _
位带
$ U0 {& ^* c% o* J, Y
CortexM3参考手册使用的
+ V( n' l# w7 s$ n- |+ j
别名区
$ r2 E3 ~7 X- F* l) q8 ^. u  `
地址总线上用来位访问地址区域,

% ]5 h, h7 F" i3 u7 O
所以说,位段和位带是一个意思,是不同手册的不同叫法。

0 j5 z- ?  D* b# L. U& G
由上述的名词解释得知,位带功能并不是STM32独有的,是CortexM3的功能(CortexM4也有这样的功能)。MCS51有位操作,以一位(bit)为数据对象的操作,MCS51可以简单的将P1口的第2位独立操作:P1.2=0;  P1.2=1 ;这样就把P1口的第三个脚(bit2)置0置1。而STM32的位段、位带别名区最重要的就为了实现这样的功能。
. l- D, e" X! H% Y! @3 s6 |

( X6 p6 E/ R7 `4 v8 P2 位带操作
( M9 m2 @9 _; ^" i
2.1 范围

3 I5 c9 [8 w  j
位带是有范围的,并不是CortexM3全部地址空间都支持的。在 CM3中,有两个区中实现了位带。其中一个是 SRAM 区的最低 1MB 范围,第二个则是片内外设区的最低 1MB 范围。这两个区中的地址除了可以像普通的 RAM 一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个 32 位的字。当你通过位带别名区访问这些字时,就可以达到访问原始比特的目的。
支持位带操作的两个内存区的范围是:
$ S1 `/ R6 f) V3 a

( L  o: E" P# d1 c3 `+ P- L7 n# K+ {' W; B( X% O! l- k% L9 g
0x2000_0000‐0x200F_FFFF(SRAM 区中最低1MB区域)

) L; q9 C! ?7 ~' b/ z5 n
0x4000_0000‐0x400F_FFFF(片上外设区中的最低 1MB)
) _$ ]8 N# ?, g
2.2 位带操作
: D, n, `( j* S) H! @, A
对 SRAM 位带区的某个比特,记该比特所在字节的地址为A,位序号为 n (0<=n<=7),则它在别名区的地址为:
# g; ^/ D& c8 ]" w# m  ~, k3 J
  1. AliasAddr = 0x22000000 + ((A‐0x20000000)*8+n)*4 =0x22000000 + (A‐0x20000000)*32 + n*4
复制代码

- C$ o( _4 D; z- b3 `0 i0 _5 e! t
对于片上外设位带区的某个比特,记该比特所在字节的地址为A,位序号为 n (0<=n<=7),则该比特在别名区的地址为:
  1. 2 h7 [& V6 a; K" n# v) g5 Y3 q! O
  2. AliasAddr = 0x42000000 + ((A‐0x40000000)*8+n)*4 = 0x42000000 + (A‐0x40000000)*32 + n*4
复制代码

) w  b% `' Y& \4 M# J9 t
上式中,“*4”表示一个字为 4 个字节,“*8”表示一个字节中有 8 个比特。
1.png
2.3代码实现
把“位带地址+位序号”转换别名地址宏为:
  1. #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000 + ((addr &0xFF FFF)<<5) + (bitnum<<2))
复制代码
. v+ {' t2 v& ?, [# q& [  d" v
把该地址转换成一个指针:

  1. ) F0 y9 D+ R/ {$ e# T! [! E3 Z4 P
  2. #define MEM_ADDR(addr, bitnum) *((volatile unsigned long *)((addr & 0xF0000000)+0x2000000 + ((addr &0xFF FFF)<<5) + (bitnum<<2)))
复制代码
6 v- e! A8 P) q  E/ f0 d
其中
8 o# n8 d) K+ Z( L8 l
5 q* k7 G+ N" e5 q8 p1 H! Q8 E" ]; W
addr的取值范围:

0 x* o( b  n% k) l+ j
0x2000_0000‐0x200F_FFFF
0x4000_0000‐0x400F_FFFF
注意:addr取值要32位对齐

% B% t' T! `. {/ J
bitnum的取值范围:
0-31

9 ?) E! K& ]5 g" u3 Y
解析:
$ G5 ~' o; g; J  y

' d3 M) }& U; t2 x: W) b& ]8 E
(addr & 0xf0000000) + 0x02000000:
区分SRAM还是外设,如果是外设,结果为4,再加0x2000000就等于0x4200000,0x42000000就是外设别名位带区。如果是SRAM,结果为2,再加上0x2000000就等于0x22000000,0x22000000就是SRAM别名位带区。
2 @, Q, B4 J4 j2 {
addr & 0x00ffffff:
屏蔽了最高2位,相当于减去0x20000000或者0x40000000。因为位带区的有效范围是1M,即0x100000,这样子就做到了低6位有效。

* ~& s; ]# i) ~3 G/ B+ I7 g/ u
<< 5:
等价于乘以32
7 p; p3 f. p( ]$ B' v
<< 2:
等价于乘以4

/ u& ^  s( d4 K9 D' V7 s
特别提醒

3 K- n" z6 g" R
当你使用位带功能时,要访问的变量必须用 volatile 来定义。因为 C 编译器并不知道同一个比特可以有两个地址。所以就要通过 volatile,使得编译器每次都如实地把新数值写入存储器,而不再会出于优化的考虑。5 t! u1 W. a* A; J5 e4 `% e* r

  u! f* k1 \2 k$ Z( g5 m9 Q
7 Z2 _6 M& y% Z( [3 位段的优点, T* T% C2 C% k1 H
最容易想到的就是通过 GPIO 的管脚来单独控制每盏 LED 的点亮与熄灭。另一方面,也对操作串行接口器件提供了很大的方便(典型如 74HC165,CD4094)。位带操作可以把代码缩小, 速度更快,效率更高,更安全。总之位带操作对于硬件 I/O 密集型的底层程序最有用处了
8 s. G4 p% @9 S) y5 x6 M8 h. v
位带操作还能用来化简跳转的判断。
* h3 P: G, Y" P6 P
当跳转依据是某个位时,以前必须这样做

' K7 X7 M+ y  M1 M# U4 C( Y* z& @7 W1 W
1、读取整个寄存器

& H  P6 T6 R& v% O( J' l0 H
2、掩蔽不需要的位

1 D5 x8 o4 p$ D) h: h  R- {
3、比较并跳转

- b( L: Z$ p+ C; x* ]% q6 N

$ }* K. \- ^0 r* Z0 z2 p
使用位带操作后
- O' s6 x4 n1 i" D  \9 e  }
* O/ V% v6 c# d' j1 k/ |* z' V
1、从未带别名区读取状态位
( s  H# a, m' s! t7 g( P4 m9 y
2、比较并跳转
2.png

& T/ q+ a' s. e- {! ^
当然,对于写入操作也从4步精简到3步
3.png

7 k9 h) O+ v( A9 P' i& h( {, D9 V* X

, W5 [8 \" G) L: z7 ^1 c
赞 收藏 1 评论0 发布时间:2020-9-8 09:59

举报

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