微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Keil创建新的STM32工程以及CortexM3的位带操作

Keil创建新的STM32工程以及CortexM3的位带操作

时间:11-19 来源:互联网 点击:
位带区地址(序号)……0x2 3.(7 ~ 0)0x2 2.(7 ~ 0)0x2 1.(7 ~ 0)0x2 0.(7 ~ 0)
位带区地址对应的内容.(7 ~ 0)……0 00 00101 10101010 0101
Reset(VarAddr, 11)之后0 00 0010100101010 0101
再Set(VarAddr, 11)之后0 00 0010110101010 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 00 00101 10101010 0101
Set(VarAddr, 31)之后100 0010110101010 0101
再Reset(VarAddr, 31)之后000 0010110101010 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

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top