LED闪烁(面向对象程序结构)
将LED闪烁(延时等待)的程序修改为面向对象的程序结构,C语言面向对象主要由结构体和函数指针实现
以后也都采用这种程序设计方法
面向对象知识
面向对象是软件开发方法,是相对于面向过程来讲的。通过把数据与方法组织为一个整体来看待,从更高的层次来进行系统建模, 更贴近事物的自然运行模式 单片机 C 语言的面向对象编程,是利用结构体,将变量、指针、函数等进行封装,达到编程更加方便、程序可读性更好、方便移植等目的。
1、结构体
结构体是由一系列具有相同类型或不同类型的数据构成的数据 集合。 常用的定义方法:
typedef struct {
变量;
指针;
函数指针;
} 结构体名称_t;
2、指针
指针是地址,指向内存中的变量。 常用的定义方法:数据类型 * 指针名;
3、函数指针
函数指针是指向函数的指针变量。 常用的定义方法:返回值类型 ( * 指针变量名) ([形参列表]);
文件整体架构
main.c -> 主函数文件,包含 main 函数等;
main.h -> 包含工程的所有头文件,都用#include" "包含进来,其他.c文件只需要包含main.h即可;
Public.c -> 公共函数文件,包含 Delay 延时函数等;
Public.h -> 基本数据类型重命名,定义包含函数指针的结构体类型,用类型定义变量并声明为外部可引用;
Sys_Init.c -> 系统初始化函数,包含 GPIO 初始化函数、上电运行指示灯等;
Sys_Init.h -> 定义包含函数指针的结构体类型,用类型定义变量并声明为外部可引用;
LED.c -> LED 外设函数,包含 LED 打开、关闭、不断翻转函数等;
LED.h -> LED端口、打开和关闭宏定义,再定义包含函数指针的结构体类型,用类型定义变量并声明为外部可引用。
编写流程
1.先创建好工程文件夹,然后创建app、user、obj三个文件夹,打开keil新建工程,魔术棒里更改工程文件到obj文件夹,C51选项导入app、user文件夹路径,回本地删除 object 和 listing 文件夹
2.user目录下添加main.c和main.h文件,在main.c文件中添加源文件的架构注释,如下面代码注释所示,如果是在其他.c文件中,则把开头的工程说明删掉即可,可以在keil工具中添加自定义代码,把这些注释加进去就行,方便以后的代码编写
/******************************************************************************
* @file main.c
* @author xxx
* @version V1.0
* @date 2022-5-3
* @Conpany
* @project LED闪烁(面向对象程序结构)
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <main.h>
/* Private define-------------------------------------------------------------*/
/* Private variables----------------------------------------------------------*/
/* Public variables-----------------------------------------------------------*/
/* Private function prototypes------------------------------------------------*/
/*
* @name main
* @brief 主函数
* @param void
* @retval int
*/
int main(void)
{
//系统初始化
//系统主循环
while(1)
{
}
}
/********************************************************
End Of File
********************************************************/
keil工具添加自定义代码方法:
1.从project面板切换到Templates面板,点击空白处,然后右键Configure Templates,跳到添加代码面板
2.在弹出的面板中添加自定义的代码块,新增后起个名字,在Text框内编写自定义代码块,也可提前写好复制进去,最后保存,重启一下keil软件,再次打开Templates面板就可以双击名字使用自己提前定义的代码块了
3.main.h头文件的架构如下所示,其他头文件也类似,如果没有需要引入的头文件则可以把Includes注释行删掉
#ifndef __MAIN_H_
#define __MAIN_H_
/* Includes ------------------------------------------------------------------*/
#include <STC15.h>
/* extern variables-----------------------------------------------------------*/
/* extern function prototypes-------------------------------------------------*/
#endif
/********************************************************
End Of File
********************************************************/
4.代码的架构写好后,就要开始编写功能代码了,一个文件里函数声明、函数实现和变量定义等都根据注释的区域来写,所以多少源文件和头文件的风格都类似,举延时函数的例子,其他代码写法都相似,就靠多写多练了,写多了就熟悉了
5.在user文件夹中新建public.c文件,该文件是存放一些公共的定义或函数的,比如数据类型重定义,延时函数;然后再新建public.h文件,用来定义数据类型;
代码的编写顺序在下面程序注释中写好,可参考着编写,也不一定非得按这顺序,熟悉逻辑后,哪一步先写后写无所谓,在需要时知道在哪里补写就行。
public.c:
/* Includes ------------------------------------------------------------------*/
#include <main.h> /*3.引入头文件,public.h被包含在了main.h头文件中*/
/* Private define-------------------------------------------------------------*/
/* Private variables----------------------------------------------------------*/
static void Delay_ms(uint16_t ms); /*6.一个或多个函数的声明*/
/* Public variables-----------------------------------------------------------*/
Public_t Public = /*7.结构体变量的初始化,用函数指针指向函数*/
{
Delay_ms
};
/* Private function prototypes------------------------------------------------*/
/*
* @name Delay_ms
* @brief 毫秒延时函数
* @param ms -> 要延时的时间
* @retval None
*/
static void Delay_ms(uint16_t ms) /*2.在public.c文件中编写一个或多个函数实现*/
{
unsigned char i, j;
while(ms--)
{
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
}
/********************************************************
End Of File
********************************************************/
public.h:
#ifndef __PUBLIC_H_
#define __PUBLIC_H_
//数据类型重定义 /*1.先在public.h文件中重定义数据类型,因为后面的函数可能会用到*/
typedef signed char sint8_t;
typedef signed short int sint16_t;
typedef signed long int sint32_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned long int uint32_t;
//结构体定义
typedef struct /*4.定义结构体,里面是函数指针,有多少个函数实现,就定义多少个函数指针*/
{
void (*Delay_ms)(uint16_t ms);
}Public_t;
/* extern variables-----------------------------------------------------------*/
extern Public_t Public; /*5.用结构体类型定义一个变量后,用extern声明为外部可调用*/
/* extern function prototypes-------------------------------------------------*/
#endif
/********************************************************
End Of File
********************************************************/
main.c:
最后在主函数中用结构体变量调用响应的函数就能实现相应的功能
/******************************************************************************
* @file main.c
* @author qzx
* @version V1.0
* @date 2022-xx-xx
* @Conpany
* @project STC15实战项目
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <main.h>
/* Private define-------------------------------------------------------------*/
/* Private variables----------------------------------------------------------*/
/* Public variables-----------------------------------------------------------*/
/* Private function prototypes------------------------------------------------*/
/*
* @name main
* @brief 主函数
* @param void
* @retval int
*/
int main(void)
{
//系统主循环
while(1)
{
Public.Delay_ms(1000); /*8.通过结构体变量调用Delay_ms函数,实现延时功能*/
}
}
/********************************************************
End Of File
********************************************************/