2016-03-14 36 views
0

可變我有三個電機驅動器,我想和我的控制器接口連接的結構中的一員。我的問題涉及如何編寫代碼以使函數更新這些驅動程序的值。參考使用存儲在結構用C

我用結構來表示的驅動器和控制器具有用於訪問所述控制器的不同的寄存器一組內置結構。

我想使一個函數,它的結構爲特定的電動機驅動器作爲輸入參數,並且改變各種的GPIO的值用於該特定電機驅動器。

比方說,我的控制器上的引腳與下面的代碼訪問(這是由控制器製造商提供的結構):

GpioCtrlRegs.GPAMUX1.bit.GPIO01 = 0; 

爲了方便更新在多個位置的銷我使用下面的宏:

#define MOTOR1_nSLEEP  GPIO01 
#define MOTOR1_nSLEEP_MUX GPAMUX1 

GpioCtrlRegs.MOTOR1_nSLEEP_MUX.bit.MOTOR1_nSLEEP = 1; 

現在,這裏是棘手的地方。我想定義下面的函數。

void Initialize (struct motor_driver MOTOR1) { 
GpioCtrlRegs.MOTOR1_nSLEEP_MUX.bit.MOTOR1_nSLEEP = 1; 
} 

但問題是,我需要能夠根據輸入參數更改宏。據我所知,這是不可能的。所以我認爲我會使用指針指向內存中的GPIO特定位置,然後將該指針添加到「struct motor_driver」中,以便它也傳遞到函數中。所以像這樣:

MOTOR1.pointers.nSLEEP_MUX = &(GpioCtrlRegs.MOTOR1_nSLEEP_MUX.bit.MOTOR1_nSLEEP); 

然後在函數中,我可以使用這個指針來直接調整GPIO寄存器的值。不幸的是,由於指針必須在字節級別工作,所以不允許指針取值爲位域。

所以我將不得不使用指針的第一個#define值「MOTOR1_nSLEEP_MUX」,然後手動訪問「.bit.MOTOR1_nSLEEP」(可能通過使用結構指針)。

現在的問題是,我不知道如何在一個靈活的,宏觀獨立的方式在宏「MOTOR1_nSLEEP」的工作,因爲它等於「GPIO01」。如何將「GPIO01」傳遞給必要的結構指針,以便我可以訪問正確的位域?你有什麼建議?我首先以一種愚蠢的方式接近這一點?

這裏是GpioCtrlRegs一些額外的信息:

struct GPIO_CTRL_REGS { 
    union GPACTRL_REG  GPACTRL; // GPIO A Control Register (GPIO0 to 31) 
    union GPA1_REG  GPAQSEL1; // GPIO A Qualifier Select 1 Register (GPIO0 to 15) 
    union GPA2_REG  GPAQSEL2; // GPIO A Qualifier Select 2 Register (GPIO16 to 31) 
    union GPA1_REG  GPAMUX1; // GPIO A Mux 1 Register (GPIO0 to 15) 
    union GPA2_REG  GPAMUX2; // GPIO A Mux 2 Register (GPIO16 to 31) 
    union GPADAT_REG  GPADIR;  // GPIO A Direction Register (GPIO0 to 31)) 
    union GPADAT_REG  GPAPUD;  // GPIO A Pull-Up Disable Register 
    Uint16     rsvd1[2]; // Reserved 
    union GPBCTRL_REG  GPBCTRL; // GPIO B Control Register (GPIO32 to 63) 
    union GPB1_REG  GPBQSEL1; // GPIO B Qualifier Select 1 Register (GPIO32 to 47) 
    union GPB2_REG  GPBQSEL2; // GPIO B Qualifier Select 2 Register (GPIO48 to 63) 
    union GPB1_REG  GPBMUX1; // GPIO B Mux 1 Register (GPIO32 to 47) 
    union GPB2_REG  GPBMUX2; // GPIO B Mux 2 Register (GPIO48 to 63) 
    union GPBDAT_REG  GPBDIR;  // GPIO B Direction Register (GPIO32 to 63) 
    union GPBDAT_REG  GPBPUD;  // GPIO B Pull-Up Disable Register 
    Uint16     rsvd2[24]; // Reserved 
    union AIO_REG   AIOMUX1; // Analog IO Mux 1 Register 
    Uint16     rsvd3[2]; // Reserved 
    union AIODAT_REG  AIODIR;  // Analog IO Direction Register 
    Uint16     rsvd4[4]; // Reserved 
}; 

union GPA1_REG { 
    Uint32 all; 
    struct GPA1_BITS bit; 
}; 

struct GPA1_BITS {  // bits description 
    Uint16 GPIO0:2;   // 1:0 GPIO0 
    Uint16 GPIO1:2;   // 3:2 GPIO1 
    Uint16 GPIO2:2;   // 5:4 GPIO2 
    Uint16 GPIO3:2;   // 7:6 GPIO3 
    Uint16 GPIO4:2;   // 9:8 GPIO4 
    Uint16 GPIO5:2;   // 11:10 GPIO5 
    Uint16 GPIO6:2;   // 13:12 GPIO6 
    Uint16 GPIO7:2;   // 15:14 GPIO7 
    Uint16 GPIO8:2;   // 17:16 GPIO8 
    Uint16 GPIO9:2;   // 19:18 GPIO9 
    Uint16 GPIO10:2;   // 21:20 GPIO10 
    Uint16 GPIO11:2;   // 23:22 GPIO11 
    Uint16 GPIO12:2;   // 25:24 GPIO12 
    Uint16 GPIO13:2;   // 27:26 GPIO13 
    Uint16 GPIO14:2;   // 29:28 GPIO14 
    Uint16 GPIO15:2;   // 31:30 GPIO15 
}; 

而在另一個文件:

#ifdef __cplusplus 
#pragma DATA_SECTION("GpioCtrlRegsFile") 
#else 
#pragma DATA_SECTION(GpioCtrlRegs,"GpioCtrlRegsFile"); 
#endif 
volatile struct GPIO_CTRL_REGS GpioCtrlRegs; 
+0

您可能會對這裏的宏太過幻想。你有沒有考慮用一系列電機制造你自己的結構?只要你的結構域與其結構覆蓋相同的內存,它就可以工作。請記住使用所有相同的額外參數進行定義,例如volatile,打包,字節順序,其他可能附加的其他內容。 –

+0

你爲什麼不創建一個條件來決定什麼寄存器將被初始化 – KS7X

+0

它可能做一個條件,但考慮到將會有多少個函數以及我需要做多少次(添加到代碼長度和開銷時間),我寧願提出一個更優雅的解決方案。 –

回答

1

設法找到了header file這很可能類似於您正在使用的一個。參考文獻GpioCtrlRegs.GPAMUX1.bit.GPIO01是一個位字段。你不能佔用一個位域的地址。

而且我猜測,Mode_GPIO是一個int,其中僅低比特(0或1)事宜。這一切都是有道理的。

字段GpioCtrlRegs.GPAMUX1是聯合,它有一個地址。

所以 - 假設鏈接的頭文件 - 你可以在兩個mux'es之間在同一銀行,如表挑:

static union GPB1_REG *mux[2] = { &GpioCtrlRegs.GPBMUX1, &GpioCtrlRegs.GPBMUX2 }; 

然後,你可以觸摸i個MUX有:

mux[i]->bit.MOTOR1_nSLEEP = 1; 

但就是這樣。你甚至不能在同一個數組中引用GPCMUX12,因爲標題給它們不同的類型。

我強烈建議你放棄它。如果你真的需要選擇電動機的int,然後寫功能,如:

void motorSleep(int i) { 
    switch (i): 
    case 1: 
     ... set the registers to make 3 sleep 
     break; 
    case 2: 
     ... set the registers to make 2 sleep 
     break; 
    case 3: 
     ... set the registers for all other inputs 
     break; 
    default: 
     assert(0); 
    } 
} 

寓意是不要過度設計這樣的東西。設計頭文件的人清楚地希望按照上述方式使用它,而不是使用奇特的地址算術。我不是說他們幫了你一個忙。但是它就是這樣啊。