良许Linux教程网 干货合集 STM32位带引申的指针变量问题

STM32位带引申的指针变量问题

之前发布的《Cortex-M位带操作的原理》一文中介绍了位带操作的概念和应用。尽管现在位带操作不再常用,但其中包含了许多值得学习和了解的知识点。

其中一个重要的知识点是指针变量。通过位带操作,我们可以对映射后的地址进行操作,这实际上就是对指针变量(存储地址的变量)进行操作。

指针变量是一种特殊的变量,它与一般变量不同。一般变量存储的是数据本身,而指针变量存储的是数据的地址。以上内容摘自百度百科【指针变量】。

指针变量的例子

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的位带别名地址(就是映射过去的地址),截一个图,大家看看:

image-20230812202644244
image-20230812202644244

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

结合公式理解:

之前文章《位带操作原理》列出了关于片上外设区计算公式:

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

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

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

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

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

3位带别名区最低有效位

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

答案:输出低。

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

4位带操作另一种宏定义

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

image-20230812202636463
image-20230812202636463

上面框起来的定义适合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库都有这样定义)。

以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !

137e00002230ad9f26e78-265x300
本文由 良许Linux教程网 发布,可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。
良许

作者: 良许

良许,世界500强企业Linux开发工程师,公众号【良许Linux】的作者,全网拥有超30W粉丝。个人标签:创业者,CSDN学院讲师,副业达人,流量玩家,摄影爱好者。
上一篇
下一篇

发表评论

联系我们

联系我们

公众号:良许Linux

在线咨询: QQ交谈

邮箱: yychuyu@163.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部