文章程式碼顯示

2018年2月15日 星期四

《筆記》C語言 - 09_3 (完):利用指標結構來操縱 MCU 相同性質的暫存器群

利用指標結構來操縱 MCU 相同性質的暫存器群

#include "stdio.h"

typedef struct{
     unsigned char BASE;
     unsigned char PORTA;
     unsigned char PORTB;
     unsigned char PORTC;
     unsigned char PORTD;
     // unsigned char Preserve0[2]; /* 假設在 MCU 中,暫存器的位置有跳躍的話可以用這種方式越過 2 個 bytes */
     // unsigned char Preserve1; /* 假設在 MCU 中,暫存器的位置有跳躍的話可以用這種方式越過 1 個 byte */
     unsigned char DDRA;
     unsigned char DDRB;
     unsigned char DDRC;
    }REG,*REGptr;

void main(){
 // 宣告一個陣列,來模擬一個暫存器群(這個暫存器群可能在 MCU 裡面管理著通訊系統)
 unsigned char regGroup[] = { 0x00, 0x01, 0x02, 0x03, 0x1A, 0x56, 0x77, 0xff };
 printf("通訊系統0\n");

 // 可以藉由"結構名稱強制轉為指標"的方式,去取出暫存器群中的某個暫存器之值
 printf("((REG*)(regGroup))->DDRB : 0x%x \n", ((REG*)(regGroup))->DDRB);
 // 或直接使用結構指標
 printf("((REGptr)(regGroup))->DDRC : 0x%x \n", ((REGptr)(regGroup))->DDRC);

 /* 假設 MCU 裡面"相同性質的暫存器群"具有多組,例如有 通訊系統0 、 通訊系統1、通訊系統2
 ** 雖然是"不同組"通訊系統 ,但因為裡面所"需要操作的暫存器完全相同",我們藉由定義一個結構體的方式
 ** 就不用大幅度的修改程式碼,達到程式碼的再利用性 */
 //假設通訊系統1的暫存器群
 unsigned char regGroup1[] = { 0x01, 0x08, 0x09, 0x0A, 0x55, 0x88, 0x99, 0xCC };
 printf("通訊系統1\n");
 printf("((REG*)(regGroup1))->DDRB : 0x%x \n", ((REG*)(regGroup1))->DDRB);
 printf("((REGptr)(regGroup1))->DDRC : 0x%x", ((REGptr)(regGroup1))->DDRC);
}


甚至我可以更簡潔的配合 #define

#include "stdio.h"

typedef struct{
     unsigned char BASE;
     unsigned char PORTA;
     unsigned char PORTB;
     unsigned char PORTC;
     unsigned char PORTD;
     // unsigned char Preserve0[2]; /* 假設在 MCU 中,暫存器的位置有跳躍的話可以用這種方式越過 2 個 bytes */
     // unsigned char Preserve1; /* 假設在 MCU 中,暫存器的位置有跳躍的話可以用這種方式越過 1 個 byte */
     unsigned char DDRA;
     unsigned char DDRB;
     unsigned char DDRC;
    }REG,*REGptr;

#define communication0 ((REGptr)(regGroup))
#define communication1 ((REGptr)(regGroup1))

void main(){
 unsigned char regGroup[] = { 0x00, 0x01, 0x02, 0x03, 0x1A, 0x56, 0x77, 0xff };
 unsigned char regGroup1[] = { 0x01, 0x08, 0x09, 0x0A, 0x55, 0x88, 0x99, 0xCC };

 printf("通訊系統0\n");
 printf("communication0->DDRB : 0x%x \n", communication0->DDRB);

 printf("通訊系統1\n");
 printf("communication1->DDRB : 0x%x \n", communication1->DDRC);

}



20180910 補充 : 
在原文書上有提到,結構內的成員變數在建立時可能會有"洞"出現,也就是在記憶體的排序中可能會造成位址的跳躍。但這問題只存在於你定義不同的數據類型於同一個結構體中。也就是說只要你整個結構體都定義為 unsigned char 就不會有這個問題


C語言系列結束 結語 : 

至此章節, C 語言有至少八成以上的知識概念都已囊括在內。

熟悉了前述的文章,基本上有關於 MCU 會使用到的 C 語言的語法不太可能會出現看不懂的(意指你不會完全不知道他在做什麼)

但,基於目前很多的 open source code 都會使用到 C++ 的部分 (又或者說是 C/C++ 混用)
所以此系列還會往 C++ 的部分繼續延伸
但因為 C++ 的部分實在太廣了,故我們只會將使用在 MCU 中常見的部分進行解說
幫助我們在看 open source code 時能夠理解他是在做什麼

↓↓↓ 連結到部落格方針與索引 ↓↓↓

Blog 使用方針與索引