使用分層模型複用代碼(GPIO)

代碼獲取

本文代碼託管於github上,歡迎各位star,https://github.com/zrw269113179/drv_pin

分層模型

分層模型可以使代碼的應用層邏輯與硬件解耦合,可以使你的代碼高度複用,完全解耦合,並且可以使你快速上手任意一款mcu。說了這麼多好處,如何具體實現?簡單來說就是定義一套統一的入口函數,無論什麼mcu都可以通過這套函數訪問硬件。

具體實現

本文講述的爲GPIO模型的具體實現。首先需要對GPIO模型進行抽象,顯而易見,GPIO只有2個功能,輸入和輸出。因此我們只需要完成以下這些函數:
1、pin_mode_set:端口模式設置
2、pin_write:端口輸出
3、pin_read:讀取端口電平
4、pin_irq_set:外部中斷設置
編寫完成這些函數後,在應用層只需要調用pin_write、pin_read就可以完成對端口的操作。
確定了函數名後,我們要對函數參數進行確定,因爲不同芯片對於GPIO的命名是不同的,有些芯片命名爲GPIOA、GPIOB…而有些命名爲GPIO1、GPIO2等,這裏我們拋棄芯片原有的port+pin來表示一個端口的模式,而直接用1234端口號來表示一個端口。
這裏我們以stm8l052舉例。

stm8l052引腳圖這裏我們用1來表示PA0,64表示PE7。
首先我們建立一張索引圖,將引腳號和端口名稱建立聯繫。

static unsigned char pin_map[] ={    
(1 << 4) + 0, (1 << 4) + 1, (1 << 4) + 2, (1 << 4) + 3, (1 << 4) + 4, (1 << 4) + 5, (1 << 4) + 6, 
(1 << 4) + 7, (0 << 4) + 0, (0 << 4) + 0, (0 << 4) + 0, (0 << 4) + 0, (0 << 4) + 0, (7 << 4) + 0, 
(7 << 4) + 1, (7 << 4) + 2, (7 << 4) + 3, (0 << 4) + 0, (5 << 4) + 0, (5 << 4) + 1, (5 << 4) + 2,
(5 << 4) + 3, (5 << 4) + 4, (5 << 4) + 5, (4 << 4) + 0, (4 << 4) + 1, (4 << 4) + 2, (4 << 4) + 3, 
(0 << 4) + 0, (0 << 4) + 0, (2 << 4) + 0, (2 << 4) + 1, (2 << 4) + 2, (2 << 4) + 3, (2 << 4) + 4, 
(2 << 4) + 5, (2 << 4) + 6, (2 << 4) + 7, (6 << 4) + 0, (6 << 4) + 1, (6 << 4) + 4, (6 << 4) + 5, 
(6 << 4) + 6, (6 << 4) + 7, (4 << 4) + 4, (4 << 4) + 5, (4 << 4) + 6, (4 << 4) + 7, (7 << 4) + 4, 
(7 << 4) + 5, (7 << 4) + 6, (7 << 4) + 7, (3 << 4) + 0, (3 << 4) + 1, (0 << 4) + 0, (0 << 4) + 0,
(3 << 4) + 2, (3 << 4) + 3, (3 << 4) + 4, (3 << 4) + 5, (3 << 4) + 6, (3 << 4) + 7, (5 << 4) + 6, 
(5 << 4) + 7
};

用一個unsigned char 表示存儲port和pin,其中前4位爲port號,1:GPIOA,2:GPIOB以此類推,後4位爲pin號,0:GPIO_Pin_0,1:GPIO_Pin_1以此類推,當數爲0((0 << 4) + 0)時表示該引腳沒有gpio功能(芯片上的vss,vdd等腳)。具體如何定義可以根據芯片靈活更改。
然後就可以編寫具體函數了,以pin_write()爲例:

void pin_write(unsigned char id, unsigned char level)
{    
	GPIO_TypeDef *port;    
	uint8_t pin;    
	switch (pin_map[id - 1] >> 4)    
	{    
		case 1:        
			port = GPIOA;        
		break;
    		case 2:        
    			port = GPIOB;        
    		break;
    		case 3:        
    			port = GPIOC;        
    		break;
    		case 4:        
    			port = GPIOD;        
    		break;
    		case 5:        
    			port = GPIOE;        
    		break;
    		case 6:        
    			port = GPIOF;        
    		break;
    		case 7:        
    			port = GPIOG;        
    		break;
    		default:        
    			port = GPIOA;        
    		break;    
    	}    
    	pin = 1 << (pin_map[id - 1] & 0xf);    
    	if (level == 0)    
    	{        
    		GPIO_ResetBits( port, pin );    
    	}    
    	else   
    	{        
    		GPIO_SetBits( port, pin );    
    	}
}

代碼很簡單,只需要調用pin_write(1,1);就可以使PA0輸出高電平了(不要忘了初始化)。

更換芯片

完成上述工作後,我們的應用層所有關於GPIO的代碼將通過這個drv_pin.c\drv_pin.h接管,又由於該文僅控制輸入輸出,所以當芯片更換後,只需更換drv_pin.c\drv_pin.h文件即可,新芯片的drv_pin.c\drv_pin.h只需完成drv_pin.h中的功能即可。

優缺點

優點

1、drv_pin.c和drv_pin.h只需編寫1遍即可重複使用,將這兩個文件交給新手,新手完全不需要重新讀datasheet就可以馬上上手,極大的減少項目時間,並且提高穩定性。
2、應用層完全與硬件隔離,應用層不再出現硬件提供的庫的代碼,這樣我們寫的一些其他組件就無需更改,如模擬iic、spi,當更換項目後就需要更改這些函數內部的代碼,如果使用drv_pin就不需要更改,有利於模塊的封裝。

缺點

因爲操作需要多一層代理,因此會佔用一些程序空間,在進行gpio操作時會略微增加一些運行時間(忽略不計)。
總體來說還是優點大於缺點的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章