1

有注册地址(第一个?)SPI1。有带偏移的结构。我想这意味着 SPI1_REG_BASE + offset = 一些 SPI 注册表的地址

#define SPI1_REG_BASE         (0x01F0E000)
//-----------------------------------------------------
//Register Structure & Defines
//-----------------------------------------------------
typedef struct
{
  volatile uint32_t SPIGCR0;        // 0x0000
  volatile uint32_t SPIGCR1;        // 0x0004
  volatile uint32_t SPIINT;         // 0x0008
  volatile uint32_t SPILVL;         // 0x000C
  volatile uint32_t SPIFLG;         // 0x0010
  volatile uint32_t SPIPC0;         // 0x0014
  volatile uint32_t SPIPC1;         // 0x0018
  volatile uint32_t SPIPC2;         // 0x001C
  volatile uint32_t SPIPC3;         // 0x0020
  volatile uint32_t SPIPC4;         // 0x0024
  volatile uint32_t SPIPC5;         // 0x0028
  volatile uint32_t RSVD0[3];       // 0x002C
  volatile uint32_t SPIDAT0;        // 0x0038
  volatile uint32_t SPIDAT1;        // 0x003C
  volatile uint32_t SPIBUF;         // 0x0040
  volatile uint32_t SPIEMU;         // 0x0044
  volatile uint32_t SPIDELAY;       // 0x0048
  volatile uint32_t SPIDEF;         // 0x004C
  volatile uint32_t SPIFMT0;        // 0x0050
  volatile uint32_t SPIFMT1;        // 0x0054
  volatile uint32_t SPIFMT2;        // 0x0058
  volatile uint32_t SPIFMT3;        // 0x005C
  volatile uint32_t INTVEC0;        // 0x0060
  volatile uint32_t INTVEC1;        // 0x0064
} spi_regs_t;

有一些定义和指针*spi的定义

#define CSDEF0 (0x00000001) //bit 0
#define CSHOLD (0x10000000) //bit 28
spi_regs_t *spi = (spi_regs_t *)SPI1_REG_BASE; 

我误解了位的设置。例如,

spi->SPIDEF |= CSDEF0 //set 0 bit in the registry field 

我知道 SPIDEF - 是具有偏移地址
4Ch (0x01F0E000 + 0x4C) 的 SPI 寄存器。但是为什么 CSDEF0 是位 0 ?SIDEF 注册表中有一个字段 CSDEF(0-7 位)。这是否意味着 7 位 CSDEF 的地址为 0x00000008 ?5位的地址为0x00000006?

但是为什么 SPIDAT1 注册表的 CSHOLD 字段的地址为 0x10000000 ?

spi->SPIDAT1 |= CSHOLD  //set bit 28

SPIDAT1 寄存器有偏移地址 3Ch (0x01F0E000 + 0x3C) 它确实有字段 CSHOLD (第 28 位)

|= 在这种情况下如何工作?

我将不胜感激任何帮助弄清楚...所有这些 %)

4

4 回答 4

4

我认为您误解了寄存器的地址和值的概念。

当您说CSDEF0SPI1 模块的寄存器位于 address时,您是对的(基于您提供的结构描述) 0x01F0E000 + 0x4C。这个地址永远不会改变,它是由硬件设计定义的。

现在使用以下语句,您不是在操作地址,而是在操作寄存器的值:

spi->SPIDEF |= CSDEF0; //set 0 bit in the registry field 
spi->SPIDAT1 |= CSHOLD;  //set bit 28

运算符是|=按位 OR 和赋值运算符。它相当于以下内容:

spi->SPIDEF = spi->SPIDEF | CSDEF0; //set 0 bit in the registry field 
spi->SPIDAT1 = spi->SPIDAT1 | CSHOLD;  //set bit 28

正如CSDEF0定义的那样0x00000001,在第一条语句中,您实际上是在设置SPIDEF寄存器的 LSB 位,而将所有其他位保留为其原始值。

于 2013-02-07T08:21:41.637 回答
1

但是为什么 CSDEF0 是位 0 ?

因为:

#define CSDEF0 (0x00000001) //bit 0

它们的意思不是“值为 0 的位”,而是“位置 0 的位”。

关于:

#define CSHOLD (0x10000000) //bit 28

看看将十六进制表示法转换为二进制表示法,它就会变得清晰。

|= 在这种情况下如何工作?

这些位置(0 和 28)处的 1 位被运算之前在该变量中的值中。

于 2013-02-07T08:18:22.267 回答
1

但是为什么 CSDEF0 是位 0 ?

此宏的目的是将位 0 ​​设置为 1。如果此宏与任何寄存器进行或运算,则该寄存器的位 0 设置为 1。

例如

让我们采取spi->SPIDEF = 0x050A即0x050A ==> 0000 0101 0000 1010

现在使用 CSDEF0 设置 spi->SPIDEF 的第 0 位。

0x050A     ==> 0000 0101 0000 1010 
CSDEF0     ==> 0000 0000 0000 0001
               --------------------

spi->SPIDEF ==> 0000 0101 0000 1011

为什么 SPIDAT1 注册表的 CSHOLD 字段的地址为 0x10000000?

与 CSDEF0 用于表示第 0 位的方式相同,CSHOLD 用于第 28 位。

我猜你对 0x000001 和 000001 (???) 的十六进制和二进制表示感到困惑。

0x01 is 01. 
0x02 is 10. 
0x100 is 1 0000 0000 
0x1000 is 1 0000 0000 0000 
0x10000000 is 1 0000 0000 0000 0000 0000 0000 0000
              ^-- Bit 28 starting from bit-0
于 2013-02-07T08:19:37.057 回答
1

位没有单独的地址。

相反,嵌入式世界中的一种常见做法是将几个小属性连接到一个更大的寄存器。例如,可以将实时调度程序的一些内部定义为:

   31 30 29 28 27     26 25 24 32 22     21 20 19     18          0
 [ max_priority  ] [ current_priority] [ reserved]   [  address_xxxx ]

这里 max_priority 是 5 位无符号整数,值为 0-31;也可以将 max_priority0 定义为该值的最低有效位。所有这些参数都将在相同的绝对地址(REG_BASE + 偏移量)内访问。

于 2013-02-07T08:21:31.497 回答