STM32物联网项目之程序框架

前言:

这个系列,我主要写我用32f103实现的各种功能模块,已经程序编写过程中,硬件调试中出现的问题,一边记录,一边分享,一边复盘。

使用的是STM32cubemax,自动生成代码,所以为了保证程序可读性,逻辑性,我们在不影响系统自动生成代码的情况下,自己要有自己的程序框架,这样,在我们后期不断增加模块功能时,改动更小,兼容性更强,可阅读性更好。


目录

1.STM32CUBEMAX自动生成代码

1.1软件配置 

2.系统代码 

2.1包含的头文件 

2.2系统时钟函数

2.3系统初始化 

3. 标准化程序框架

3.1MyApplication.h文件

3.2main.c文件 

3.3.1头文件

3.3.2源文件 

3.3.3run函数


1.STM32CUBEMAX自动生成代码

为了方便演示程序框架,我用最简单也是最入门的点亮LED灯来操作。

STM32物联网项目之程序框架_第1张图片

1.1软件配置 

 首先,我们需要配置stm32cubemax的各种配置,包括芯片选型,GPIO外设,时钟RCC,等等,如下图所示:

 GPIO口的配置,推挽还是开漏,已经不同选择的原因,rcc时钟频率的配置,这些都跟挂载总线有关,时钟源这些等等底层逻辑相关的,后期我会单独分享复盘底层逻辑;这个章节我主要想介绍程序框架。

2.系统代码 

当我们配置好cubemax之后,点击GENERATE CODE 就会在我们保存的文件路径底下自动生成project,如下图所示:

因为我是用点亮led灯来演示的,所以系统除了主函数,只有gpio,后期我们用到的模块越多,源文件也会相应的增加,我们主要分析一下系统生成文件都包含那些以及主要的功能

2.1包含的头文件 

引用了main.h以及gpio.h这两个头文件,这两个头文件内部主要是对gpio口的引脚及端口进行定义 ,包括gpio初始化的声明。

2.2系统时钟函数

我们配置完系统时钟之后,这些文函数就会自动生成。

2.3系统初始化 

STM32物联网项目之程序框架_第2张图片 

系统初始化部分就包含了 HAL库的初始化以及gpio的初始化。

3. 标准化程序框架

我们在不影响上述文件的情况下,新增属于我们自己的框架文件,在保证接口固定的情况下,每次只修改部分接口函数即可。

1、新增MyApplication文件夹,放置4个标准c文件,分别是公共文件,回调文件,系统文件,用户初始化文件,后续应用代码均放在此文件夹;

2、新增MyApplication.h文件,包含所有用户代码的头文件与外设头文件,调整外设或用户文件,只需要调整此文件内的相应头文件即可;

3、main.c文件标准化

3.1MyApplication.h文件

#ifndef __MyApplication_H__
#define __MyApplication_H__

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"

#include "stdio.h"
#include "stdlib.h"
#include "System.h"
#include "Public.h"
#include "MyInit.h"
#endif

我们将所有能用到的头文件集中在一个大的头文件中,只要所有源文件调用这一个头文件即可。

3.2main.c文件 

//调用头文件
/* USER CODE BEGIN Includes */
#include "MyApplication.h"
/* USER CODE END Includes */

//初始化
  /* USER CODE BEGIN 2 */
  MyInit.Peripheral_Set();	//Óû§³õʼ»¯
  /* USER CODE END 2 */

//主循环
  while (1)
  {
    System.Run();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

//标准化错误处理函数
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  System.Error_Handler();
  /* USER CODE END Error_Handler_Debug */
}
//标准化断言失败处理函数
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
	System.Assert_Failed();
  /* USER CODE END 6 */
}

 我们定义一个标准化的main.c文件,在这个文件中我们把实现的功能放入system函数中,并添加标准初始化文件,用来初始化单片机的上电状态,已经标准化断言失败文件,错误处理文件。

3.3system文件

3.3.1头文件

typedef struct
{
	void (*Run)(void);
	void (*Error_Handler)(void);
	void (*Assert_Failed)(void);
} System_t;

/* extern variables-----------------------------------------------------------*/
extern System_t  System;
/* extern function prototypes-------------------------------------------------*/

#endif

 我们用结构体封住了三个函数指针,分别指向run函数,错误处理函数,和断言失败函数,结构体封装的好处 就是我们调用函数时候,只需要用指针寻址解引用,这样的话如果函数需要修改的话,不影响地址指向,也就是说主函数并不需要修改,我们只需要修改指向的函数内容即可。

3.3.2源文件 

typedef struct
{
	void (*Run)(void);
	void (*Error_Handler)(void);
	void (*Assert_Failed)(void);
} System_t;

/* extern variables-----------------------------------------------------------*/
extern System_t  System;
/* extern function prototypes-------------------------------------------------*/

#endif

 主要定义结构体System以及3个函数,并将3个函数的名称(首地址)赋值给System结构体,完成结构体的初始化。  如此一来,main.c文件可以通过System结构体的函数指针调用System.c文件的3个函数了。

3.3.3run函数

static void Run()
{
	HAL_Delay(1000);
	HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
}

 我们要实现的功能模块在这里实现就可以了,我们只是点亮小灯,所以功能简单,延时函数以及翻转灯光就行。

 

 

 

 

 

 

你可能感兴趣的:(物联网)