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

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

时间:11-19 来源:互联网 点击:

(*(__IO uint32_t *) (RAM_BB_BASE ((VarAddr - RAM_BASE) < 5) ((BitNumber) < 2)) = 0)

这一行第一眼看去不明觉厉。。需要仔细想想。把Var_ResetBit_BB 定义成这样一个函数,它的两个参数是(VarAddr, BitNumber)

//用这种形式表示

void Reset(VarAddr, BitNumber){

首先是 (RAM_BB_BASE ((VarAddr - RAM_BASE) < 5) ((BitNumber) < 2))  假设得到的结果是A

然后是 (__IO uint32_t *) A  这是强制类型转换,即把A 的类型转换成__IO uint32_t的指针,假设结果是B,即B =(__IO uint32_t *) A

接下来 * B  即取 B的内容,假设C = *B

最后是 C = 0

}

接着再来具体分析一下函数里面的过程,也就是转换公式的实现部分( RAM_BB_BASE ( (VarAddr - RAM_BASE) < 5) ( (BitNumber) < 2) )

VarAddr对应于公式中的 Addr ,BitNumber 对应于 n

(1) 首先,二进制数左移n位,就相当于乘以2的n次方(D),因此

(VarAddr - RAM_BASE) < 5 就相当于(VarAddr - RAM_BASE) × 32 ,(BitNumber) < 2相当于(BitNumber) × 4

对照转换公式可以发现两者很像了,如果 按位或 和 公式中的 + 在这里能得到相同的结果,那么这个函数就可以用了。下面来看看是不是这样。

(2)

RAM_BB_BASE=0x2200 0,转换成二进制就是

0010 0010 0 0  0 0 0 0

由于低25位全都是0(加上一个数肯定不会产生进位),因此 与一个数相加 和 与一个数按位或 的结果是一样的(但是 或 更快),当然这个数不能超过25位。

而位带区地址最多是0x2 0开始的1MB=2^20范围,也就是VarAddr-RAM_BASE涉及到的范围是在0x00 ~ 0xFFFFF,也即

0  0 0 0 0  ~  1  1 1 1 1 (20位) 

左移5位后也就是最多25位,因此符合上面的条件,按位或和加法等效,不存在进位问题,精妙的设计!

每一个序号(地址)对应的内存中有8位,也就是说BitNumber范围是0~7 (0 ~ 0),左移2位后是 00 ~ 00,不超过VarAddr-RAM_BASE左移5位  后多出来的0,因此也符合条件,按位或和加法等效。

因此( RAM_BB_BASE ( (VarAddr - RAM_BASE) < 5) ( (BitNumber) < 2) ) = 转换公式的右边

再回到(*(__IO uint32_t *) (RAM_BB_BASE ((VarAddr - RAM_BASE) < 5) ((BitNumber) < 2)) = 0) ,在刚才假设的那个void Reset(VarAddr, BitNumber) 函数中,A(或者说是B)代表变量在位带别名区的对应地址(序号),C=*B,也就是取内容,即取这个序号的内容(其实是由此开始的4个序号,即 32位 )。

若要Reset,则C = 0,若要Set 则 C = 1(不用 =31,因为该字只有最低位有效)。由此实现了:若要对位带别名区的地址(序号)中的内容进行复位/置位(其实是写一个字进去),就可以改变位带区中对应的地址中的某一位的值(比如),而这个位带别名区的地址只需通过VarAddr = (uint32_t)&Var得到在位带区中的地址,并把要改动该地址中的哪一位(BitNumber)一起作为参数给 Reset /Set 函数即可 的功能。而GetBit则是到*B为止,即return位带别名区地址的内容(32位)。

但是现在有个问题:VarAddr = (uint32_t)&Var只是从Var的开始地址算起,Offset = VarAddr - BB_BASE已经固定了,无法转到下一个字(n=0~7),这要是Var这个变量过大,那不就够不着对应的位带别名区了。。?

2.2.2

结合代码中调用这几个“函数”的部分来看,会有进一步发现。

//Var = 0x05AA5;

//VarAddr = (uint32_t)&Var;

(1)

1  /* Modify Var variable bit 0 --*/2   Var_ResetBit_BB(VarAddr, 0);  /* Var = 0x05AA4 = 0 0 0 0  0101 1010 1010 0100 */3   printf("VAR=0x%x\n",Var);4 5   Var_SetBit_BB(VarAddr, 0);    /* Var = 0x05AA5 = 0 0 0 0  0101 1010 1010 0101 */6   printf("VAR=0x%x\n",Var);

位带区地址(序号)……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, 0)之后0 00 00101 10101010 0100
再Set(VarAddr, 0)之后0 00 00101 10101010 0101

BitNumber=0,Reset得到的结果是把第一个地址的.0位(第1位)变成了0,Set后又回到了1。

(2)

1   /* Modify Var variable bit 11 --*/2    Var_ResetBit_BB(VarAddr, 11);             /* Var = 0x052A5 = 0 0 0 0 0101 0010 1010 0101*/3    printf("VAR=0x%x",Var);4  5    /* Get Var variable bit 11 value */6    VarBitValue = Var_GetBit_BB(VarAddr, 11); /* VarBitValue = 0x00 */7    printf(" Bit11=%x\n",VarBitValue);8 9    //******************************************10    Var_SetBit_BB(VarAddr, 11);               /* Var = 0x05AA5 = 0 0 0 0 0101 1010 1010 0101*/11    printf("VAR=0x%x",Var);12  13    /* Get Var variable bit 11 value */14    VarBitValue = Var_GetBit_BB(VarAddr, 11);    /* VarBitValue = 0x01 */15    printf(" Bit11=%x\n",VarBitValue);

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

网站地图

Top