指针变量,位带指针,LSB最低有效位······

置顶公众号,不错过每一条消息!


上一篇文章【STM32位带操作】牵涉到的内容相对比较多,后台有许多朋友也问了很多相关的问题。不知道那些问过的朋友下来有没有总结,其实那些问题都是一些基础问题。


主要内容:

1.指针变量及例子

2.指针变量---位带操作

3.位带别名区最低有效位

4.位带操作另一种宏定义


1指针变量及例子

前面文章【STM32位带操作】牵涉到的一个重要知识点就是指针变量


这种位带映射操作,就是操作映射过后的地址,其实就是操作指针变量


指针变量:指存放地址的变量

指针变量是一种特殊的变量,它不同于一般的变量,一般变量存放的是数据本身,而指针变量存放的是数据的地址。《摘自百度百科【指针变量


指针变量的例子

int main(void)
{
  uint32_t *p;

  p = (uint32_t *)(0x42210184);

  System_Initializes();
 while(1)  {    *p = 0;    TIMDelay_Nms(500);    *p = 1;    TIMDelay_Nms(500);  } }

上面例子中给p指针变量赋的值是“0x42210184”,只是强制转换成(uint32_t *)这种指针类型


而*p = 0;代表该地址上的数据值为0;也就是上面说的该地址存放的数据为0


前面有一个朋友问过我关于指针变量的问题,看到这里,相信你应该知道使用指针变量,直接打印指针就可以判断指针是否越界。


2指针变量---位带操作

上面代码中0x42210184”代表STM32F103系列芯片中PA1的位带别名地址(就是映射过去的地址),截一个图,大家看看:


提示:上图中对p的赋值,其实是一样的(在STM32中),都是0x42210184。


结合公式理解

上一篇文章STM32位带操作】列出了关于片上外设区计算公式:

AliasAddr = 0x42000000+(A-0x40000000)*32 + n*4

对比截图中第一个p赋的值,就是片上外设的计算公式。

第二个p只是对代码优化了:“&”到“-”的优化,可以看编译器相关手册。


第4个p就是上一节代码中值,有没有发现,位带操作其实就操作指针变量啊?


这样相比读出寄存器,再&或者|再写入寄存器的效率要高多啦?


3位带别名区最低有效位

有朋友发现,*p = 0;这样操作对地址0x42210184(PA1输出写入0,PA1输出低。假如我写入0x10,那么PA1输出多少呢?


答案:输出低。


原因在于:在位带区中,每个比特都映射到别名地址区的一个字只有 LSB 有效,也就是最低一位有效。


4位带操作另一种宏定义

有通过昨天的两个公式,可以推出下图的公式:


上面框起来的定义适合RAM和外设两种,假如定义一个LED为PA1,只需要将PA1相关参数传入即可。


LED另外一种定义:

#define LED BIT_ADDR((GPIOA_BASE + 12), 1)


这种定义需要注意:+12,其实是ODR相对GPIOA的基地址的偏移地址。


我曾在这里遇到的坑:我将STM32F1的移植到F4上,出现了问题,我找了半天才发现由于这个偏移地址不一样导致的。


STM32F1的ODR偏移是12,而F4的ODR偏移是20。所以,建议大家使用GPIOA->ODR这种方式。(不管是标准外设库还是HAL库都有这样定义)。



推荐阅读

1.IAR在线调试查看各种变量的不同方法

2.解读STM32位带操作


5最后

若觉得文章对你有帮助,记得点赞、分享。扫描下面二维码、关注,在底部菜单中查看更多精彩内容!

长按识别图中二维码关注



赞赏是对作者的认可与支持!