之前有提到過的指標副程式的用法
最近看到了一個有趣的程式寫法
至於出處,我已經不清楚了,不過是從microchip網站的範例下載來的
因為是練習,所以刪除了一些不必要使用的程式
typedef struct { // EEPROM DATA OBJECT
unsigned int *buff;
unsigned char n;
unsigned int addr;
unsigned int csel; // chip select
}I2CEMEM_DATA;
//資料結構
typedef struct { // EEPROM DRIVER OBJECT
unsigned int cmd;
I2CEMEM_DATA *oData;
void (*init)(void *);
void (*tick)(void *);
}I2CEMEM_DRV;
//其中oDATA 繼承了 I2CEMEM_DATA的資料結構
#define I2CSEMEM_DRV_DEFAULTS { 0,\
(I2CEMEM_DATA *)0,\
(void (*)(void *))Init_I2C,\
(void (*)(void *))I2CEMEMdrv}
//巨集,定義I2CEMEM_DRV的資料
void Init_I2C( I2CEMEM_DRV *i2cMem );
void I2CEMEMdrv(I2CEMEM_DRV *i2cMem);
int main (void){
unsigned int wBuff[32];
// Instantiate Drive and Data objects
I2CEMEM_DRV i2cmem= I2CSEMEM_DRV_DEFAULTS;
//初始化i2cmem ,使用I2CSEMEM_DRV_DEFAULTS 巨集
I2CEMEM_DATA wData={0,0,0,0}, rData={0,0,0,0};
i2cmem.init(&i2cmem); //Initialize I2C periphral device;
//執行void Init_I2C( I2CEMEM_DRV *i2cMem )
//等同執行 Init_I2C( )這支副程式;
wData.buff=wBuff;
//將wData.buff 指向 WBuff 的位址
i2cmem.oData=&wData;
//將i2cmem.oData 指向wData 的位址
i2cmem.tick(&i2cmem);
//執行void I2CEMEMdrv(I2CEMEM_DRV *i2cMem)
//等同執行 I2CEMEMdrv( )這支副程式
while(1);
}
void Init_I2C( I2CEMEM_DRV *i2cMem )
{
i2cMem->cmd=10;
i2cMem->oData=0;
}
void I2CEMEMdrv(I2CEMEM_DRV *i2cMem)
{
int cntr=0;
i2cMem->oData->addr=11;
i2cMem->oData->buff;
i2cMem->oData->n=12;
i2cMem->oData->csel=13;
for(cntr=0;cntr<32;cntr++)
*(i2cMem->oData->buff+cntr)=cntr;
}
其中裡面比較有趣的是(void (*)(void *)) 這樣的轉態指令,一開始的時候,我還搞不是很懂為什麼要這樣做,原因是在程式設定時,因為型態的不同,所以要強制轉態,這就好像是變數一樣:
int a=10;
char b;
b=( char )a;
有點類似這樣的感覺
這樣的程式感覺好像是多此一舉,用定址副程式就可以搞定了,還特定寫了指標副程式,搞得程式很複雜,但我猜這是為了讓程式可以模組化,只要找到程式類型相近的,那麼,就可以直接套進去使用了,或許,只需要修改
#define I2CSEMEM_DRV_DEFAULTS { 0,\
(I2CEMEM_DATA *)0,\
(void (*)(void *))Init_I2C,\
(void (*)(void *))I2CEMEMdrv}
這段巨集程式,這樣就可以輕鬆修改程式了
ps:好久沒有看這樣的程式,真的會生疏,還好有寫blog的習慣,不然應該都忘光了