TA的每日心情 | 开心 2022-12-9 15:13 |
---|
签到天数: 10 天 [LV.3]偶尔看看II
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本帖最后由 Heaven_1 于 2022-3-3 18:59 编辑 3 F1 M/ c8 [3 D
* e( c. J1 f# W# q5 v( j
为了像51单片机一样能够对某个管脚单独操作,引入了位带操作这样的操作机制。
; K9 c( h* \1 E
% h4 ^2 ^& `: b; w, k, H如下图,位带(Bit band)区就是就是你想单独操作的IO的区域,比如PA1、PA2。而位带别名区就是你给每一位重新起了个名字的那一片地址区域。可以看下表,M3内核存储器映射表,你能看到1M内存的BitBand区,还有与之对应的32M内存的BitBand别名区,因为你将每一位膨胀成为了一个32位的地址,所以相应的别名区的内存也会是位带区的32倍。: W0 d. x6 H" s y# n d, o
! l2 z ~, r$ `# M
+ M: v5 H! ]3 U1 T2 k/ K# d! C0 H
想进行位带操作,应该先去找该位对应的别名区的地址,找到了这个地址,对这个地址进行操作,那么实际上也就是对该位进行操作了。; v' H2 v/ ^% G0 m
3 v; B# [& k# T W2 b官方给出了如下相应的计算公式:
. O+ P/ K3 P& f/ F- @ L$ @- d
4 v; O' S2 E' V# \" fAliasAddr. n7 ^7 K) U2 ? H. a/ I+ t9 K
+ {3 \$ T' R. W9 Q=0x42000000+((A‐0x40000000)*8+n)*4. Y& o) L" S) \' t+ _% r+ o
4 N3 c* s% f r$ q" w; ^=0x42000000+ (A‐0x40000000)*32 + n*4
" n) i5 G- M! U8 y, s0 {4 V( Q7 a# P; Z7 |
其中,AliasAddr是别名区的地址,A是GPIOA->ODR的地址,n是该端口的上的某一位。
* A# t- ^6 A7 ^: Z' E
' }2 r( ^% c1 S6 b1 c' Q2 T0x42000000是位带别名区域的起始地址,A是输出数据寄存器GPIOA->ODR的地址,A的地址先减去位带区基地址,得到的是相对于位带区基地址的偏移地址,那么膨胀之后还是一个偏移地址,是相对于位带别名区基地址的偏移量,加上位带别名区域基地址,就得到了其对应的别名区地址。
( R% P& R8 I; x1 K. F! }* W: r0 {# O$ x. t T7 n1 {* \$ k
多数情况下,大家见到的代码,应该是以下这个样子,一共分为三步:
+ W+ X" r: U9 d v* H. F& y& B$ B; A' K" I. F! y
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
& z8 b1 X, G# x
+ Q$ P. Q! n" D#define MEM_ADDR(addr) *((volatile unsigned long *(addr)): W7 o/ D3 U5 ?9 p! L
$ w! Y& s3 M) Y" E#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
3 Z5 Z @2 a4 {
/ p# c* l' y! Y+ w5 G. v第一步,就是我们上面分析的,得到位带别名区域的32位地址。 x! Q2 o$ E! V! ?9 b) O
9 i0 q8 R, H4 d6 e) r* A6 n* y
第二步,就是将第一步得到的32位地址,给转换成一个指针变量,并且操作这个地址里的值,唯一的区别,就是由于安全的考虑,多加了一个volatile 这样的关键字。3 V9 I2 Q. {2 ?) R3 N* [
" n! ?7 X2 I% J& l2 G+ k" G& f举个例子, t9 z. M4 Z1 Y2 L
0 Z9 X/ G8 n1 _: P: J9 \+ I4 v
如下,想直接访问0x00000001这个地址,并且给这个地址写1,该怎么做呢?7 D! {" ^" k( J. g
6 X% r7 I3 L/ n# F; K/ T: U# define ADDR 0x00000001! @$ c7 Y) }9 o1 b
$ f: `3 K+ J! b v7 p, j6 l4 [
*(int *)ADDR = 1;' q1 [6 j+ i& w& V4 z
: f! N* P5 l7 s; c, h4 t
第三步,就是将前两部,结合在一起,根据传入的addr和bit计算得到32位的地址,然后强制类型转换,使得我们可以去操作这个地址里的值。: j6 S9 B: P* _- x* F
5 e; b' U7 ]9 X/ y
提示:bitnum<<2相当于bitnum2乘以4,位运算相关文章:C语言操作寄存器的常见手法,实际上在计算机底层乘法也是基于位运算实现的。+ t3 l3 l0 Q, F+ t
6 r# C2 l' m) G7 G9 J- D7 f9 t* k5 ?: P
" e# t7 ]! R4 W6 N0 }3 a; F
9 f; A9 q* ^9 a' D6 v N
|
|