RTE简介
RTE 运行时环境
首先RTE的全称为,Runtime Environment。
定义:指的是一套为应用程序提供核心支持的软件服务和资源的总和。它位于操作系统、硬件抽象层和应用程序之间,这里主要以数据为主,例如实时数据和参数设置。
作用:应用程序在运行时(Runtime)依赖于它来执行任务,例如任务调度、内存管理、中断处理和访问外设驱动;
并且这使得APP层可以与BSP层、硬件层完全解耦,使得APP的可移植性大大提高。
生成的宏定义还可以支持Matlab&Simulink的MBD编程,以完成复杂逻辑的功能实现。

RTE建立过程
- 使用EXECL表格来存放对应数据,如下图所示:

- 通过VBA语言编写宏来生成对应的.c .h文件

以下是生成RTE.h的VBA代码示例,其他则先不展示,我会将源码提供给大家
Sub GenerateRTEDefineHeaderFile()
On Error GoTo ErrorHandler
' 定义常量
Const MAX_NAME_LENGTH As Integer = 40
Dim filePath As String
Dim fileNumber As Integer
' 1. 检查并准备文件
If Not PrepareFileEnvironment(filePath, fileNumber) Then Exit Sub
' 2. 写入文件内容
WriteHeaderFileContent filePath, fileNumber, MAX_NAME_LENGTH
MsgBox "RTE_Define.h 文件已生成!" & vbCrLf & "路径: " & filePath, vbInformation
Exit Sub
ErrorHandler:
MsgBox "错误 " & Err.Number & ": " & Err.Description, vbCritical
If fileNumber > 0 Then Close #fileNumber
End Sub
' 准备文件环境
Private Function PrepareFileEnvironment(ByRef filePath As String, ByRef fileNumber As Integer) As Boolean
' 检查目录
If Len(Dir(ThisWorkbook.Path, vbDirectory)) = 0 Then
MsgBox "无法访问当前目录", vbExclamation
Exit Function
End If
' 构建文件路径
filePath = ThisWorkbook.Path & Application.PathSeparator & "RTE_Define.h"
fileNumber = FreeFile()
' 尝试打开文件测试写入权限
On Error Resume Next
Open filePath For Output As #fileNumber
If Err.Number <> 0 Then
MsgBox "无法创建文件,请检查写入权限", vbExclamation
Exit Function
End If
Close #fileNumber
On Error GoTo 0
PrepareFileEnvironment = True
End Function
' 写入文件内容
Private Sub WriteHeaderFileContent(ByVal filePath As String, ByVal fileNumber As Integer, ByVal maxNameLength As Integer)
' 打开文件
Open filePath For Output As #fileNumber
' 写入文件头
Print #fileNumber, "#ifndef _RTE_DEFINE_H"
Print #fileNumber, "#define _RTE_DEFINE_H"
Print #fileNumber, ""
Print #fileNumber, "/* 自动生成的RTE_Define定义 */"
Print #fileNumber, "/* 生成时间: " & Now & " */"
Print #fileNumber, ""
' 写入工作表数据
WriteWorksheetData fileNumber, maxNameLength
' 写入文件尾
Print #fileNumber, "#endif /* _RTE_H */"
' 关闭文件
Close #fileNumber
End Sub
' 写入工作表数据
Private Sub WriteWorksheetData(ByVal fileNumber As Integer, ByVal maxNameLength As Integer)
Dim sheetNames As Variant
Dim sheetIndex As Integer
sheetNames = Array("参数类", "数据类")
For sheetIndex = LBound(sheetNames) To UBound(sheetNames)
WriteSingleWorksheet fileNumber, sheetNames(sheetIndex), maxNameLength
Next sheetIndex
End Sub
' 写入单个工作表数据
Private Sub WriteSingleWorksheet(ByVal fileNumber As Integer, _
ByVal sheetName As String, _
ByVal maxNameLength As Integer)
Dim ws As Worksheet
Dim dataRange As Range
Dim dataArray As Variant
Dim i As Long
On Error Resume Next
Set ws = ThisWorkbook.Sheets(sheetName)
On Error GoTo 0
If ws Is Nothing Then
MsgBox "工作表 " & sheetName & " 不存在,已跳过", vbExclamation
Exit Sub
End If
' 写入工作表标题
Print #fileNumber, "/* " & sheetName & " 信号定义 */"
' 获取数据
Set dataRange = ws.Range("A2:H" & ws.Cells(ws.Rows.Count, "A").End(xlUp).Row)
dataArray = dataRange.Value
' 写入数据行
For i = LBound(dataArray, 1) To UBound(dataArray, 1)
WriteDataRow fileNumber, dataArray, i, maxNameLength
Next i
' 添加分隔空行
Print #fileNumber, ""
End Sub
' 写入单行数据
Private Sub WriteDataRow(ByVal fileNumber As Integer, _
ByVal dataArray As Variant, _
ByVal rowIndex As Long, _
ByVal maxNameLength As Integer)
Dim signalID As Integer
Dim signalEnName As String
Dim signalChName As String
Dim paddingSpaces As String
' 获取数据
signalID = dataArray(rowIndex, 1)
signalEnName = dataArray(rowIndex, 2)
signalChName = dataArray(rowIndex, 3)
' 跳过空行
If signalEnName = "" Then Exit Sub
' 写入宏定义
Print #fileNumber, "//" & signalChName
paddingSpaces = String(maxNameLength - Len(signalEnName), " ")
Print #fileNumber, "#define SET_" & signalEnName & "(u16Value)" & paddingSpaces & "SetRteVal(" & signalEnName & ", u16Value)"
paddingSpaces = String(maxNameLength - (Len(signalEnName) - 8), " ")
Print #fileNumber, "#define GET_" & signalEnName & "()" & paddingSpaces & "GetRteVal(" & signalEnName & ")"
Print #fileNumber,
End Sub
- 添加生成的文件进入keil工程,生成代码如下
RTE.c
#include <RTE.h>
/* 自动生成的RTE信号数组 */
/* 生成时间: 2025/10/29 11:02:26 */
/* 参数类 信号定义 */
RTE_PARMS_SRTUCT rte_parms[] =
{
//ParmsName 默认值 Max Value, Min Value, Zoom, Offset, //SignalChName
{0x00 /*RTE_SET_PARMS_START_FLAG*/, 0, 65535, 0, 1, 0, },//设置参数开始位置
{0x00 /*RTE_SET_PARMS_1*/, 0, 65535, 0, 1, 0, },//设置参数1
{0x00 /*RTE_SET_PARMS_2*/, 0, 65535, 0, 1, 0, },//设置参数2
{0x00 /*RTE_SET_PARMS_3*/, 0, 65535, 0, 1, 0, },//设置参数3
{0x00 /*RTE_SET_PARMS_4*/, 0, 65535, 0, 1, 0, },//设置参数4
{0x00 /*RTE_SET_PARMS_5*/, 0, 65535, 0, 1, 0, },//设置参数5
{0x00 /*RTE_SET_PARMS_6*/, 0, 65535, 0, 1, 0, },//设置参数6
{0x00 /*RTE_SET_PARMS_7*/, 0, 65535, 0, 1, 0, },//设置参数7
{0x00 /*RTE_SET_PARMS_8*/, 0, 65535, 0, 1, 0, },//设置参数8
{0x00 /*RTE_SET_PARMS_END_FLAG*/, 0, 65535, 0, 1, 0, },//设置参数结束位置
};
/* 数据类 信号定义 */
RTE_REAL_DATA_SRTUCT rte_real_data[] =
{
//ParmsName 默认值 //SignalChName
{0x00 /*RTE_REAL_DATA_START_FLAG*/, 0x00, },//实时数据开始位置
{0x00 /*RTE_REAL_DATA_1*/, 0x00, },//实时数据1
{0x00 /*RTE_REAL_DATA_2*/, 0x00, },//实时数据2
{0x00 /*RTE_REAL_DATA_3*/, 0x00, },//实时数据3
{0x00 /*RTE_REAL_DATA_4*/, 0x00, },//实时数据4
{0x00 /*RTE_REAL_DATA_5*/, 0x00, },//实时数据5
{0x00 /*RTE_REAL_DATA_6*/, 0x00, },//实时数据6
{0x00 /*RTE_REAL_DATA_7*/, 0x00, },//实时数据7
{0x00 /*RTE_REAL_DATA_8*/, 0x00, },//实时数据8
{0x00 /*RTE_REAL_DATA_9*/, 0x00, },//实时数据9
{0x00 /*RTE_REAL_DATA_END_FLAG*/, 0x00, },//实时数据结束位置
};
RTE.h
#ifndef _RTE_H
#define _RTE_H
/* 自动生成的RTE信号定义 */
/* 生成时间: 2025/10/29 11:02:25 */
/* RTEDataStruct.txt 内容 */
#include "main.h"
#pragma pack(1)
typedef struct
{
uint16_t SignalVal; //数据
uint16_t Zoom; //精度
uint16_t OffSet; //偏移量
}RTE_REAL_DATA_SRTUCT;
typedef struct
{
uint16_t SignalVal; //数据
uint16_t DefaultVal; //默认值
uint16_t MaxVal; //最大值
uint16_t MinVal; //最小值
uint16_t Zoom; //精度
uint16_t OffSet; //偏移量
}RTE_PARMS_SRTUCT;
#pragma pack()
/* 参数类 信号定义 */
#define RTE_SET_PARMS_START_FLAG (0) /* 设置参数开始位置 */
#define RTE_SET_PARMS_1 (1) /* 设置参数1 */
#define RTE_SET_PARMS_2 (2) /* 设置参数2 */
#define RTE_SET_PARMS_3 (3) /* 设置参数3 */
#define RTE_SET_PARMS_4 (4) /* 设置参数4 */
#define RTE_SET_PARMS_5 (5) /* 设置参数5 */
#define RTE_SET_PARMS_6 (6) /* 设置参数6 */
#define RTE_SET_PARMS_7 (7) /* 设置参数7 */
#define RTE_SET_PARMS_8 (8) /* 设置参数8 */
#define RTE_SET_PARMS_END_FLAG (9) /* 设置参数结束位置 */
/* 数据类 信号定义 */
#define RTE_REAL_DATA_START_FLAG (0) /* 实时数据开始位置 */
#define RTE_REAL_DATA_1 (1) /* 实时数据1 */
#define RTE_REAL_DATA_2 (2) /* 实时数据2 */
#define RTE_REAL_DATA_3 (3) /* 实时数据3 */
#define RTE_REAL_DATA_4 (4) /* 实时数据4 */
#define RTE_REAL_DATA_5 (5) /* 实时数据5 */
#define RTE_REAL_DATA_6 (6) /* 实时数据6 */
#define RTE_REAL_DATA_7 (7) /* 实时数据7 */
#define RTE_REAL_DATA_8 (8) /* 实时数据8 */
#define RTE_REAL_DATA_9 (9) /* 实时数据9 */
#define RTE_REAL_DATA_END_FLAG (10) /* 实时数据结束位置 */
#endif /* _RTE_H */
RTE_Define.h
#ifndef _RTE_DEFINE_H
#define _RTE_DEFINE_H
/* 自动生成的RTE_Define定义 */
/* 生成时间: 2025/10/29 11:02:27 */
/* 参数类 信号定义 */
//设置参数开始位置
#define SET_RTE_SET_PARMS_START_FLAG(u16Value) SetRteVal(RTE_SET_PARMS_START_FLAG, u16Value)
#define GET_RTE_SET_PARMS_START_FLAG() GetRteVal(RTE_SET_PARMS_START_FLAG)
//设置参数1
#define SET_RTE_SET_PARMS_1(u16Value) SetRteVal(RTE_SET_PARMS_1, u16Value)
#define GET_RTE_SET_PARMS_1() GetRteVal(RTE_SET_PARMS_1)
//设置参数2
#define SET_RTE_SET_PARMS_2(u16Value) SetRteVal(RTE_SET_PARMS_2, u16Value)
#define GET_RTE_SET_PARMS_2() GetRteVal(RTE_SET_PARMS_2)
//设置参数3
#define SET_RTE_SET_PARMS_3(u16Value) SetRteVal(RTE_SET_PARMS_3, u16Value)
#define GET_RTE_SET_PARMS_3() GetRteVal(RTE_SET_PARMS_3)
//设置参数4
#define SET_RTE_SET_PARMS_4(u16Value) SetRteVal(RTE_SET_PARMS_4, u16Value)
#define GET_RTE_SET_PARMS_4() GetRteVal(RTE_SET_PARMS_4)
//设置参数5
#define SET_RTE_SET_PARMS_5(u16Value) SetRteVal(RTE_SET_PARMS_5, u16Value)
#define GET_RTE_SET_PARMS_5() GetRteVal(RTE_SET_PARMS_5)
//设置参数6
#define SET_RTE_SET_PARMS_6(u16Value) SetRteVal(RTE_SET_PARMS_6, u16Value)
#define GET_RTE_SET_PARMS_6() GetRteVal(RTE_SET_PARMS_6)
//设置参数7
#define SET_RTE_SET_PARMS_7(u16Value) SetRteVal(RTE_SET_PARMS_7, u16Value)
#define GET_RTE_SET_PARMS_7() GetRteVal(RTE_SET_PARMS_7)
//设置参数8
#define SET_RTE_SET_PARMS_8(u16Value) SetRteVal(RTE_SET_PARMS_8, u16Value)
#define GET_RTE_SET_PARMS_8() GetRteVal(RTE_SET_PARMS_8)
//设置参数结束位置
#define SET_RTE_SET_PARMS_END_FLAG(u16Value) SetRteVal(RTE_SET_PARMS_END_FLAG, u16Value)
#define GET_RTE_SET_PARMS_END_FLAG() GetRteVal(RTE_SET_PARMS_END_FLAG)
/* 数据类 信号定义 */
//实时数据开始位置
#define SET_RTE_REAL_DATA_START_FLAG(u16Value) SetRteVal(RTE_REAL_DATA_START_FLAG, u16Value)
#define GET_RTE_REAL_DATA_START_FLAG() GetRteVal(RTE_REAL_DATA_START_FLAG)
//实时数据1
#define SET_RTE_REAL_DATA_1(u16Value) SetRteVal(RTE_REAL_DATA_1, u16Value)
#define GET_RTE_REAL_DATA_1() GetRteVal(RTE_REAL_DATA_1)
//实时数据2
#define SET_RTE_REAL_DATA_2(u16Value) SetRteVal(RTE_REAL_DATA_2, u16Value)
#define GET_RTE_REAL_DATA_2() GetRteVal(RTE_REAL_DATA_2)
//实时数据3
#define SET_RTE_REAL_DATA_3(u16Value) SetRteVal(RTE_REAL_DATA_3, u16Value)
#define GET_RTE_REAL_DATA_3() GetRteVal(RTE_REAL_DATA_3)
//实时数据4
#define SET_RTE_REAL_DATA_4(u16Value) SetRteVal(RTE_REAL_DATA_4, u16Value)
#define GET_RTE_REAL_DATA_4() GetRteVal(RTE_REAL_DATA_4)
//实时数据5
#define SET_RTE_REAL_DATA_5(u16Value) SetRteVal(RTE_REAL_DATA_5, u16Value)
#define GET_RTE_REAL_DATA_5() GetRteVal(RTE_REAL_DATA_5)
//实时数据6
#define SET_RTE_REAL_DATA_6(u16Value) SetRteVal(RTE_REAL_DATA_6, u16Value)
#define GET_RTE_REAL_DATA_6() GetRteVal(RTE_REAL_DATA_6)
//实时数据7
#define SET_RTE_REAL_DATA_7(u16Value) SetRteVal(RTE_REAL_DATA_7, u16Value)
#define GET_RTE_REAL_DATA_7() GetRteVal(RTE_REAL_DATA_7)
//实时数据8
#define SET_RTE_REAL_DATA_8(u16Value) SetRteVal(RTE_REAL_DATA_8, u16Value)
#define GET_RTE_REAL_DATA_8() GetRteVal(RTE_REAL_DATA_8)
//实时数据9
#define SET_RTE_REAL_DATA_9(u16Value) SetRteVal(RTE_REAL_DATA_9, u16Value)
#define GET_RTE_REAL_DATA_9() GetRteVal(RTE_REAL_DATA_9)
//实时数据结束位置
#define SET_RTE_REAL_DATA_END_FLAG(u16Value) SetRteVal(RTE_REAL_DATA_END_FLAG, u16Value)
#define GET_RTE_REAL_DATA_END_FLAG() GetRteVal(RTE_REAL_DATA_END_FLAG)
#endif /* _RTE_H */
RTE相关函数实现
实现以下功能:
- 参数读取
- 参数写入
- 上电初始化
- 参数恢复出厂
/****************************************************************************************
* @file rteDateParse.c
* @brief rte数据相关操作
* @author lwz
* @date 2025/10/29
* @version V1.0.0
* @note 1、数据初始化
2、数据读取和写入
3、数据恢复出厂
****************************************************************************************/
/*头文件添加区*/
#include "rteDateParse.h"
#include "RTE.h"
/*宏定义定义区*/
/*全局变量定义区*/
/*外部变量引用区*/
extern RTE_PARMS_SRTUCT rte_parms[] ; //参数类RTE数据
extern RTE_REAL_DATA_SRTUCT rte_real_data[]; //数据类RTE数据
/*函数声明区*/
/*函数定义区*/
/***************************************************************************************
* @brief 设置RTE信号
* @param rteSigId 要设置的信号ID
* date_t 传入的数据
* @retval void
* @note
***************************************************************************************/
void SetRteVal(uint16_t rteSigId, uint16_t date)
{
uint16_t date_t = (date * rte_parms[rteSigId].Zoom) + rte_parms[rteSigId].OffSet;
if(rteSigId > RTE_SET_PARMS_START_FLAG && rteSigId < RTE_SET_PARMS_END_FLAG)
{
if(rte_parms[rteSigId].MinVal <= date_t && rte_parms[rteSigId].MaxVal >= date_t)
{
rte_parms[rteSigId].SignalVal = date_t;
//数据写入存储芯片以便永久保存 如EEPROM
}
}
else if(rteSigId > RTE_REAL_DATA_START_FLAG && rteSigId < RTE_REAL_DATA_END_FLAG)
{//数据类没有上下限,且无需存放在芯片中,掉电丢失
rte_real_data[rteSigId].SignalVal = date_t;
}
else
{
//ERROR
}
}
/***************************************************************************************
* @brief 读取RTE信号
* @param rteSigId 要读取的信号ID
* @retval ret RTE的值
* @note
***************************************************************************************/
uint16_t GetRteVal(uint16_t rteSigId)
{
uint16_t ret = 0;
if(rteSigId > RTE_SET_PARMS_START_FLAG && rteSigId < RTE_SET_PARMS_END_FLAG)
{
ret = rte_parms[rteSigId].SignalVal;
}
else if(rteSigId > RTE_REAL_DATA_START_FLAG && rteSigId < RTE_REAL_DATA_END_FLAG)
{
ret = rte_real_data[rteSigId].SignalVal;
}
else
{
//ERROR
ret = 0;
}
return ret;
}
/***************************************************************************************
* @brief rte上电初始化
* @param void
* @retval void
* @note 数据类全为0,参数类从EEPROM中读取
***************************************************************************************/
void rteInit(void)
{
for(uint16_t i=RTE_SET_PARMS_START_FLAG; i<RTE_SET_PARMS_END_FLAG; i++)
{
rte_parms[i].SignalVal = 0;//此处应为从EEPROM中读取对应参数数据 暂时先写0
}
for(uint16_t i=RTE_REAL_DATA_START_FLAG; i<RTE_REAL_DATA_END_FLAG; i++)
{
rte_parms[i].SignalVal = 0;
}
}
/***************************************************************************************
* @brief rte参数回复默认值
* @param void
* @retval void
* @note 数据类不操作,参数类改为使用默认值
***************************************************************************************/
void rteRecovery(void)
{
for(uint16_t i=RTE_SET_PARMS_START_FLAG; i<RTE_SET_PARMS_END_FLAG; i++)
{
rte_parms[i].SignalVal = rte_parms[i].DefaultVal;
}
}
小结
使用RTE该架构,可是使得项目开发进度大大加快,使得各个功能之间相互解耦,各功能仅依赖于RTE所提供的数据即可运行,使得app的跨平台性、可移植性大幅提高,且多人团队开发更高效,非常值得尝试。
3557

被折叠的 条评论
为什么被折叠?



