设计思想
1.采用通用性设计思想,屏蔽底层硬件差异,简化程序移植过程。
2.采用层次化设计思想,硬件抽象层调用驱动层,应用层则调用硬件抽象层。
3.采用模块化设计思想,以外围电路模块为单元进行设计。
板级支持包BSP
应用层---调用BSP提供的接口函数API
操作系统--调用BSP提供的接口函数API
板级支持包--BSP_LED_Init/BSP_LED_On/BSP_LED_Off
驱动程序寄存器或者固件库--硬件平台8051/MSP430/STM32
设计实现:
以外围电路模块为单元设计,分文头文件和源文件
头文件:宏定义、枚举类型、结构体类型等数据类型的定义,以及提供给外部调用的接口函数的声明
源文件:变量的定义、硬件引脚的定义以及接口函数的具体实现
指示灯模块的硬件抽象层设计
指示灯模块分成BSP_LED.h和BSP_LED.c两个文件
设计时假设有4个指示灯LEDO~LED3,均采用高电平驱动方式,对应的控制引脚依次为PA0、PBO、PCO和PDO
指示灯模块的BSP_LED.h 文件:
文件基本描述:
模块名称: 指示灯驱动模块 文件名:BSP_LED.h 说明:头文件,提供自定义数据类型及外部调用的接口函数的声明
版本号: V2.0 修改记录:版本号,日期,作者
#ifndef __BSP_LED_H #define __BSP_LED_H 避免重复包含
用户自定义数据类型:
typedef enum{LED0 = 0,LED1 = 1,LED2 = 2,LED3 = 3}LED_INDEX:定义指示灯序号的数据类型,用枚举类型实现,四个枚举常量表示4个指示灯
本模块提供给外部函数调用的函数(提供给外部使用函数的声明)
extern void BSP_LED_Init (LED_INDEX led);//指示灯初始化
extern void BSP_LED_On (LED_INDEX led);//指示灯开启
extern void BSP_LED_Off (LED_INDEX led);//指示灯关闭
extern void BSP_LED_Toggle (LED_INDEX led);//指示灯状态翻转
指示灯模块的 BSP LED.c 文件
文件基本描述:
模块名称: 指示灯驱动模块 文件名 : BSP_Led.c 说明: 驱动LED指示灯 版本号: V2.0
*修改记录:1、将LED驱动采用结构体指针数组的形式改写,移植时只需要修改LED的数量,引脚定义以及存放端口和引脚的两个数组
版本号 日期 作者
模块移植性说明(模块的移植方法)
1.如果用户的LED指示灯个数小于等于4个,可以将多余指示灯的引脚定义全部定义为和第1个指示灯一样,其余代码不做任何修改
2.如果用户的LED指示灯个数大于k个,需要改如下以容:
(1)增加.h文件中LED_INDEX类型的枚举常量
(2)修改指示灯数量定义LEDn
(3)修改指示灯控制引脚的定义
(4)修改端口和引脚两个数组: GPIO_PORT[LEDn]和GPIO_PIN[LEDn]
(5)修改引脚的时钟控制宏定义LEDX GPIO CLK ENABLE( __NDEX__)的内容
添加HAL库头文件,以便使用HAL库提供的数据类型和接口函数
添加本模块自身的头文件,以便使用指示灯序号LED INDEX这个数据类型
#include "stm32f4xx hal.h"
#include "BSP_LED.h"
指示灯硬件接口定义
// 指示灯数量
#define LEDn 4
// 指示灯0指示灯控制引脚的宏定义,引脚号,端口号,端口时钟使能
#define LEDO PIN GPIO PIN_0 // PAO
#define LED GPIO PORT GPIOA
#define LEDO GPIO CLK ENABLE() HAL_RCC_GPIOA CLK ENABLE()
// 指示灯1
#define LED1_PIN GPIO_PIN_0 // PBO
#define LED1 GPIO PORT GPIOB
#define LED1 GPIO CLK ENABLE()HAL RCC GPIOB CLK ENABLE()
//端口数组,数组中存放的都是指示灯控制引脚所属端口,数据类型为只想端口寄存器的结构体指针GPIO_TypeDef
GPIO_TypeDef *GPIO_PORT[LEDn] = {LEDO_GPIO_PORT,LED1_GPIO PORT,LED2_GPIO_PORT,LED3_GPIO_PORT};
// 引脚数组,数组中存放的都是指示灯控制引脚
const uint16 t GPIO PIN[LEDn] = {LEDO_PIN,LED1_PIN,LED2_PIN,LED3_PIN,};
// 端口时钟使能宏定义,使用do while(e)的形式是为了避免宏展开时发生错误
#define LEDX GPIO CLK_ENABLE(__INDEX__) do{\
If(( INDEX) == 0) LEDO GPIO CLK ENABLE();\
else if(( INDEX ) == 1)LED1 GPIO CLK ENABLE();\
else if((_INDEX ) == 2)LED2 GPIO CLK ENABLE();\
else if(( INDEX ) == 3)LED3 GPIO CLK ENABLE();\
}while(0)
接口函数的实现:
1.指示灯引脚初始化函数BSP_LED_Init
函数的基本描述
函数名称 函数功能 入口参数 返回值 使用注意
void BSP LED Init(LED INDEX Led)
{
GPIO InitTypeDef GPIO InitStruct = {0};//定义引脚初始化变量,并赋初值为0
LEDX GPIO_CLK_ENABLE(Led); //使能引脚所属端口的时钟
/* Configure the GPIO LED pin */
GPI0_Initstruct.Pin = GPIO_PIN[Led];
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO SPEED_FREQ LOW;
HAL_GPIO_Init(GPIO_PORT[Led], &GPIO_InitStruct);//以上配置引脚参数并初始化引脚
HAL GPIO Writepin(GPIO PORT[Led],GPIO_PIN[Led], GPIO_PIN_RESET);//设置引脚初始电平
}
接口函数之指示灯开启: BSP_LED_On
调用接口函数HAL_GPIO_WritePin
void BSP_LED On(LED INDEX Led)
{
HAL_GPIO_WritePin(GPIO_PORT[Led], GPIO_PIN[Led], GPIO_PIN_SET);
}
接口函数之指示灯关闭: BSP_LED_Off
调用接口函数HAL_GPIO_WritePin
void BSP_LED_Off(LED INDEX Led)
{
HAL_GPIO_WritePin(GPIO_PORT[Led], GPIO_PIN[Led], GPIO_PIN_RESET);
}
接口函数之指示灯状态翻转: BSP_LED_Toggle
调用接口函数HAL_GPIO_TogglePin
void BSP_LED_Toggle(LED INDEX Led)
{
HAL_GPIO_WritePin(GPIO_PORT[Led], GPIO_PIN[Led]);
}
设计总结