1. 程式人生 > >嵌入式c語言的集中新用法

嵌入式c語言的集中新用法

       搞嵌入式的,大都用C語言寫程式碼,一直習慣用 if 、switch打天下,在定義資料結構的時候也只用到 字元型、整型、陣列,位;很少用結構體,共用體,列舉,因為咱C語言學得不好,和它們不熟,總感覺它們不那麼好招呼,重要的是自已覺得沒必要用上它們。

        隨著越來越多的積累,咱寫程式碼的風格也在不斷的發生變化,從以前的喜歡將所有的函式及資料的定義寫在一個檔案裡到逐漸的將函式按功能模組化、從以前的習慣直接在程式裡寫常數到慢慢的開始用上巨集來代替,咱程式設計的風格也逐漸開始正規化,程式設計水平也逐步提升,當然這些成績都源於咱不斷的學習,學習高人的程式設計規範、學習herald的感悟設計、還有網上寫得非常出色的程式碼以及STM32的韌體函式庫。下面和大家共享下,我看到的一些關於嵌入式c語言的一些用法。

一、學習高手的檔案包含巧妙用法

 當一個頭檔案被多個c檔案包含,且該標頭檔案中定義了這些c檔案的公共變數,則在編譯的時候,會出現重複定義,導致編譯通不過,通常我們會採用如下兩種做法來解決上述問題。

為了讓問題表述得更清楚,我們假設三個C檔案C1,C2,C3,一個頭檔案H1,C1,C2,C3有兩個公共變數V1和V2)

1、在C1檔案中定義變數V1和V2,在C2和C3檔案中對V1,V2用extern宣告;

2、在C1檔案中定義變數V1和V2,在H1中對V1,V2用extern宣告,然後在C2和C3檔案中包含H1; 

很顯然,以上兩種方法都要對V1和V2書寫至少兩次,一次定義,一次外部宣告,且不是在同一檔案下,這樣不利於管理和修改,有沒有一種方法可以讓這些公用的變數放在一個檔案裡,且只要書寫一次呢? 


        我在二姨那裡無意中看到匠人的發帖,就是關於該問題的討論,現在我轉發一下,與大家同共分享。首先我們將要用到的公共變數全部書寫到com.h檔案中,每一個變數在定義前加一個符號EXT_,當該標頭檔案被main.c函式包含時,定義EXT_為空,表示com.h中的變數在main.c中被定義,當被其他檔案包含時,定義EXT為extern,表示外部宣告,如Com.h檔案,

//避免重複定義

#ifndef root
    #define EXT_
#else
    #define EXT_ extern
#endif

//全域性變數
EXT_u8 variablel;
Main.c
#define root   //在包含com.h前定義root
#include "com.h"

二、用結構體的方式來定義匯流排或外設地址   

當一個整體包含不同型別的多個成員時,通常用結構體來定義結構體變數,這樣記憶體會將這些變數按照遞增的方式分配到相鄰的地址(不對齊的地方會有填充),按“結構體名.成員名”的方式訪問結構體內的成員,這是訪問結構體變數的方式;但是還有一種指向結構體變數的指標,它可以將某個地址轉換成該結構體型別的指標,比如暫存器的定義:

typedef struct
{
    vu32 CRL;
    vu32 CRH;
    vu32 IDR;
    vu32 IDR;
    vu32 BSRR;
    vu32 BRR;
    vu32 LCKR;
} GPIO_TypeDef;

#define GPIOA_BASE;      ((u32)0x40010800)  //GPIOA的基地址為0x40010800
#define GPIOA   (GPIO_TypeDef*)   GPIOA_BASE   //強制型別轉換為GPIO_Typedef型別的指標

這樣就可以在操作GPIOA的暫存器時只要這樣寫就可以了

讀:X=GPIOA->CRL;     寫:GPIOA->CRL=x;

或:X=(*GPIOA).CRL;    寫:(*GPIOA).CRL=x;

當然,要達到上述目的也可以採用如下方式
 

#define GPIOA_ CRL 0x40010800
#define GPIOA_ CRH 0x40010804
#define GPIOA_ IDR 0x40010808
#define GPIOA_ ODR 0x4001080C
#define GPIOA_ BSSR 0x40010810#define GPIOA_ LCKR 0x40010814

很明顯,第一種書寫方式更加正規化,且當定義多個 GPIO 時,只要將其它 GPIO 的基地址
強制轉換為該結構型別的指標即可。

再來看看一個定義外部匯流排的例子

typedef struct
{
vu8 CH375_DATA;
vu8 CH375_CMD; //偏移量 1
} CH375_TypeDef;
#define CH375 ((CH375_TypeDef *) 0x6c000000)
CH375-> CH375_DATA=data; //往 0x6c000000 地址處寫資料
CH375-> CH375_CMD=cmd; //往 0x6c000001 地址處寫命令

怎麼樣,是不是方便多了。重要的是程式碼的觀賞和可讀性提高了。

 

先這樣,以後發現會加。