簡體   English   中英

C,是否可以將宏分配給結構變量?

[英]C, Is it possible to ASSIGN a macro to a structure variable?

我是嵌入式編程的新手。 我有一個帶有2個頭文件的PIC微控制器: pic.hTimer_peripheral.h

pic.h ,計時器配置寄存器已定義為:

__extension__ typedef struct tagT1CONBITS {
union {
  struct {
    unsigned :1;
    unsigned TCS:1;
    unsigned TSYNC:1;
    unsigned :1;
    unsigned TCKPS:2;
    unsigned TGATE:1;
    unsigned :6;
    unsigned TSIDL:1;
    unsigned :1;
    unsigned TON:1;
  };

  struct {
    unsigned :4;
    unsigned TCKPS0:1;
    unsigned TCKPS1:1;
   };
};
} T1CONBITS;

timer.h ,一些宏定義為:

/* Timer1 Control Register (T1CON) Bit Defines */

#define T1_ON               0xffff      /* Timer1 ON */
#define T1_OFF              0x7fff      /* Timer1 OFF */

與單片機數據表相對應。 unsigned類型是16位。 我試圖通過這種方式將T1_ON分配給結構變量T1CONBITS

T1CONBITS=T1_ON   // which is wrong.

我知道我可以初始化一個結構,但是我想在我的主要功能中做一個賦值,並且我不想使用這樣的結構成員來做它:

T1CONBITS.TCS=1; 
T1CONBITS.TSYNC=1;

有什么辦法嗎? 如果沒有,為什么您認為在timer.h中定義了這些宏?

感謝您的見解

這是行不通的,因為您正在嘗試為某個完全不相關的類型的變量分配數字。 數字與結構的基礎位模式匹配這一事實是編譯器不太關心的事情。

嘗試這個:

union BitsInt {
    struct tagT1CONBITS con;
    int bits;
};

T1CONBITS = ((union BitsInt){ .bits = T1_ON }).con;

您將一種類型的數據放入,而得到無關類型的相同數據。

(使用聯合來轉換位模式對於最新的C標准是有效的。)

經過預處理

T1CONBITS=T1_ON;

會是這樣的:

T1CONBITS=0xffff;

要成為struct變量,只能分配相同類型的變量


您可以這樣輕松地將T1CONBITS設置為全1

memset(&T1CONBITS, 0xff, sizeof(T1CONBITS));

T1CONBITS結構的名稱表明它旨在訪問T1CON的 是否還定義了一個寄存器T1CON,您可以編寫以下內容?

T1CON = T1_ON ;

更好的是,您可以按預期方式簡單地使用T1CONBITS,並且完全需要同時達到T1_ON和T1_OFF:

T1CONBITS.TON = 0 ; // Off
T1CONBITS.TON = 1 ; // On

通過直接分配T1CON,可以將所有其他位設置為1,這在任何情況下都可能不是您想要的。 而是您將進行“讀取-修改-寫入”操作,這實際上是位訪問所產生的錯誤少得多且更清晰的方式。

以我的經驗,編譯器為某個微控制器提供的預制寄存器映射充其量是繁瑣,不可讀和不可移植的。 沒有人能說出您的特定代碼是否有意義,因為在每個編譯器上位字段的實現方式都是不同的。

如果您可以選擇自己編寫寄存器定義,請這樣做。 例如:

#define T1CON (*(uint16_t*)0x1234u) // some address

#define T1CON_TCS    0x4000u
#define T1CON_TSYNC  0x2000u
...
#define T1CON_TCKPS  0x0C00u

然后使用標准C編程位設置慣用法設置位:

T1CON |=  T1CON_TCS; // set this bit
T1CON &= ~T1CON_TCS; // clear this bit

設置屬於同一組的幾個位:

#define T1_ON  0x0C00u 
#define T1_OFF 0x0400u

T1CON |= (T1CON_TCKPS & T1_ON);

等等。

(盡管請注意,這可能是讀-修改-寫,可能不是您想要的。如果必須使用普通位集(在特殊情況下,用於清除標志寄存器等),則通常省略按位邏輯和只需編寫T1CON = T1CON_TCS | TSYNC;並設置所有所需的位即可,但請注意,沒有保證,特定的C代碼提供讀-修改-寫還是位設置取決於CPU和編譯器。請反匯編以確保代碼確實您所期望的。)

這對於世界上的每個C編譯器都是100%可移植的,並且對於使用嵌入式系統工作的每個C程序員而言都是100%可讀的。

暫無
暫無

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

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