自己写库--构建库函数编程

1、GPIO寄存器映射代码的优化

这是GPIO寄存器的映射,看起来不多,但是如果你遇到的寄存器很多的情况下,你就需要写多行的这样的代码,那么有没有什么办法可以对这段代码进行优化呢? 

#define GPIOE_CRL	   *(unsigned int *)(GPIOE_BASE+0x00)
#define GPIOE_CRH      *(unsigned int *)(GPIOE_BASE+0x04)
#define GPIOE_IDR      *(unsigned int *)(GPIOE_BASE+0x08)
#define GPIOE_ODR      *(unsigned int *)(GPIOE_BASE+0x0C)
#define GPIOE_BSRR     *(unsigned int *)(GPIOE_BASE+0x10)
#define GPIOE_BRR      *(unsigned int *)(GPIOE_BASE+0x14)
#define GPIOE_LCKR     *(unsigned int *)(GPIOE_BASE+0x18)

 优化思路:采用结构体的方式。因为每个寄存器之间间隔了4个字节是有规律可寻的。通过指针来访问。相当于只需要知道这个寄存器的基地址就行。最后再通过强制类型转换成指针类型,通过操作指针来完成功能。

typedef unsigned int u32;
typedef unsigned short u16;
//代码优化
typedef struct
{
	u32 CRL;
	u32 CRH;
	u32 IDR;
	u32 ODR;
	u32 BSRR;
	u32 BRR;
	u32 LCKR;
}GPIO_TypeDef;

#define GPIOE ((GPIO_TypeDef*)GPIOE_BASE)
//库函数雏形
	RCC_APB2ENR |= (1<<6);
	GPIOE->CRL &=~(0x0F<<(4*5));
	GPIOE->CRL |= (3<<(5*4));
	GPIOE->ODR |= (1<<5);
	while(1)
	{
		GPIOE->ODR |= (1<<5);
		delay(0xFFFFF);
		GPIOE->ODR &= ~(1<<5);
		delay(0xFFFFF);
		
		
	}

 

2、RCC结构体 

//RCC
typedef struct
{
	u32 CR;
	u32 CFGR;
	u32 CIR;
	u32 APB2RSTR;
	u32 APB1RSTR;
	u32 AHBENR;
	u32 APB2ENR;
	u32 APB1ENR;
	u32 BDCR;
	u32 CSR;
}RCC_TypeDef;
#define RCC   ((RCC_TypeDef*)RCC_BASE)

3、端口置位和复位函数 

引脚定义 

#ifndef __STM32F10X_GPIO_H
#define __STM32F10X_GPIO_H

#include "stm32f10x.h"

//引脚宏定义
#define GPIO_Pin_0   ((u16)0x0001)
#define GPIO_Pin_1   ((u16)0x0002)
#define GPIO_Pin_2   ((u16)0x0004)
#define GPIO_Pin_3   ((u16)0x0008)
#define GPIO_Pin_4   ((u16)0x0010)
#define GPIO_Pin_5   ((u16)0x0020)
#define GPIO_Pin_6   ((u16)0x0040)
#define GPIO_Pin_7   ((u16)0x0080)

#define GPIO_Pin_8   ((u16)0x0100)
#define GPIO_Pin_9   ((u16)0x0200)
#define GPIO_Pin_10  ((u16)0x0400)
#define GPIO_Pin_11  ((u16)0x0800)
#define GPIO_Pin_12  ((u16)0x1000)
#define GPIO_Pin_13  ((u16)0x2000)
#define GPIO_Pin_14  ((u16)0x4000)
#define GPIO_Pin_15  ((u16)0x8000)
#define GPIO_Pin_All ((u16)0xFFFF)

void GPIO_SetBits(GPIO_TypeDef *GPIOx,u16 GPIO_PIN);
void GPIO_ReSetBits(GPIO_TypeDef *GPIOx,u16 GPIO_PIN);
#endif 

 置位和复位函数

#include "stm32f10x_gpio.h"

void GPIO_SetBits(GPIO_TypeDef *GPIOx,u16 GPIO_PIN)
{
	GPIOx->BSRR |= GPIO_PIN;
}

void GPIO_ReSetBits(GPIO_TypeDef *GPIOx,u16 GPIO_PIN)
{
	GPIOx->BRR |= GPIO_PIN;
}

函数实现 

//库函数雏形
	RCC->APB2ENR |= (1<<6);
	GPIOE->CRL &=~(0x0F<<(4*5));
	GPIOE->CRL |= (3<<(5*4));
	GPIO_SetBits(GPIOE,GPIO_Pin_5);
	while(1)
	{
		GPIO_SetBits(GPIOE,GPIO_Pin_5);
		delay(0xFFFFF);
		GPIO_ReSetBits(GPIOE,GPIO_Pin_5);
		delay(0xFFFFF);
		
	}

 

4、初始化结构体函数

 

void GPIO_Init(GPIO_TypeDef*GPIOx,GPIO_InitTypeDef* GPIO_Initstruct)
{
	u32 currentmode = 0x00,currentpin = 0x00,pinpos = 0x00,pos = 0x00;
	u32 tmpreg = 0x00,pinmask = 0x00;
	//读取GPIO的第四位模式
	currentmode = ((u32)GPIO_Initstruct->GPIO_Mode ) & ((u32)0x0F);
	//判断bit4是1还是0,1是输入,0是输出
	if((((u32)GPIO_Initstruct->GPIO_Mode) & ((u32)0x10)) != 0x00)
	{
		//输出模式,设置输出速度
		currentmode |= (u32)GPIO_Initstruct->GPIO_Speed;
	}
	
	//GPIO_CRL寄存器配置,低八位
	if(((u32)GPIO_Initstruct->GPIO_Pin &((u32)0x00FF))!=0x00)
	{
		//先备份CRL寄存器的值
		tmpreg = GPIOx->CRL;
		
		//循环,从Pin0开始配对,找出具体的Pin
		for(pinpos = 0x00;pinpos<0x08;pinpos++)
		{
			//将pos位pinpos左移一位
			pos = ((u32)0x01)<<pinpos;
			//将pos和GPIO_PIN相与
			currentpin = ((GPIO_Initstruct->GPIO_Pin)&pos);
			
			//如果pos == currentpin则找到pin
			if(currentpin == pos)
			{
				//pinpos的值左移两位(乘以4),因为寄存器中4个寄存器位置配置一个引脚
				pos = pinpos<<2;
				
				//把控制这个引脚的4个寄存器位清零,其他寄存器不变
				pinmask = ((u32)0x0F)<<pos;
				tmpreg &= ~pinmask;
				
				//向寄存器写入要配置的引脚的模式
				tmpreg  |= (currentmode<<pos);
				
				//判断是否位下拉输入模式
				if(GPIO_Initstruct->GPIO_Mode == GPIO_Mode_IPD)
				{
					//下拉模式,引脚置0
					GPIOx->BRR = (((u32)0x01)<<pinpos);
				}
				else
				{
					if(GPIO_Initstruct->GPIO_Mode == GPIO_Mode_IPU)
					{
						//上拉模式,引脚默认为1
						GPIOx->BSRR = (((u32)0x01)<<pinpos);
					}
				}
			}
		}
		//把前面暂存的值写入
		GPIOx->CRL = tmpreg;
	}
	
	//配置高八位
	if(GPIO_Initstruct->GPIO_Pin>0X00FF)
	{
		tmpreg = GPIOx->CRH;
		//循环,从pin8开始
		for(pinpos = 0x00;pinpos<0x08;pinpos++)
		{
			pos = ((u32)0x01)<<(pinpos+0x08);
			
			将pos和GPIO_PIN相与
			currentpin = ((GPIO_Initstruct->GPIO_Pin)&pos);
			
			//如果pos == currentpin则找到pin
			if(currentpin == pos)
			{
				//pinpos的值左移两位(乘以4),因为寄存器中4个寄存器位置配置一个引脚
				pos = pinpos<<2;
				
				//把控制这个引脚的4个寄存器位清零,其他寄存器不变
				pinmask = ((u32)0x0F)<<pos;
				tmpreg &= ~pinmask;
				
				//向寄存器写入要配置的引脚的模式
				tmpreg  |= (currentmode<<pos);
				
				//判断是否位下拉输入模式
				if(GPIO_Initstruct->GPIO_Mode == GPIO_Mode_IPD)
				{
					//下拉模式,引脚置0
					GPIOx->BRR = (((u32)0x01)<<(pinpos+0x08));
				}
				else
				{
					if(GPIO_Initstruct->GPIO_Mode == GPIO_Mode_IPU)
					{
						//上拉模式,引脚默认为1
						GPIOx->BSRR = (((u32)0x01)<<(pinpos+0x08));
					}
				}
			}
		}
		
		GPIOx->CRH = tmpreg;
	}
}

 

 修改后的代码

//库函数雏形
	RCC->APB2ENR |= (1<<6);
//	GPIOE->CRL &=~(0x0F<<(4*5));
//	GPIOE->CRL |= (3<<(5*4));
    GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHZ;
	GPIO_Init(GPIOE,&GPIO_InitStruct);
	GPIO_SetBits(GPIOE,GPIO_Pin_5);
	while(1)
	{
		GPIO_SetBits(GPIOE,GPIO_Pin_5);
		delay(0xFFFFF);
		GPIO_ReSetBits(GPIOE,GPIO_Pin_5);
		delay(0xFFFFF);
		
	}
}

 5、提高代码的可移植性

可以将变量设置成宏定义,移植代码时就可以直接修改宏定义的部分。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值