精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何模塊化編程

科技綠洲 ? 來源:嵌入式大雜燴 ? 作者:嵌入式大雜燴 ? 2023-06-22 11:40 ? 次閱讀

引言

當(dāng)項目小組做一個相對較復(fù)雜的工程時,意味著你不再獨(dú)自單干。而是和小組成員分工合作,這就要求小組成員各自負(fù)責(zé)一部分工程。比如你可能只是負(fù)責(zé)通訊或者顯示這一塊。

這個時候,你就應(yīng)該將自己的這一塊程序?qū)懗梢粋€模塊,單獨(dú)調(diào)試,留出接口供其它模塊調(diào)用。

最后,小組成員都將自己負(fù)責(zé)的模塊寫完并調(diào)試無誤后,由項目組長進(jìn)行組合調(diào)試。

像這些場合就要求程序必須模塊化。模塊化的好處是很多的,不僅僅是便于分工,它還有助于程序的調(diào)試,有利于程序結(jié)構(gòu)的劃分,還能增加程序的可讀性和可移植性。

要說的話

初學(xué)者往往搞不懂如何模塊化編程,其實(shí)它是簡單易學(xué),而且又是組織良好程序結(jié)構(gòu)行之有效的方法之一。

本文將先大概講一下模塊化的方法和注意事項,最后將以初學(xué)者使用最廣的keil c編譯器為例,給出模塊化編程的詳細(xì)步驟。

模塊化程序設(shè)計應(yīng)該理解以下概述:

模塊即是一個.c 文件和一個.h 文件的結(jié)合,頭文件(.h)中是對于該模塊接口的聲明;

這一條概括了模塊化的實(shí)現(xiàn)方法和實(shí)質(zhì):將一個功能模塊的代碼單獨(dú)編寫成一個.c文件,然后把該模塊的接口函數(shù)放在.h文件中.舉例:假如你用到液晶顯示,那么你可能會寫一個液晶驅(qū)動模塊,以實(shí)現(xiàn)字符、漢字和圖像的現(xiàn)實(shí),命名為: led_device.c,該模塊的.c文件大體可以寫成:

#include …

//定義變量
unsigned char value;//全局變量

//定義函數(shù)
//這是本模塊第一個函數(shù),起到延時作用,只供本模塊的函數(shù)調(diào)用,所以用到static關(guān)鍵字修飾
/********************延時子程序************************/
static void delay (uint us) //delay time
{}
//這是本模塊的第二個函數(shù),要在其他模塊中調(diào)用
/*********************寫字符程序**************************
** 功能:向LCD寫入字符
** 參數(shù):dat_comm 為1寫入的是數(shù)據(jù),為0寫入的是指令
content 為寫入的數(shù)字或指令
******************************************************/
void wr_lcd (uchar dat_comm,uchar content)
{}
……
……
/***************************** END Files***********************************/

注:此處只寫出這兩個函數(shù),第一個延時函數(shù)的作用范圍是模塊內(nèi),第二個,它是其它模塊需要的。為了簡化,此處并沒有寫出函數(shù)體.

.h文件中給出模塊的接口.在上面的例子中, 向LCD寫入字符函數(shù):wr_lcd (uchar dat_comm,uchar content)就是一個接口函數(shù),因為其它模塊會調(diào)用它,那么.h文件中就必須將這個函數(shù)聲明為外部函數(shù)(使用extrun關(guān)鍵字修飾),另一個延時函數(shù):void delay (uint us)只是在本模塊中使用(本地函數(shù),用static關(guān)鍵字修飾),因此它是不需要放到.h文件中的。

.h文件格式如下:

//聲明全局變量
extern unsigned char value;
//聲明接口函數(shù)
extern void wr_lcd (uchar dat_comm,uchar content); //向LCD寫入字符
……
/***************************** END Files***********************************/

這里注意三點(diǎn):

  1. 在keil 編譯器中,extern這個關(guān)鍵字即使不聲明,編譯器也不會報錯,且程序運(yùn)行良好,但不保證使用其它編譯器也如此。強(qiáng)烈建議加上,養(yǎng)成良好的編程規(guī)范。
  2. .c文件中的函數(shù)只有其它模塊使用時才會出現(xiàn)在.h文件中,像本地延時函數(shù)static void delay (uint us)即使出現(xiàn)在.h文件中也是在做無用功,因為其它模塊根本不去調(diào)用它,實(shí)際上也調(diào)用不了它(static關(guān)鍵字的限制作用)。
  3. 注意本句最后一定要加分號”;”,相信有不少同學(xué)遇到過這個奇怪的編譯器報錯: error C132: 'xxxx': not in formal parameter list,這個錯誤其實(shí)是.h的函數(shù)聲明的最后少了分號的緣故。

模塊的應(yīng)用:假如需要在LCD菜單模塊lcd_menu.c中使用液晶驅(qū)動模塊lcd_device.c中的函數(shù)void wr_lcd (uchar dat_comm,uchar content),只需在LCD菜單模塊的lcd_menu.c文件中加入液晶驅(qū)動模塊的頭文件lcd_device.h即可.

#include“l(fā)cd_device.h //包含液晶驅(qū)動程序頭文件,之后就可以在該.c文件中調(diào)用//lcd_device.h中的全局函數(shù),使用液晶驅(qū)動程序里的全局//變量(如果有的話)。

//調(diào)用向LCD寫入字符函數(shù)
wr_lcd (0x01,0x30);

//對全局變量賦值
value=0xff;

某模塊提供給其它模塊調(diào)用的外部函數(shù)及數(shù)據(jù)需在.h 中文件中冠以extern 關(guān)鍵字聲明;

這句話在上面的例子中已經(jīng)有體現(xiàn),即某模塊提供給其它模塊調(diào)用的外部函數(shù)和全局變量需在.h 中文件中冠以extern 關(guān)鍵字聲明。

下面重點(diǎn)說一下全局變量的使用。使用模塊化編程的一個難點(diǎn)(相對于新手)就是全局變量的設(shè)定,初學(xué)者往往很難想通模塊與模塊公用的變量是如何實(shí)現(xiàn)的,常規(guī)的做法就是本句提到的,在.h文件中外部數(shù)據(jù)冠以extern關(guān)鍵字聲明。

比如上例的變量value就是一個全局變量,若是某個模塊也使用這個變量,則和使用外部函數(shù)一樣,只需在使用的模塊.c文件中包含#include“l(fā)cd_device.h”即可。

另一種處理模塊間全局變量的方法來自于嵌入式操作系統(tǒng)uCOS-II,這個操作系統(tǒng)處理全局變量的方法比較特殊,也比較難以理解,但學(xué)會之后妙用無窮,這個方法只需用在頭文件中定義一次。方法為:

在定義所有全局變量(uCOS-II將所有全局變量定義在一個.h文件內(nèi))的.h頭文件中:

#ifdef xxx_GLOBALS
#define xxx_EXT
#else
#define xxx_EXT extern
#endif

.H 文件中每個全局變量都加上了xxx_EXT的前綴。xxx 代表模塊的名字。

該模塊的.C文件中有以下定義:

#define xxx_GLOBALS
#include "includes.h"

當(dāng)編譯器處理.C文件時,它強(qiáng)制xxx_EXT(在相應(yīng).H文件中可以找到)為空,(因為xxx_GLOBALS已經(jīng)定義)。

所以編譯器給每個全局變量分配內(nèi)存空間,而當(dāng)編譯器處理其他.C 文件時,xxx_GLOBAL沒有定義,xxx_EXT 被定義為extern,這樣用戶就可以調(diào)用外部全局變量。為了說明這個概念,可以參見uC/OS_II.H,其中包括以下定義:

#ifdef OS_GLOBALS
#define OS_EXT
#else
#define OS_EXT extern
#endif
OS_EXT INT32U OSIdleCtr;
OS_EXT INT32U OSIdleCtrRun;
OS_EXT INT32U OSIdleCtrMax;

同時,uCOS_II.H 中有以下定義:

#define OS_GLOBALS

#include “includes.h”

當(dāng)編譯器處理uCOS_II.C 時,它使得頭文件變成如下所示,因為OS_EXT 被設(shè)置為空。

INT32U OSIdleCtr;

INT32U OSIdleCtrRun;

INT32U OSIdleCtrMax;

這樣編譯器就會將這些全局變量分配在內(nèi)存中。當(dāng)編譯器處理其他.C 文件時,頭文件變成了如下的樣子,因為OS_GLOBAL沒有定義,所以O(shè)S_EXT 被定義為extern。

extern INT32U OSIdleCtr;

extern INT32U OSIdleCtrRun;

extern INT32U OSIdleCtrMax;

在這種情況下,不產(chǎn)生內(nèi)存分配,而任何 .C文件都可以使用這些變量。這樣的就只需在 .H文件中定義一次就可以了。

模塊內(nèi)的函數(shù)和全局變量需在.c 文件開頭冠以static 關(guān)鍵字聲明;

這句話主要講述了關(guān)鍵字static的作用。Static是一個相當(dāng)重要的關(guān)鍵字,他能對函數(shù)和變量做一些約束,而且可以傳遞一些信息

比如上例在LCD驅(qū)動模塊.c文件中定義的延時函數(shù)static void delay (uint us),這個函數(shù)冠以static修飾,一方面是限定了函數(shù)的作用范圍只是在本模塊中起作用,另一方面也給人傳達(dá)這樣的信息:該函數(shù)不會被其他模塊調(diào)用。

下面詳細(xì)說一下這個關(guān)鍵字的作用,在C 語言中,關(guān)鍵字static 有三個明顯的作用:

  1. 在函數(shù)體,一個被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過程中維持其值不變。
  2. 在模塊內(nèi)(但在函數(shù)體外),一個被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問,但不能被模塊外其它函數(shù)訪問。它是一個本地的全局變量。
  3. 在模塊內(nèi),一個被聲明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用。那就是,這個函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用。

前兩個都比較容易理解,最后一個作用就是剛剛舉例中提到的延時函數(shù)(static void delay (uint us)),本地化函數(shù)是有相當(dāng)好的作用的。

永遠(yuǎn)不要在.h 文件中定義變量!

比較一下代碼:

代碼一:

/*module1.h*/
int a = 5; /* 在模塊1 的.h 文件中定義int a */
/*module1 .c*/
#include "module1.h" /* 在模塊1 中包含模塊1 的.h 文件 */
/*module2 .c*/
#include "module1.h" /* 在模塊2 中包含模塊1 的.h 文件 */
/*module3 .c*/
#include "module1.h" /* 在模塊3 中包含模塊1 的.h 文件 */

以上程序的結(jié)果是在模塊1、2、3 中都定義了整型變量a,a 在不同的模塊中對應(yīng)不同的地址元,這個世界上從來不需要這樣的程序。正確的做法是:

代碼二:

/*module1.h*/
extern int a; /* 在模塊1 的.h 文件中聲明int a */
/*module1 .c*/
#include "module1.h" /* 在模塊1 中包含模塊1 的.h 文件 */
int a = 5; /* 在模塊1 的.c 文件中定義int a */
/*module2 .c*/
#include "module1.h" /* 在模塊2 中包含模塊1 的.h 文件 */
/*module3 .c*/
#include "module1.h" /* 在模塊3 中包含模塊1 的.h 文件 */

這樣如果模塊1、2、3 操作a 的話,對應(yīng)的是同一片內(nèi)存單元。

注:

一個嵌入式系統(tǒng)通常包括兩類(注意是兩類,不是兩個)模塊:

  • 硬件驅(qū)動模塊,一種特定硬件對應(yīng)一個模塊;
  • 軟件功能模塊,其模塊的劃分應(yīng)滿足低偶合、高內(nèi)聚的要求。
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 編程
    +關(guān)注

    關(guān)注

    88

    文章

    3520

    瀏覽量

    93262
  • 模塊化
    +關(guān)注

    關(guān)注

    0

    文章

    321

    瀏覽量

    21273
  • 程序設(shè)計
    +關(guān)注

    關(guān)注

    3

    文章

    261

    瀏覽量

    30315
收藏 人收藏

    評論

    相關(guān)推薦

    模塊化編程

    額 哪位大蝦能提供一下模塊化編程的相關(guān)視頻,越全越好,不勝感激。。。。。
    發(fā)表于 12-21 15:08

    模塊化編程

    大俠們,求教模塊化編程的問題啊,,,怎么添加多個C文件,如何寫自己的頭文件???
    發(fā)表于 11-08 10:50

    模塊化編程

    大家一起來講解看,,,到底何為模塊化編程???
    發(fā)表于 08-07 21:56

    模塊化編程

    模塊化編程,很好的學(xué)習(xí)資料
    發(fā)表于 08-16 16:59

    模塊化編程

    在練習(xí)模塊化編程的時候,知道盡量不用全局變量!!可是,不得不使用很多的全局變量的時候,怎么辦?提示multiple public……
    發(fā)表于 08-26 16:17

    模塊化編程思想

    模塊化編程思想
    發(fā)表于 06-24 10:09

    轉(zhuǎn):C語言模塊化編程

    C語言模塊化編程
    發(fā)表于 07-25 17:15

    到底什么是模塊化編程

    對于一些接觸單片機(jī)編程不久的小萌新來說,模塊化編程這個概念剛接觸的時候可能會很懵,到底什么是模塊化編程?我以前也不懂,后面根據(jù)網(wǎng)上的說明和自
    發(fā)表于 12-03 07:39

    什么是模塊化編程

    1什么是模塊化模塊化編程就是把我們的一整個項目,分成很多模塊(比如一個學(xué)生成績查詢可以分為,登陸,查詢,修改保存,退出等模塊)而一個程序工程
    發(fā)表于 12-06 08:02

    什么是模塊化編程模塊化編程的注意事項

    單片機(jī)零基礎(chǔ)入門(8-4)模塊化編程---LED1602調(diào)試工具一、回顧二、什么是模塊化編程?1、傳統(tǒng)方式編程:2、
    發(fā)表于 02-23 07:14

    8051模塊化編程分析

    本文以“60秒倒計時電路”為例談一談51 單片機(jī)匯編語言模塊化編程的一點(diǎn)技巧
    發(fā)表于 06-30 11:04 ?3166次閱讀
    8051<b class='flag-5'>模塊化</b><b class='flag-5'>編程</b>分析

    012-IIC總線原理和模塊化編程方法

    云龍單片機(jī)—IIC總線原理和模塊化編程方法。
    發(fā)表于 03-17 11:03 ?7次下載

    模塊化編程思想

    模塊化編程思想,充分利用c語言的可移植性,更好的利用c語言。
    發(fā)表于 03-22 15:15 ?16次下載

    單片機(jī)的C語言模塊化編程

    單片機(jī)的C語言模塊化編程
    發(fā)表于 10-13 11:16 ?51次下載
    單片機(jī)的C語言<b class='flag-5'>模塊化</b><b class='flag-5'>編程</b>

    藍(lán)橋杯模塊化編程

    ???九層妖塔?起于壘土【藍(lán)橋杯】—{模塊化編程}
    發(fā)表于 11-21 18:36 ?9次下載
    藍(lán)橋杯<b class='flag-5'>模塊化</b><b class='flag-5'>編程</b>