【问题标题】:Accessing SFR (Special Function Registers) on a 32 bit controller访问 32 位控制器上的 SFR(特殊功能寄存器)
【发布时间】:2014-07-13 19:08:44
【问题描述】:

如何访问内存映射外设的 SFR(特殊功能寄存器)。

我如何确保编译器不会弄乱字节顺序?

例如,如何访问地址0x00080的32位寄存器,位是如何映射的?请不要羞于进入细节和低级。

【问题讨论】:

  • FWIW,目前还没有标签 sfr。我认为不应该仅仅为此而创建它。
  • 还有另一个提示:SFR Definitions。这似乎只对 Cx51 处理器有效。
  • sfrsfr16sbit 可能是特定于您的工具链和目标体系结构的编译器扩展,或者它们可能是在目标特定标头中定义的类型别名。无论哪种方式,您都可以很好地指定工具链和目标以获得任何有用的答案。在大多数架构上,SFR(或更一般的片上外设寄存器)和内存映射,因此访问就像访问任何其他内存一样 - 但必须声明为volatile。大多数目标没有位可寻址内存或 SFR - 8051 是这样的,但不是 32 位。
  • @Clifford 我试图简化我的问题。我的设备有内存映射外围设备。 TMR0(32 位)对应字节 0x80。如何访问此内存位置,以及如何处理字节序?
  • 关键问题:什么 CPU?如果没有这个重要的细节,任何回应都将是 WAG。

标签: c embedded


【解决方案1】:

大多数工具链或芯片供应商都会提供一个目标特定的头文件来支持这一点。但是,如果您需要创建自己的,那么您可以例如定义:

volatile uint32_t* TMR0_ADDR = 0x00080 ;
#define TMR0 (*TMR0_ADDR) ;

你可以直接分配TMR0:例如:

TMR0 = 0x80000000 ;

关于位是如何映射的,它们与内存一样(它们毕竟是内存映射的),所以 0x00000001 设置 LSB,0x80000000 设置 MSB。如果您想映射寄存器中的各个位域,那么您可以使用位域结构(而不​​是上面的uint32_t) - 但是位域结构的实现是特定于编译器的,因此您为一个编译器生成的目标特定标头可能不能移植给其他人。这就是为什么您应该尽可能使用工具链提供的标头。

【讨论】:

    【解决方案2】:

    这取决于您使用的编译器,许多编译器提供 at 关键字,可用于放置变量,然后可用于访问 sfr:

    volatile uint32_t sfrVariable _at_ 0x00080;
    sfrVariable = 0;
    

    如果您使用的是 GCC,它不允许您这样做,在这种情况下您将不得不使用:

    #define sfrVariable         (*(volatile uint32_t *) 0x00080) 
    sfrVariable = 0;
    

    默认情况下,编译器将运行 little-endian,但大多数情况下 uint 不会受到它的影响,因为它已经是 little-endian 类型。

    【讨论】:

      猜你喜欢
      • 2018-07-23
      • 2012-11-28
      • 2014-11-18
      • 1970-01-01
      • 1970-01-01
      • 2011-03-02
      • 1970-01-01
      • 2020-11-21
      相关资源
      最近更新 更多