簡體   English   中英

如何設置寄存器中的位?

[英]How to set bits in registers?

有注冊表(第一個?)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-是SPI寄存器,其偏移地址為4Ch
(0x01F0E000 + 0x4C)。 但是,為什么CSDEF0是位0? SPIDEF注冊表中有一個字段CSDEF(0-7位)。 這是否意味着CSDEF的7位地址為0x00000008? 5位地址為0x00000006?

但是,為什么SPIDAT1注冊表的CSHOLD字段的地址為0x10000000?

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

SPIDAT1寄存器的偏移地址為3Ch(0x01F0E000 + 0x3C)它確實具有字段CSHOLD(第28位)

| =在這種情況下如何工作?

我將不勝感激,為您找出所有...%的幫助。

我認為您誤解了寄存器的地址和值的概念。

當您說SPI1模塊的CSDEF0寄存器位於地址0x01F0E000 + 0x4C時,您是對的(基於給出的結構描述)。 該地址永遠不會改變,它是由硬件設計定義的。

現在,使用以下語句,您將不操縱地址,而是操縱寄存器的值:

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

|=運算符是按位或運算符和賦值運算符。 它等效於以下內容:

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

由於CSDEF0定義為0x00000001 ,因此在第一條語句中,您實際上是在設置SPIDEF寄存器的LSB位,而將所有其他位保留為其原始值。

但是為什么CSDEF0是位0?

因為:

#define CSDEF0 (0x00000001) //bit 0

它們的意思不是“值為0的位”而是“位置0的位”。

關於:

#define CSHOLD(0x10000000)//位28

看一下將十六進制符號轉換為二進制符號,這將變得很清楚。

| =在這種情況下如何工作?

將那些位置(0和28)的1位AT 累加到該變量中先前的值中。

但是,為什么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

位沒有單獨的地址。

相反,嵌入式世界中的一種常見做法是將幾個小的屬性連接到一個更大的寄存器。 例如,可以將實時調度程序的一些內部定義為:

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

在此,max_priority是值為0-31的5位無符號整數; 最好將max_priority0定義為該值的最低有效位。 所有這些參數將在相同的絕對地址(REG_BASE +偏移量)內訪問。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM