Keil创建新的STM32工程以及CortexM3的位带操作
位带区地址(序号) | …… | 0x2 3.(7 ~ 0) | 0x2 2.(7 ~ 0) | 0x2 1.(7 ~ 0) | 0x2 0.(7 ~ 0) |
位带区地址对应的内容.(7 ~ 0) | …… | 0 0 | 0 0 | 0101 1010 | 1010 0101 |
Reset(VarAddr, 11)之后 | 0 0 | 0 0 | 01010010 | 1010 0101 | |
再Set(VarAddr, 11)之后 | 0 0 | 0 0 | 01011010 | 1010 0101 |
BitNumber=0,Reset得到的结果是把第一个地址的.11位(第12位)变成了0,Set后又回到了1。从这里这里看到,当要改变下一个地址中的内容时,不是用VarAddr+1,而是用更大的BitNumber,即n不限制在0~7,而是0~31,或者更大。这样又出现了一个问题:之前说到的
( RAM_BB_BASE ( (VarAddr - RAM_BASE) < 5) ( (BitNumber) < 2) ) = 转换公式的右边
前提之一是 n=0~7,即只与低位的0按位或,这样才和加法是等效的。
结合2.2.1最后提到的问题,其实这也是一种等效。当BitNumber > 7 时,可以看成是一次进位。
假设VarAddr = 0x2 0 ,当BitNumber = 7, 则指的是 0x2 0.7 即第1个地址的第8位
当BitNumber = 11 = 7 + 4 ,相当于VarAddr+1,指的是0x2 1.3 即第2个地址的第四位
因此BitNumber 和 VarAddr就像个位和十位的关系一样,不过是逢八进一。而且这样做有个好处,只需要改BitNumber就行,而不需要同时改BitNumber和VarAddr,比如在Var_ResetBit_BB(VarAddr, BitNumber)函数中不用Var_ResetBit_BB(VarAddr+1, BitNumber)了,而是直接根据需要,修改BitNumber就行。
另外,在Set以后也可以看到,VarBitValue变成了1(即只有一个字中的最低位变成了1)。
(3)
1 /* Modify Var variable bit 31 --*/2 Var_SetBit_BB(VarAddr, 31); /* Var = 0x85AA5 = 0x1 0 0 0 0101 1010 1010 0101 */3 printf("VAR=0x%x",Var);4 5 /* Get Var variable bit 31 value */6 VarBitValue = Var_GetBit_BB(VarAddr, 31); /* VarBitValue = 0x01 */7 printf(" Bit31=%x\n",VarBitValue);8 9 //******************************************10 Var_ResetBit_BB(VarAddr, 31); /* Var = 0x05AA5 = 0x0 0 0 0 0101 1010 1010 0101 */11 printf("VAR=0x%x",Var);12 13 /* Get Var variable bit 31 value */14 VarBitValue = Var_GetBit_BB(VarAddr, 31); /* VarBitValue = 0x00 */15 printf(" Bit31=%x",VarBitValue);
位带区地址(序号) | …… | 0x2 3.(7 ~ 0) | 0x2 2.(7 ~ 0) | 0x2 1.(7 ~ 0) | 0x2 0.(7 ~ 0) |
位带区地址对应的内容.(7 ~ 0) | …… | 0 0 | 0 0 | 0101 1010 | 1010 0101 |
Set(VarAddr, 31)之后 | 10 | 0 0 | 01011010 | 1010 0101 | |
再Reset(VarAddr, 31)之后 | 00 | 0 0 | 01011010 | 1010 0101 |
结果和(2)中得到的结论相符。
2.2.3
到这儿基本上把位带操作及其实现的基础部分写完了,最后再来一发从位带别名区地址反推回位带区地址的过程,备忘。
假设 AliasAddr = 0x2200 002C = 0010 0010 0 0101 0 0 0010 1100
可以把AliasAddr分成3段,1[0010 001] 2[0 0 0101 0 0 001] 3[0 1100]
第1段,在后面补上25个0,可以看成是位带别名区的起始0x2200 0
第2段,就是offset=VarAddr - BB_Base ,也即相对位带区的偏移0 0 0101 0 0 001 =0 0010 1 0 1 = 0x02801
第3段,右移两位后就是BitNumber啦 右移后得到011 = 3
这样可以得到相应的位带区 地址.位 是 (0x2 0 + 0x0 2801) . 3= (0x2 2801) . 3
再加一点内容吧,关于内存对齐,来自C语言吧
如果你了解体系结构,就会知道,计算机内存寻址并不是一个字节一个字节读取的,而是一次读取多个,比如32bit数据线的计算机就可一次读取4字节,既一个int值.这时就出现问题了,比如你在结构体中定义如下:
struct a{
char c;
int i;
}
那么计算机在内存中该如何存放呢?
比较笨的办法是c占第一个字节,i占用2-5字节.那么假设你的程序正好处于寻址边界,比如0x0这样的位置,那么计算机为了获取i,就必须先获取1-4字节,然后左移8位,再获取5-8字节,右移24位,然后再相加,才能得到i,无意这种办法是比较傻的.所以计算机在处理这种问题的时候,往往会将内存按4字节对齐,比如c占用第一字节,i占用5-8字节.这样i就和c在4位上对齐了.相当于我们写字一行不够了,干脆就不写在一行,直接重起一行.主要是方便寻址,提高性能.
】
没想到写这篇博客花了这么长时间,对于位带操作及其实现的认识也是反反复复,写的时候再一思考发现部分原来的理解是错误的。
如果还有其他错误,还希望读到这一篇文章的你能够帮忙指正,也帮助我学习 :)
参考资料:1http://www.cnblogs.com/emouse/archive/2012/03/01/2375146.html
2http://blo
KeilSTM32工程CortexM3位带操 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)