1. 程式人生 > >微控制器高階裸機程式設計(一)-- 資料驅動程式

微控制器高階裸機程式設計(一)-- 資料驅動程式

我理解的所謂資料驅動程式的方法,簡單而言:將資料與程式分析,將程式碼邏輯的組織轉換成數字規律的統計。即將資料作為一個要處理的指令碼(當做資料庫),然後程式作為直譯器,將指令碼的內容用程式碼邏輯解釋出來,實現程式設計功能。

這就要求我們將程式碼邏輯分解出其內在資料關係,這樣我們就可以寫出與資料無關的函式,這樣的函式通用性很大,利於複用,耦合性也比較低,利於修改,且修改後不易出錯。

這樣的方法也有壞處,就是可讀性變差,解決的辦法就是多寫點關於邏輯的註釋。

下面舉個例子:(來自書籍--微控制器程式設計魔法師之高階裸程式設計思想,挺好的一本書,可以看看,可以去下載下載連結處,待有緣人! )

(1)要實現如下波形:

(2)我們 一般的實現方法:將上面分成16段(依據是波形存在不一樣的時候作為分界點),每段單獨分析。程式碼如下(使用51微控制器實現)。

#include <reg51.h>

sbit P10=P1^0;
sbit P11=P1^1;
sbit P12=P1^2;
sbit P13=P1^3;

void delay(unsigned char d, unsigned int t)
{
	unsigned int i;

	P1 = P1 & 0xF0 | d;
	for(i=0; i<t; i++);
}

main(void)
{
	while(1)
	{
		delay(0x00, 749);		// 階段1
		delay(0x01, 251);		// 階段2

		delay(0x00, 749);		// 階段3
		delay(0x03, 251);		// 階段4

		delay(0x00, 749);		// 階段5
		delay(0x01, 251);		// 階段6

		delay(0x00, 749);		// 階段7
		delay(0x07, 251);		// 階段8

		delay(0x00, 749);		// 階段9
		delay(0x01, 251);		// 階段10

		delay(0x00, 749);		// 論僇11
		delay(0x03, 251);		// 論僇12

		delay(0x00, 749);		// 階段13
		delay(0x01, 251);		// 階段14

		delay(0x00, 749);		// 階段15
		delay(0x0F, 251);		// 階段16
	}
}

(3)而採用資料驅動程式的方法:將每個階段分離出資料,然後用一個函式統一處理。本例中使用陣列來儲存代表各個階段的邏輯的資料,接著用一段程式碼就可解決,來程式碼如下:

#include <reg51.h>

sbit P10=P1^0;
sbit P11=P1^1;
sbit P12=P1^2;
sbit P13=P1^3;

#define STAGES		16
unsigned char code P1_1234[] = {0, 1, 0, 3, 0, 1, 0, 7, 0, 1, 0, 3, 0, 1, 0, 15};
unsigned int code Dts[] = {749, 251, 749, 251, 749, 251, 749, 251, 749, 251, 749, 251, 749, 251, 749, 251};

void delay(unsigned char d, unsigned int t)
{
	unsigned int i;

	P1 = P1 & 0xF0 | d;
	for(i=0; i<t; i++);
}

main(void)
{
	int i;

	while(1)
	{
		for(i=0; i<STAGES; i++)
			delay(P1_1234[i], Dts[i]);
	}
}

(4)好處:似乎沒有看出了,犧牲了易讀性,有得必有失,我們會的得到什麼?

再舉幾個例子:實現以下波形。對於這個波形,如果我們不採用資料驅動程式的方法,那麼相當於重寫(重新分階段,不難但是繁瑣),而使用這種高階的方法後,直譯器程式碼一個字母都不用改變。

資料驅動程式的程式碼如下:

#include <reg51.h>

sbit P10=P1^0;
sbit P11=P1^1;
sbit P12=P1^2;
sbit P13=P1^3;

#define STAGES		8
unsigned char code P1_1234[] = {0, 1, 3, 7, 15, 7, 3, 1};

void delay(unsigned char d, unsigned int t)
{
	unsigned int i;

	P1 = P1 & 0xF0 | d;
	for(i=0; i<t; i++);
}

main(void)
{
	int i;

	while(1)
	{
		for(i=0; i<STAGES; i++)
			delay(P1_1234[i], 500);
	}
}

(5)總結:

雖然資料驅動程式碼這種高階的方法不是萬能,但是對於相似的程式設計要求,則給我們提供了一種可複用的方法,避免一些簡單卻繁瑣的工作任務。

還有, 用這種方法記得寫註釋,不然不僅別人看不懂, 就連幾天後的你再次回顧時,都不知道是怎麼寫出來的。