前言
ps:可直接跳到效果展示
众所周知CUBEMX可以生成代码,图形界面可以方便用户进行STM32的配置,有天我就在想能否用户改变生成后的代码,于是就有了下面的文章。
一、使用默认模板
直接进入Project Manager页面。
我们看一下官方的说明
生成了一些外设信息,这些都是通过FreeMarker模板引擎代码生成的,具体命令以及函数可以去官网查看。
二、使用自定义模板
自定义的模板必须要用以下代码作为开头
[#ftl]
[#list configs as dt]
[#assign data = dt]
[#assign peripheralParams =dt.peripheralParams]
[#assign peripheralGPIOParams =dt.peripheralGPIOParams]
[#assign usedIPs =dt.usedIPs]
并且用以下作为结尾
[/#list]
在这里我们想生成两个文件bsp.c bsp.h,首先在这个目录下创建两个名为bsp_c.ftl bsp_h.ftl
由于这个文件夹受保护我们用cmd的notepad创建
中间代码这里以安富莱的bsp.c为例
/*
*********************************************************************************************************
*
* 模块名称 : BSP模块(For STM32F429)
* 文件名称 : bsp.c
* 版 本 : V1.0
* 说 明 : 这是硬件底层驱动程序的主文件。每个c文件可以 #include "bsp.h" 来包含所有的外设驱动模块。
* bsp = Borad surport packet 板级支持包
* 修改记录 :
* 版本号 日期 作者 说明
* V1.0 2018-07-29 Eric2013 正式发布
*
* Copyright (C), 2018-2030, 安富莱电子 www.armfly.com
*
*********************************************************************************************************
*/
#include "bsp.h"
/*
*********************************************************************************************************
* 函数声明
*********************************************************************************************************
*/
static void SystemClock_Config(void);
/*
*********************************************************************************************************
* 函 数 名: bsp_Init
* 功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_Init(void)
{
/*
STM32H429 HAL 库初始化,此时系统用的还是F429自带的16MHz,HSI时钟:
- 调用函数HAL_InitTick,初始化滴答时钟中断1ms。
- 设置NVIV优先级分组为4。
*/
HAL_Init();
/*
配置系统时钟到168MHz
- 切换使用HSE。
- 此函数会更新全局变量SystemCoreClock,并重新配置HAL_InitTick。
*/
SystemClock_Config();
/*
Event Recorder:
- 可用于代码执行时间测量,MDK5.25及其以上版本才支持,IAR不支持。
- 默认不开启,如果要使能此选项,务必看V5开发板用户手册第8章
*/
#if Enable_EventRecorder == 1
/* 初始化EventRecorder并开启 */
EventRecorderInitialize(EventRecordAll, 1U);
EventRecorderStart();
#endif
bsp_InitKey(); /* 按键初始化,要放在滴答定时器之前,因为按钮检测是通过滴答定时器扫描 */
bsp_InitTimer(); /* 初始化滴答定时器 */
bsp_InitUart(); /* 初始化串口 */
bsp_InitExtIO(); /* 初始化扩展IO */
bsp_InitLed(); /* 初始化LED */
}
/*
*********************************************************************************************************
* 函 数 名: SystemClock_Config
* 功能说明: 初始化系统时钟
* System Clock source = PLL (HSE)
* SYSCLK(Hz) = 168000000 (CPU Clock)
* HCLK = SYSCLK / 1 = 168000000 (AHB1Periph)
* PCLK2 = HCLK / 2 = 84000000 (APB2Periph)
* PCLK1 = HCLK / 4 = 42000000 (APB1Periph)
* HSE Frequency(Hz) = 25000000
* PLL_M = 25
* PLL_N = 336
* PLL_P = 2
* PLL_Q = 4
* VDD(V) = 3.3
* Flash Latency(WS) = 5
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
/* 芯片内部的LDO稳压器输出的电压范围,选用的PWR_REGULATOR_VOLTAGE_SCALE1 */
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/* 使能HSE,并选择HSE作为PLL时钟源 */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler(__FILE__, __LINE__);
}
/*
选择PLL的输出作为系统时钟
HCLK = SYSCLK / 1 (AHB1Periph)
PCLK2 = HCLK / 2 (APB2Periph)
PCLK1 = HCLK / 4 (APB1Periph)
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
/* 此函数会更新SystemCoreClock,并重新配置HAL_InitTick */
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler(__FILE__, __LINE__);
}
/* 使能SYS时钟和IO补偿 */
__HAL_RCC_SYSCFG_CLK_ENABLE() ;
HAL_EnableCompensationCell();
}
/*
*********************************************************************************************************
* 函 数 名: Error_Handler
* 形 参: file : 源代码文件名称。关键字 __FILE__ 表示源代码文件名。
* line :代码行号。关键字 __LINE__ 表示源代码行号
* 返 回 值: 无
* Error_Handler(__FILE__, __LINE__);
*********************************************************************************************************
*/
void Error_Handler(char *file, uint32_t line)
{
/*
用户可以添加自己的代码报告源代码文件名和代码行号,比如将错误文件和行号打印到串口
printf("Wrong parameters value: file %s on line %d\r\n", file, line)
*/
/* 这是一个死循环,断言失败时程序会在此处死机,以便于用户查错 */
if (line == 0)
{
return;
}
while(1)
{
}
}
/*
*********************************************************************************************************
* 函 数 名: bsp_RunPer10ms
* 功能说明: 该函数每隔10ms被Systick中断调用1次。详见 bsp_timer.c的定时中断服务程序。一些处理时间要求不严格的
* 任务可以放在此函数。比如:按键扫描、蜂鸣器鸣叫控制等。
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_RunPer10ms(void)
{
bsp_KeyScan10ms();
}
/*
*********************************************************************************************************
* 函 数 名: bsp_RunPer1ms
* 功能说明: 该函数每隔1ms被Systick中断调用1次。详见 bsp_timer.c的定时中断服务程序。一些需要周期性处理的事务
* 可以放在此函数。比如:触摸坐标扫描。
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_RunPer1ms(void)
{
}
/*
*********************************************************************************************************
* 函 数 名: bsp_Idle
* 功能说明: 空闲时执行的函数。一般主程序在for和while循环程序体中需要插入 CPU_IDLE() 宏来调用本函数。
* 本函数缺省为空操作。用户可以添加喂狗、设置CPU进入休眠模式的功能。
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_Idle(void)
{
/* --- 喂狗 */
/* --- 让CPU进入休眠,由Systick定时中断唤醒或者其他中断唤醒 */
/* 例如 emWin 图形库,可以插入图形库需要的轮询函数 */
//GUI_Exec();
/* 例如 uIP 协议,可以插入uip轮询函数 */
//TOUCH_CapScan();
}
/*
*********************************************************************************************************
* 函 数 名: HAL_Delay
* 功能说明: 重定向毫秒延迟函数。替换HAL中的函数。因为HAL中的缺省函数依赖于Systick中断,如果在USB、SD卡
* 中断中有延迟函数,则会锁死。也可以通过函数HAL_NVIC_SetPriority提升Systick中断
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
/* 当前例子使用stm32f4xx_hal.c默认方式实现,未使用下面重定向的函数 */
#if 0
void HAL_Delay(uint32_t Delay)
{
bsp_DelayUS(Delay * 1000);
}
#endif
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
重点:保存的编码为ANSI
这样就建立好了一个模板
同理把.h文件也建好
回到CubeMx
效果展示
Generate一下可以看到生成的文件
后面把他加进Keil5不做过多阐述文章来源:https://www.toymoban.com/news/detail-401727.html
总结
这样直接用CubeMx生成常用的.c .h文件,就省去很多复制粘贴繁琐的工作,当然FreeMarker有很多命命这么没用到,仅仅是简单的用一下,有兴趣的同学可以去官网深入学习,像cube那样生成用户段不会被覆盖,所以说我们刚才的模板如果再次Generate会把新添加的代码抹去,我们仅仅需要在生成之后把模板Remove了就可以避免了,如果需要改变Cube原始生成的Main.h可以到目录db\templates进行修改,加上include<bsp.h>等等,修改前最好还是备份一下。 如果有任何问题可以加交流群482574669文章来源地址https://www.toymoban.com/news/detail-401727.html
到了这里,关于【STM32开发小技巧】CUBEMX改变工程模板(FreeMarker一键生成定制文件)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!