今天給大家帶來微控制器、嵌入式中比較常用的一種程式設計方法--分層設計模式,核心中就大量採用這種設計方式,一般對於某種硬體體系分為幾層,以乙個核心層來管理,它會抽象出硬體或者個體的共性操作來進行管理,很像在用c語言實現物件導向的設計。
下面就以實際**來簡單說明。假設我們有這麼一種需求,需要從某些裝置讀取一些資料,但是這些裝置可能有51體系的,也可能有arm體系的。那麼我們應該抽象乙個資料結構來表示這種這些傳送資料的裝置。這就是核心層需要做的工作,假如我們裝置有兩個共性:
1.使用前需要初始化
2.能收到資料
那麼我們的資料結構就應該這麼抽象:
struct receiveopr
int (*getdevdata)(char data); //裝置接收資料的函式
int (*devinit)(); //裝置初始化函式
但是核心層管理的不僅僅是乙個裝置,為了方便核心層能找到某個裝置,那麼就需要給裝置乙個標示,這個標示可以有很多種,比如裝置名字,產品id等等,這裡我們以裝置名來區分。所以上面結構體就應該繼續新增名字成員,變為:
struct receiveopr
char *name; //接收裝置的名字
int (*getdevdata)(char data); //裝置接收資料的函式
int (*devinit)(); //裝置初始化函式
那麼核心層如何管理這些裝置呢?比較簡單也是比較常見的就是裝置鍊錶了,也就是我們普通的資料結構鍊錶,所以還需要乙個指標,來操作這個裝置鍊錶,於是,結構體應該再新增乙個成員,變為:
struct receiveopr
char *name; //接收裝置的名字
int (*getdevdata)(char data); //裝置接收資料的函式
int (*devinit)(); //裝置初始化函式
struct receiveopr *next; //用來管理鍊錶
核心中有種雙向鍊錶的資料結構 list_head,它提供了更為強大的鍊錶管理能力,是核心最核心的資料結構之一,有興趣也可以移植那個來用。到這裡,我們的接收裝置的功能抽象就基本完成了(如果在實現過程中發現還需要其他成員,可以隨時新增)。
那麼核心層如何具體去實現呢?貼一下**通過注釋就能明白。
receive_manager.h---輸入裝置核心層標頭檔案
#ifndef _receive_manager_h
#define _receive_manager_h
struct receiveopr
char *name; //接收裝置的名字
int (*getdevdata)(char data); //裝置接收資料的函式
int (*devinit)(); //裝置初始化函式
struct receiveopr *next; //用來管理鍊錶
//函式宣告
int registerrecvopr(struct receiveopr *p);
int selectrecvdev(char *name);
int getdevdata(char data);
int recvdevinit();
int recvmanagerinit();
#endif /* _receive_manager_h */
receive_manager.c---輸入裝置核心層實現檔案
#include
#include
#include
static struct receiveopr *listreceivehead = null; //裝置鍊錶的煉表頭
static struct receiveopr *defaultdev = null; //需要操作的裝置指標
* @brief 核心層提供給具體裝置的註冊函式,每個裝置都要提供上面的結構體指標,然後註冊到核心層
* @param p **行數
int registerrecvopr(struct receiveopr *p)
struct receiveopr *listtmp;
if (!listreceivehead)
listreceivehead = p;
p->next = null;
else
listtmp = listreceivehead;
while (listtmp->next)
listtmp = listtmp->next;
listtmp->next = p;
p->next = null;
return 0;
* @brief 根據name在鍊錶中找到相應的裝置,然後賦給指標 defaultdev
* @param name 裝置名字
int selectrecvdev(char *name)
struct receiveopr *listtmp = listreceivehead;
while (listtmp)
if (strcmp(listtmp->name, name) == 0)
defaultdev = listtmp;
return 0;
listtmp++;
return -1;
* @brief 根據指定的defaultdev,取出其中的資料,存到data陣列中
* @param data 陣列指標
int getdevdata(char data)
int ret;
if(defaultdev)
ret = defaultdev->getdevdata(data);
return ret;
else
return -1;
* @brief 根據指定的defaultdev,對其進行初始化
int recvdevinit()
if(defaultdev)
if(defaultdev->devinit() == 0)
return 0;
else
return -1;
else
return -1;
* @brief 對需要管理的裝置進行註冊,後邊會說到
int recvmanagerinit()
registerarmrecv();
return 0;
核心層簡單的管理工作就完成了,總結下就是:
1.提供 registerrecvopr 介面給具體裝置用,並把裝置新增到裝置鍊錶
2.提供 recvdevinit、selectrecvdev、getdevdata介面給上層用,來選擇裝置並使用裝置
那麼我們具體的裝置要怎麼做呢,就是實現核心層定義的結構體,然後註冊到核心層即可,下面以乙個模擬裝置來說明
arm_recv.c---假設這是arm體系下乙個裝置,功能沒有實現,只是模擬用
#include
static char buf[16];
static int fd;
static int getarmrecvdev(char data);
static int armrecvinit();
//這是核心層提供的裝置抽象,具體裝置檔案就是需要去挨個實現這些成員
static struct receiveopr armrecvdev = {
.name = "arm_recv",
.getdevdata = getarmrecvdev,
.devinit = armrecvinit,
//提交資料的函式,只是模擬而已
static int getarmrecvdev(char data)
int i, j=0;
int ret;
ret = read(fd, buf, 16);
if(ret > 0)
for(i=0; i<16; i++)
if(i%2 == 0)
data[j] = buf[i];
j++;
return (ret / 2);
else
return -1;
//裝置初始化函式
static int armrecvinit()
fd = open("/dev/power", o_rdwr);
if (fd < 0)
printf("can't open arm_recv!\n");
return -1;
else
printf("open arm_recv success!\n");
return 0;
//註冊函式,核心層初始化時候會依次呼叫各個裝置的註冊函式
int registerarmrecv(void)
return registerrecvopr(&armrecvdev);
這裡只是舉了乙個例子,具體的裝置功能當然要複雜的多,假如還有個51體系的,或者stm32的,那麼完全可以再實現兩個檔案:51recv.c和stm32.c來註冊
到核心層。
最後,來看下上層如何通過核心層來操作具體裝置
main.c---使用例項
#include "receive_manager.h"
int main(int argc, char **argv)
int ret;
char buf[8];
recvmanagerinit(); //註冊各個輸入裝置
selectrecvdev("arm_recv"); //選擇要操作的裝置
recvdevinit(); //對選擇的裝置進行初始化
while(1)
ret = getdevdata(buf); //操作裝置
printf("%d\n", ret);
簡單吧,這樣的設計使我們的程式層次感更加明了,方便管理我們的專案。這裡只是簡單的做了介紹,實際專案中使用的核心層管理要複雜的多。
C語言模式實現C 繼承和多型
這個問題主要考察的是c和c 的區別,以及c 中繼承和多型的概念。c和c 的區別 c語言是面向過程的語言,而c 是物件導向的過程。什麼是物件導向和面向過程?面向過程就是分析解決問題的步驟,然後用函式把這些步驟一步一步的進行實現,在使用的時候進行一一呼叫就行了,注重的是對於過程的分析。物件導向則是把構成...
C語言模式實現C 繼承和多型
c實現乙個struct a和struct b各包含乙個int成員a和b,要求達到b繼承了a的效果,也就是b裡面包含乙個a。並且能達到多型的效果,也就是乙個a p指向a調的是a的函式,指向b呼叫的是b的函式。1.繼承 1 c 的繼承 在c 中,可以用乙個類 子類 去繼承另乙個類 父類 子類可以得到父類...
PHP 分層模式和mvc模式
繼續昨天沒完的內容,分層開發模式。分層開發模式分析 可讀性 維護性 擴充套件性相比model1模式有了明顯改善,但是也有不足。有些頁面既充當了介面,同時又去響應使用者的各種請求,當請求過多時,頁面的結構遭到破壞,也就是說 比較亂。mvc m模型model v檢視view c控制器ctrl 它是個軟體...