feat(example): 新增飞行控制 C 示例项目
- 提供传感器、滤波、控制律和执行器等模块化示例 - 包含约 35 个函数用于代码分析与文档生成流程测试 - 使用 Makefile 支持最小化编译验证
This commit is contained in:
13
Makefile
Normal file
13
Makefile
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
CC ?= gcc
|
||||||
|
CFLAGS ?= -Iinclude -Wall -Wextra -std=c99
|
||||||
|
|
||||||
|
SRC := $(wildcard src/*.c)
|
||||||
|
OBJ := $(SRC:.c=.o)
|
||||||
|
|
||||||
|
all: do178_small_app
|
||||||
|
|
||||||
|
do178_small_app: $(OBJ)
|
||||||
|
$(CC) $(OBJ) -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJ) do178_small_app
|
||||||
24
README.md
Normal file
24
README.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# DO178 Small C Project
|
||||||
|
|
||||||
|
这是一个用于 StarCodeDoc 文档模板端到端验证的小型 C 示例项目。
|
||||||
|
|
||||||
|
项目刻意拆成多个职责清晰的小模块,用来验证:
|
||||||
|
|
||||||
|
- 章节 4 动态模块标题生成
|
||||||
|
- 每个模块下的模块主要函数表
|
||||||
|
- 每个函数下的七行函数设计表
|
||||||
|
- main 函数归属模块
|
||||||
|
- 流程图图片块与函数 sourceRefs 绑定
|
||||||
|
|
||||||
|
模块划分:
|
||||||
|
|
||||||
|
- 系统入口与调度
|
||||||
|
- 传感器采集
|
||||||
|
- 信号滤波
|
||||||
|
- 控制律计算
|
||||||
|
- 执行器输出
|
||||||
|
- 通信指令
|
||||||
|
- 诊断监控
|
||||||
|
- 运行日志
|
||||||
|
|
||||||
|
函数数量约 35 个,适合快速构建知识库并验证文档生成效果。
|
||||||
94
include/flight_app.h
Normal file
94
include/flight_app.h
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#ifndef FLIGHT_APP_H
|
||||||
|
#define FLIGHT_APP_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int16_t raw_air_speed;
|
||||||
|
int16_t raw_altitude;
|
||||||
|
int16_t raw_pitch;
|
||||||
|
int16_t raw_temperature;
|
||||||
|
} SensorRawData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float air_speed;
|
||||||
|
float altitude;
|
||||||
|
float pitch;
|
||||||
|
float temperature;
|
||||||
|
} SensorData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float target_speed;
|
||||||
|
float target_altitude;
|
||||||
|
float pitch_limit;
|
||||||
|
uint8_t auto_mode;
|
||||||
|
} CommandState;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float throttle;
|
||||||
|
float elevator;
|
||||||
|
uint8_t armed;
|
||||||
|
} ActuatorState;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t sensor_fault;
|
||||||
|
uint16_t actuator_fault;
|
||||||
|
uint16_t command_fault;
|
||||||
|
uint16_t cycle_count;
|
||||||
|
} DiagnosticState;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SensorData sensor;
|
||||||
|
CommandState command;
|
||||||
|
ActuatorState actuator;
|
||||||
|
DiagnosticState diagnostic;
|
||||||
|
} AppState;
|
||||||
|
|
||||||
|
void System_Init(AppState *state);
|
||||||
|
void System_LoadDefaults(CommandState *command);
|
||||||
|
void System_RunCycle(AppState *state);
|
||||||
|
void System_Shutdown(AppState *state);
|
||||||
|
|
||||||
|
void Sensor_Init(SensorRawData *raw);
|
||||||
|
void Sensor_ReadAdc(SensorRawData *raw);
|
||||||
|
uint8_t Sensor_Validate(const SensorRawData *raw);
|
||||||
|
void Sensor_Scale(const SensorRawData *raw, SensorData *data);
|
||||||
|
void Sensor_Collect(SensorRawData *raw, SensorData *data);
|
||||||
|
|
||||||
|
void Filter_Init(SensorData *data);
|
||||||
|
float Filter_Median3(float a, float b, float c);
|
||||||
|
float Filter_LowPass(float previous, float current, float alpha);
|
||||||
|
float Filter_Limit(float value, float min_value, float max_value);
|
||||||
|
void Filter_Process(SensorData *data);
|
||||||
|
|
||||||
|
void Control_Init(CommandState *command);
|
||||||
|
float Control_ComputeSpeedError(const CommandState *command, const SensorData *data);
|
||||||
|
float Control_ComputeAltitudeError(const CommandState *command, const SensorData *data);
|
||||||
|
float Control_PidStep(float error, float gain, float limit);
|
||||||
|
void Control_Update(const CommandState *command, const SensorData *data, ActuatorState *actuator);
|
||||||
|
|
||||||
|
void Actuator_Init(ActuatorState *actuator);
|
||||||
|
void Actuator_Arm(ActuatorState *actuator);
|
||||||
|
void Actuator_WriteThrottle(ActuatorState *actuator, float throttle);
|
||||||
|
void Actuator_WriteElevator(ActuatorState *actuator, float elevator);
|
||||||
|
void Actuator_UpdateOutputs(ActuatorState *actuator);
|
||||||
|
void Actuator_Disarm(ActuatorState *actuator);
|
||||||
|
|
||||||
|
void Comm_Init(CommandState *command);
|
||||||
|
uint16_t Comm_PackStatus(const AppState *state);
|
||||||
|
uint8_t Comm_ReceiveCommand(CommandState *command, uint16_t word);
|
||||||
|
void Comm_ApplyCommand(CommandState *command, uint16_t word);
|
||||||
|
void Comm_SendStatus(uint16_t status_word);
|
||||||
|
|
||||||
|
void Diag_Init(DiagnosticState *diagnostic);
|
||||||
|
uint8_t Diag_CheckSensor(const SensorData *data);
|
||||||
|
uint8_t Diag_CheckActuator(const ActuatorState *actuator);
|
||||||
|
void Diag_UpdateFaults(DiagnosticState *diagnostic, const SensorData *data, const ActuatorState *actuator);
|
||||||
|
uint16_t Diag_ReportStatus(const DiagnosticState *diagnostic);
|
||||||
|
|
||||||
|
void Log_Init(void);
|
||||||
|
void Log_RecordSample(const SensorData *data);
|
||||||
|
void Log_RecordFault(uint16_t status_word);
|
||||||
|
void Log_Flush(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
35
src/actuators.c
Normal file
35
src/actuators.c
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#include "flight_app.h"
|
||||||
|
|
||||||
|
void Actuator_Init(ActuatorState *actuator) {
|
||||||
|
actuator->throttle = 0.0f;
|
||||||
|
actuator->elevator = 0.0f;
|
||||||
|
actuator->armed = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actuator_Arm(ActuatorState *actuator) {
|
||||||
|
actuator->armed = 1U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actuator_WriteThrottle(ActuatorState *actuator, float throttle) {
|
||||||
|
if (actuator->armed) {
|
||||||
|
actuator->throttle = Filter_Limit(throttle, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actuator_WriteElevator(ActuatorState *actuator, float elevator) {
|
||||||
|
if (actuator->armed) {
|
||||||
|
actuator->elevator = Filter_Limit(elevator, -20.0f, 20.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actuator_UpdateOutputs(ActuatorState *actuator) {
|
||||||
|
Actuator_Arm(actuator);
|
||||||
|
Actuator_WriteThrottle(actuator, actuator->throttle);
|
||||||
|
Actuator_WriteElevator(actuator, actuator->elevator);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actuator_Disarm(ActuatorState *actuator) {
|
||||||
|
actuator->armed = 0U;
|
||||||
|
actuator->throttle = 0.0f;
|
||||||
|
actuator->elevator = 0.0f;
|
||||||
|
}
|
||||||
31
src/comm.c
Normal file
31
src/comm.c
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#include "flight_app.h"
|
||||||
|
|
||||||
|
void Comm_Init(CommandState *command) {
|
||||||
|
command->auto_mode = 1U;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Comm_PackStatus(const AppState *state) {
|
||||||
|
uint16_t word = 0U;
|
||||||
|
word |= (uint16_t)(state->diagnostic.sensor_fault & 0x01U);
|
||||||
|
word |= (uint16_t)((state->diagnostic.actuator_fault & 0x01U) << 1U);
|
||||||
|
word |= (uint16_t)((state->diagnostic.command_fault & 0x01U) << 2U);
|
||||||
|
return word;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Comm_ReceiveCommand(CommandState *command, uint16_t word) {
|
||||||
|
if ((word & 0x8000U) == 0U) {
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
Comm_ApplyCommand(command, word);
|
||||||
|
return 1U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Comm_ApplyCommand(CommandState *command, uint16_t word) {
|
||||||
|
command->auto_mode = (uint8_t)((word >> 14U) & 0x01U);
|
||||||
|
command->target_speed = 180.0f + (float)(word & 0x003FU);
|
||||||
|
command->target_altitude = 2000.0f + (float)((word >> 6U) & 0x00FFU) * 10.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Comm_SendStatus(uint16_t status_word) {
|
||||||
|
(void)status_word;
|
||||||
|
}
|
||||||
34
src/control.c
Normal file
34
src/control.c
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#include "flight_app.h"
|
||||||
|
|
||||||
|
void Control_Init(CommandState *command) {
|
||||||
|
command->target_speed = 200.0f;
|
||||||
|
command->target_altitude = 2500.0f;
|
||||||
|
command->pitch_limit = 10.0f;
|
||||||
|
command->auto_mode = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Control_ComputeSpeedError(const CommandState *command, const SensorData *data) {
|
||||||
|
return command->target_speed - data->air_speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Control_ComputeAltitudeError(const CommandState *command, const SensorData *data) {
|
||||||
|
return command->target_altitude - data->altitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Control_PidStep(float error, float gain, float limit) {
|
||||||
|
float output = error * gain;
|
||||||
|
if (output > limit) {
|
||||||
|
return limit;
|
||||||
|
}
|
||||||
|
if (output < -limit) {
|
||||||
|
return -limit;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Control_Update(const CommandState *command, const SensorData *data, ActuatorState *actuator) {
|
||||||
|
float speed_error = Control_ComputeSpeedError(command, data);
|
||||||
|
float altitude_error = Control_ComputeAltitudeError(command, data);
|
||||||
|
actuator->throttle = Control_PidStep(speed_error, 0.01f, 1.0f);
|
||||||
|
actuator->elevator = Control_PidStep(altitude_error, 0.002f, command->pitch_limit);
|
||||||
|
}
|
||||||
43
src/diagnostics.c
Normal file
43
src/diagnostics.c
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#include "flight_app.h"
|
||||||
|
|
||||||
|
void Diag_Init(DiagnosticState *diagnostic) {
|
||||||
|
diagnostic->sensor_fault = 0U;
|
||||||
|
diagnostic->actuator_fault = 0U;
|
||||||
|
diagnostic->command_fault = 0U;
|
||||||
|
diagnostic->cycle_count = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Diag_CheckSensor(const SensorData *data) {
|
||||||
|
if (data->air_speed < 0.0f || data->altitude < 0.0f) {
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
if (data->temperature < -40.0f || data->temperature > 85.0f) {
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
return 1U;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Diag_CheckActuator(const ActuatorState *actuator) {
|
||||||
|
if (actuator->throttle < 0.0f || actuator->throttle > 1.0f) {
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
if (actuator->elevator < -20.0f || actuator->elevator > 20.0f) {
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
return 1U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Diag_UpdateFaults(DiagnosticState *diagnostic, const SensorData *data, const ActuatorState *actuator) {
|
||||||
|
diagnostic->sensor_fault = Diag_CheckSensor(data) ? 0U : 1U;
|
||||||
|
diagnostic->actuator_fault = Diag_CheckActuator(actuator) ? 0U : 1U;
|
||||||
|
diagnostic->command_fault = 0U;
|
||||||
|
diagnostic->cycle_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Diag_ReportStatus(const DiagnosticState *diagnostic) {
|
||||||
|
uint16_t status = 0U;
|
||||||
|
status |= diagnostic->sensor_fault;
|
||||||
|
status |= (uint16_t)(diagnostic->actuator_fault << 1U);
|
||||||
|
status |= (uint16_t)(diagnostic->command_fault << 2U);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
39
src/filters.c
Normal file
39
src/filters.c
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#include "flight_app.h"
|
||||||
|
|
||||||
|
void Filter_Init(SensorData *data) {
|
||||||
|
data->air_speed = 0.0f;
|
||||||
|
data->altitude = 0.0f;
|
||||||
|
data->pitch = 0.0f;
|
||||||
|
data->temperature = 25.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Filter_Median3(float a, float b, float c) {
|
||||||
|
if ((a >= b && a <= c) || (a >= c && a <= b)) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
if ((b >= a && b <= c) || (b >= c && b <= a)) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Filter_LowPass(float previous, float current, float alpha) {
|
||||||
|
return previous + alpha * (current - previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Filter_Limit(float value, float min_value, float max_value) {
|
||||||
|
if (value < min_value) {
|
||||||
|
return min_value;
|
||||||
|
}
|
||||||
|
if (value > max_value) {
|
||||||
|
return max_value;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Filter_Process(SensorData *data) {
|
||||||
|
data->air_speed = Filter_Limit(Filter_LowPass(data->air_speed, data->air_speed, 0.2f), 0.0f, 450.0f);
|
||||||
|
data->altitude = Filter_Limit(data->altitude, 0.0f, 12000.0f);
|
||||||
|
data->pitch = Filter_Limit(Filter_Median3(data->pitch, data->pitch, data->pitch), -30.0f, 30.0f);
|
||||||
|
data->temperature = Filter_Limit(data->temperature, -40.0f, 85.0f);
|
||||||
|
}
|
||||||
25
src/logger.c
Normal file
25
src/logger.c
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#include "flight_app.h"
|
||||||
|
|
||||||
|
static uint16_t g_log_count = 0U;
|
||||||
|
static uint16_t g_fault_count = 0U;
|
||||||
|
|
||||||
|
void Log_Init(void) {
|
||||||
|
g_log_count = 0U;
|
||||||
|
g_fault_count = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Log_RecordSample(const SensorData *data) {
|
||||||
|
(void)data;
|
||||||
|
g_log_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Log_RecordFault(uint16_t status_word) {
|
||||||
|
if (status_word != 0U) {
|
||||||
|
g_fault_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Log_Flush(void) {
|
||||||
|
g_log_count = 0U;
|
||||||
|
g_fault_count = 0U;
|
||||||
|
}
|
||||||
13
src/main.c
Normal file
13
src/main.c
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include "flight_app.h"
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
AppState state;
|
||||||
|
System_Init(&state);
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < 5; ++i) {
|
||||||
|
System_RunCycle(&state);
|
||||||
|
}
|
||||||
|
|
||||||
|
System_Shutdown(&state);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
42
src/sensors.c
Normal file
42
src/sensors.c
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#include "flight_app.h"
|
||||||
|
|
||||||
|
void Sensor_Init(SensorRawData *raw) {
|
||||||
|
raw->raw_air_speed = 0;
|
||||||
|
raw->raw_altitude = 0;
|
||||||
|
raw->raw_pitch = 0;
|
||||||
|
raw->raw_temperature = 250;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sensor_ReadAdc(SensorRawData *raw) {
|
||||||
|
raw->raw_air_speed = 2048;
|
||||||
|
raw->raw_altitude = 1800;
|
||||||
|
raw->raw_pitch = 30;
|
||||||
|
raw->raw_temperature = 265;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Sensor_Validate(const SensorRawData *raw) {
|
||||||
|
if (raw->raw_air_speed < 0 || raw->raw_air_speed > 4095) {
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
if (raw->raw_altitude < 0 || raw->raw_altitude > 4095) {
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
if (raw->raw_temperature < -400 || raw->raw_temperature > 850) {
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
return 1U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sensor_Scale(const SensorRawData *raw, SensorData *data) {
|
||||||
|
data->air_speed = (float)raw->raw_air_speed * 0.12f;
|
||||||
|
data->altitude = (float)raw->raw_altitude * 2.5f;
|
||||||
|
data->pitch = (float)raw->raw_pitch * 0.1f;
|
||||||
|
data->temperature = (float)raw->raw_temperature * 0.1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sensor_Collect(SensorRawData *raw, SensorData *data) {
|
||||||
|
Sensor_ReadAdc(raw);
|
||||||
|
if (Sensor_Validate(raw)) {
|
||||||
|
Sensor_Scale(raw, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
43
src/system.c
Normal file
43
src/system.c
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#include "flight_app.h"
|
||||||
|
|
||||||
|
void System_Init(AppState *state) {
|
||||||
|
SensorRawData raw;
|
||||||
|
Sensor_Init(&raw);
|
||||||
|
Filter_Init(&state->sensor);
|
||||||
|
Control_Init(&state->command);
|
||||||
|
Actuator_Init(&state->actuator);
|
||||||
|
Diag_Init(&state->diagnostic);
|
||||||
|
Comm_Init(&state->command);
|
||||||
|
Log_Init();
|
||||||
|
System_LoadDefaults(&state->command);
|
||||||
|
}
|
||||||
|
|
||||||
|
void System_LoadDefaults(CommandState *command) {
|
||||||
|
command->target_speed = 210.0f;
|
||||||
|
command->target_altitude = 3000.0f;
|
||||||
|
command->pitch_limit = 12.0f;
|
||||||
|
command->auto_mode = 1U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void System_RunCycle(AppState *state) {
|
||||||
|
SensorRawData raw;
|
||||||
|
uint16_t status_word;
|
||||||
|
|
||||||
|
Sensor_Collect(&raw, &state->sensor);
|
||||||
|
Filter_Process(&state->sensor);
|
||||||
|
Control_Update(&state->command, &state->sensor, &state->actuator);
|
||||||
|
Actuator_UpdateOutputs(&state->actuator);
|
||||||
|
Diag_UpdateFaults(&state->diagnostic, &state->sensor, &state->actuator);
|
||||||
|
|
||||||
|
status_word = Diag_ReportStatus(&state->diagnostic);
|
||||||
|
Comm_SendStatus(status_word);
|
||||||
|
Log_RecordSample(&state->sensor);
|
||||||
|
if (status_word != 0U) {
|
||||||
|
Log_RecordFault(status_word);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void System_Shutdown(AppState *state) {
|
||||||
|
Actuator_Disarm(&state->actuator);
|
||||||
|
Log_Flush();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user