使用分层模型复用代码(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操作时会略微增加一些运行时间(忽略不计)。
总体来说还是优点大于缺点的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝忧云枫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值