commit 816da4829968ff2992fabf8872566c150a5dc54e Author: xingchen Date: Tue Sep 1 09:25:26 2026 +0800 feat(example): 新增飞行控制 C 示例项目 - 提供传感器、滤波、控制律和执行器等模块化示例 - 包含约 35 个函数用于代码分析与文档生成流程测试 - 使用 Makefile 支持最小化编译验证 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e421fc4 --- /dev/null +++ b/Makefile @@ -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 diff --git a/README.md b/README.md new file mode 100644 index 0000000..5b1835c --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# DO178 Small C Project + +这是一个用于 StarCodeDoc 文档模板端到端验证的小型 C 示例项目。 + +项目刻意拆成多个职责清晰的小模块,用来验证: + +- 章节 4 动态模块标题生成 +- 每个模块下的模块主要函数表 +- 每个函数下的七行函数设计表 +- main 函数归属模块 +- 流程图图片块与函数 sourceRefs 绑定 + +模块划分: + +- 系统入口与调度 +- 传感器采集 +- 信号滤波 +- 控制律计算 +- 执行器输出 +- 通信指令 +- 诊断监控 +- 运行日志 + +函数数量约 35 个,适合快速构建知识库并验证文档生成效果。 diff --git a/include/flight_app.h b/include/flight_app.h new file mode 100644 index 0000000..dc3e11f --- /dev/null +++ b/include/flight_app.h @@ -0,0 +1,94 @@ +#ifndef FLIGHT_APP_H +#define FLIGHT_APP_H + +#include + +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 diff --git a/src/actuators.c b/src/actuators.c new file mode 100644 index 0000000..85bbcc9 --- /dev/null +++ b/src/actuators.c @@ -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; +} diff --git a/src/comm.c b/src/comm.c new file mode 100644 index 0000000..d30abad --- /dev/null +++ b/src/comm.c @@ -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; +} diff --git a/src/control.c b/src/control.c new file mode 100644 index 0000000..3d9a11b --- /dev/null +++ b/src/control.c @@ -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); +} diff --git a/src/diagnostics.c b/src/diagnostics.c new file mode 100644 index 0000000..d45e5af --- /dev/null +++ b/src/diagnostics.c @@ -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; +} diff --git a/src/filters.c b/src/filters.c new file mode 100644 index 0000000..d74716d --- /dev/null +++ b/src/filters.c @@ -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); +} diff --git a/src/logger.c b/src/logger.c new file mode 100644 index 0000000..65fe58e --- /dev/null +++ b/src/logger.c @@ -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; +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..824f002 --- /dev/null +++ b/src/main.c @@ -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; +} diff --git a/src/sensors.c b/src/sensors.c new file mode 100644 index 0000000..142ea3e --- /dev/null +++ b/src/sensors.c @@ -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); + } +} diff --git a/src/system.c b/src/system.c new file mode 100644 index 0000000..e450c76 --- /dev/null +++ b/src/system.c @@ -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(); +}