【问题标题】:Why use 2 pointers to point to register address in atmega microcontroller?为什么使用 2 个指针指向 atmega 微控制器中的寄存器地址?
【发布时间】:2017-07-26 09:18:24
【问题描述】:

这一行定义了 avr 微控制器中 DDRD 寄存器的地址

#define myDDRD *((volatile unsigned char* const) 0x31)

能否请您澄清一下在上述行中如何使用指针? 为什么我们需要第一个星号?第二个不应该足以指向地址 0x31 吗?

【问题讨论】:

  • 它是一个 const 指向 volatile unsigned char 的指针。如果您只是在阅读方面需要帮助。
  • 星号* 在不同的范围内可以表示不同的东西。如果用作二元运算符,它可能意味着乘法。这可能意味着指针用于类型(如类型转换(volatile unsigned char* const))。或者,如果用作一元运算符,它可能意味着 取消引用指针(这是使用“第一个”星号发生的情况)。
  • @user247954 这是一个外部资源。但有人已经为您完成了这项工作。
  • @AjayBrahmakshatriya 我明白了,但第二个星号不应该足以定义这个指针吗?为什么我们需要 2 个星号?
  • 它没有将宏定义为地址。该宏在代码中被左值替换。

标签: c pointers avr atmega avr-gcc


【解决方案1】:

您可以将*((volatile unsigned char* const) 0x31) 分成两部分:
一个内部:(volatile unsigned char* const) 0x31
和一个外部部分:*( inner part )

内部将整数 0x31 转换为常量 volatile unsigned char 指针。
指针类型由类型名称和类型名称后的星号组成:type*。要转换表达式括号,请使用 (type)expression

外部部分取消引用指针包含的地址,因为它前面有星号:*pointer,以便访问它的值。

如果我们只取内部部分,为什么从地址读取和写入是不够的?

想象一个指针int* intPtr 已经指向一个有效的整数。如果您现在想要更改该整数,您必须通过*intPtr = 42; 来完成。如果您改用intPtr = 42;,则将 42 写入指针值而不是它指向的地址,因此 42 将是指针包含的新地址。

简而言之:
宏从地址 0x31 中读取一个字节 (unsigned char),如果它位于分配的右侧,则向它写入一个字节,如果它位于左侧。

用法:
一个典型的用法是在位于特定地址的寄存器上进行位操作,例如清除或设置单个位:

myDDRD &= ~(1 << PD0); /* clear bit 0 as PD0 is defined as 0 */
myDDRD |= (1 << PD1);  /* set bit 1 as PD1 is defined as 1   */

有关位操作的更多信息,请参见此处:How do you set, clear, and toggle a single bit?

【讨论】:

  • 它也可以用于写入到地址,如果用作赋值的 lhs。
  • 如果我们只取内部部分,为什么从地址读取和写入是不够的?
  • @user247954:因为它只是指向地址的指针。要访问该特定地址,您必须取消引用它。例如,如果您有一个 int* intPtr 并且将由 intPtr = 42 使用它,您会将 42 写入指针值而不是指针包含的地址。
  • @AndreKampling 好的,我明白了。感谢您的清晰解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-12
  • 1970-01-01
  • 1970-01-01
  • 2021-06-10
  • 1970-01-01
相关资源
最近更新 更多