Compare commits

13 Commits

Author SHA1 Message Date
2ce600dc4d 删除多个类和结构体的拷贝构造函数和赋值运算符,确保不可复制性
All checks were successful
Build and Upload Artifact / build and upload-artifact (push) Successful in 20m4s
2025-05-21 18:55:14 +08:00
69155f3ce1 新增 Hc05 类,支持 HC-05 蓝牙模块的串口通信,增加串口设置波特率函数
All checks were successful
Build and Upload Artifact / build and upload-artifact (push) Successful in 20m1s
2025-05-13 10:04:09 +08:00
c3e0edd72d TaskHelper int 修改为 uint32_t
All checks were successful
Build and Upload Artifact / build and upload-artifact (push) Successful in 19m51s
2025-05-12 14:24:59 +08:00
38aaa9b8b3 优化 TerminateHandler 函数,增强异常处理逻辑并确保错误信息通过调试串口输出
All checks were successful
Build and Upload Artifact / build and upload-artifact (push) Successful in 19m55s
2025-05-12 13:31:39 +08:00
a7485fca40 新增 DebugSerialPort 支持,CommonCenter、CanMv 和 DfPlayer 改用智能指针
Some checks failed
Build and Upload Artifact / build and upload-artifact (push) Has been cancelled
2025-05-12 13:17:44 +08:00
21eec9089e 优化 App 类,重构 Setup 和 AppStart 函数,清理未使用的代码,增强可读性
All checks were successful
Build and Upload Artifact / build and upload-artifact (push) Successful in 19m58s
2025-05-10 19:49:39 +08:00
72dcf53b3e 关闭 ThreadX 2025-05-10 19:45:55 +08:00
83d9a263a4 新增 DfPlayer 和 CanMv 类,优化 UART 读写方法,更新 CommonCenter 以支持新类实例化 2025-05-10 19:38:20 +08:00
b4ecf03e95 重构 SerialPort 类,移除静态成员,改为实例成员,优化 UART 读写方法 2025-05-10 18:58:32 +08:00
52a4669c0d 新增 CommonCenter 类和 Config 结构体,提供超声波测距功能的配置和实例化支持 2025-05-10 18:23:47 +08:00
f87404cba6 新增 Ultrasonic 类和 TaskHelper 类,提供超声波测距功能及任务等待辅助方法 2025-05-10 18:23:21 +08:00
f6541a5fbd 更新 CMakeLists.txt,使用 find_package 查找 Python3,并更新 MCUVersionGen.py 脚本的执行命令 2025-05-08 23:22:12 +08:00
aa43e21103 开启 ThreadX 2025-05-07 22:53:45 +08:00
11 changed files with 224 additions and 41 deletions

View File

@@ -2,11 +2,17 @@
#include "../Common/can_mv.hpp" #include "../Common/can_mv.hpp"
#include "../Common/df_player.hpp" #include "../Common/df_player.hpp"
#include "../Common/hc05.hpp"
#include "../Common/ultrasonic.hpp" #include "../Common/ultrasonic.hpp"
#include "../config.hpp" #include "../config.hpp"
#include "Common/serial_port.hpp"
class CommonCenter { class CommonCenter {
public: public:
CommonCenter() = delete;
CommonCenter(const CommonCenter&) = delete;
CommonCenter& operator=(const CommonCenter&) = delete;
static Ultrasonic& GetUltrasonic() { static Ultrasonic& GetUltrasonic() {
static Ultrasonic* instance = nullptr; static Ultrasonic* instance = nullptr;
if (instance == nullptr) { if (instance == nullptr) {
@@ -31,4 +37,23 @@ public:
} }
return *instance; return *instance;
} }
static Hc05& GetHc05() {
static Hc05* instance = nullptr;
if (instance == nullptr) {
instance = new Hc05(Config::kHc05Uart);
}
return *instance;
}
static SerialPort& GetDebugSerialPort() {
static constexpr auto kBaudRate = 115200;
static constexpr auto kLength = 256;
static constexpr auto kTimeout = 1000;
static SerialPort* instance = nullptr;
if (instance == nullptr) {
instance = new SerialPort(Config::kDebugUart, kBaudRate, kLength, kTimeout);
}
return *instance;
}
}; };

View File

@@ -1,19 +1,24 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <memory>
#include "../Common/serial_port.hpp" #include "../Common/serial_port.hpp"
class CanMv { class CanMv {
public: public:
explicit CanMv(UART_HandleTypeDef* uart) : serialPort(new SerialPort(uart, kLength, kTimeout)) {} explicit CanMv(UART_HandleTypeDef* uart)
: serialPort(std::make_unique<SerialPort>(uart, kBaudRate, kLength, kTimeout)) {}
~CanMv() { ~CanMv() = default;
delete serialPort; CanMv(const CanMv&) = delete;
} CanMv& operator=(const CanMv&) = delete;
CanMv(CanMv&&) = delete;
CanMv& operator=(CanMv&&) = delete;
private: private:
static constexpr uint32_t kLength = 128; static constexpr uint32_t kBaudRate = 115200;
static constexpr uint32_t kTimeout = 10; static constexpr uint32_t kLength = 128;
SerialPort* serialPort; static constexpr uint32_t kTimeout = 10;
std::unique_ptr<SerialPort> serialPort;
}; };

View File

@@ -1,16 +1,20 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <memory>
#include "../Common/serial_port.hpp" #include "../Common/serial_port.hpp"
class DfPlayer { class DfPlayer {
public: public:
explicit DfPlayer(UART_HandleTypeDef* uart) : serialPort(new SerialPort(uart, kLength, kTimeout)) {} explicit DfPlayer(UART_HandleTypeDef* uart)
: serialPort(std::make_unique<SerialPort>(uart, kBaudRate, kLength, kTimeout)) {}
~DfPlayer() { ~DfPlayer() = default;
delete serialPort; DfPlayer(const DfPlayer&) = delete;
} DfPlayer& operator=(const DfPlayer&) = delete;
DfPlayer(DfPlayer&&) = delete;
DfPlayer& operator=(DfPlayer&&) = delete;
void Play(); void Play();
void Stop(); void Stop();
@@ -50,9 +54,10 @@ private:
kQueryFlashCurrentTrack = 0x4D, kQueryFlashCurrentTrack = 0x4D,
}; };
static constexpr uint32_t kLength = 128; static constexpr uint32_t kBaudRate = 9600;
static constexpr uint32_t kTimeout = 10; static constexpr uint32_t kLength = 128;
SerialPort* serialPort; static constexpr uint32_t kTimeout = 10;
std::unique_ptr<SerialPort> serialPort;
void SendCommand(Command cmd, uint16_t param = 0); void SendCommand(Command cmd, uint16_t param = 0);

47
Core/App/Common/hc05.hpp Normal file
View File

@@ -0,0 +1,47 @@
#pragma once
#include <cerrno>
#include <cstdint>
#include "../Common/serial_port.hpp"
class Hc05 {
private:
static constexpr uint32_t kBaudRate = 9600;
static constexpr uint32_t kLength = 128;
static constexpr uint32_t kTimeout = 10;
std::unique_ptr<SerialPort> serialPort;
static constexpr uint8_t kCommand = 0xAA;
public:
// App 返回单个字节 Command 结果
enum class Response : uint8_t {
kForward, // 前进
kBackward, // 后退
kTurnLeft, // 左转
kTurnRight, // 右转
kForwardLeft, // 左前方
kForwardRight, // 右前方
kBackwardLeft, // 左后方
kBackwardRight, // 右后方
kTurnAround, // 掉头/180度转向
kStop, // 停止,到达目的地
};
explicit Hc05(UART_HandleTypeDef* uart)
: serialPort(std::make_unique<SerialPort>(uart, kBaudRate, kLength, kTimeout)) {}
~Hc05() = default;
Hc05(const Hc05&) = delete;
Hc05& operator=(const Hc05&) = delete;
Hc05(Hc05&&) = delete;
Hc05& operator=(Hc05&&) = delete;
Response SendCommand() {
Response data;
serialPort->WriteBytesBlocking(reinterpret_cast<const uint8_t*>(&kCommand), sizeof(kCommand));
serialPort->ReadBytesBlocking(reinterpret_cast<uint8_t*>(&data), sizeof(data));
return data;
}
};

36
Core/App/Common/key.hpp Normal file
View File

@@ -0,0 +1,36 @@
#pragma once
#include "../Helper/delay_helper.h"
#include "stm32h5xx_hal_gpio.h"
#include <cstdint>
#include "../Helper/gpio_helper.hpp"
class Key {
private:
static constexpr uint32_t kDebounceDelay = 20;
GpioHelper::Gpio gpio;
GPIO_PinState normalStatus;
public:
explicit Key(GpioHelper::Gpio gpio, GPIO_PinState normalStatus) : gpio(gpio), normalStatus(normalStatus) {
GpioHelper::GpioInit(gpio, GPIO_MODE_INPUT, normalStatus ? GPIO_PULLUP : GPIO_PULLDOWN);
}
~Key() = default;
Key(const Key&) = delete;
Key& operator=(const Key&) = delete;
Key(Key&&) = delete;
Key& operator=(Key&&) = delete;
bool IsPressed() {
auto reading = gpio.Read();
if (reading != normalStatus) {
DelayMs(kDebounceDelay);
reading = gpio.Read();
if (reading != normalStatus) {
return true;
}
}
return false;
}
};

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "main.h" #include "main.h"
#include "stm32h5xx_hal_uart.h"
#include <cstdarg> #include <cstdarg>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
@@ -13,23 +14,35 @@ private:
uint32_t timeout; uint32_t timeout;
std::unique_ptr<char[]> buffer; std::unique_ptr<char[]> buffer;
uint8_t ReadByteForce() {
return handle->Instance->RDR;
}
public: public:
SerialPort(UART_HandleTypeDef* uart, uint32_t length, uint32_t timeout) SerialPort(UART_HandleTypeDef* uart, uint32_t baudRate, uint32_t length, uint32_t timeout)
: handle(uart), timeout(timeout), buffer(std::make_unique<char[]>(length)) {} : handle(uart), timeout(timeout), buffer(std::make_unique<char[]>(length)) {
SetBaudRate(baudRate);
}
~SerialPort() = default; ~SerialPort() = default;
SerialPort(const SerialPort&) = delete;
SerialPort& operator=(const SerialPort&) = delete;
SerialPort(SerialPort&&) = delete;
SerialPort& operator=(SerialPort&&) = delete;
uint8_t ReadByte() { void SetBaudRate(uint32_t baudRate) {
return handle->Instance->RDR; HAL_UART_DeInit(handle);
handle->Init.BaudRate = baudRate;
HAL_UART_Init(handle);
} }
std::string ReadLine() { std::string ReadLine() {
std::string result; std::string result;
result.reserve(128); result.reserve(128);
char c; char c;
ReadByte(); ReadByteForce();
while (true) { while (true) {
auto r = HAL_UART_Receive(handle, reinterpret_cast<uint8_t*>(&c), sizeof(c), timeout); auto r = HAL_UART_Receive(handle, reinterpret_cast<uint8_t*>(&c), sizeof(c), timeout);
if (r != HAL_OK) { if (r != HAL_OK) {
throw std::runtime_error("UART receive error"); throw std::runtime_error("UART receive error");
} }

View File

@@ -19,6 +19,12 @@ public:
captureFlag = GetCaptureFlag(channel); captureFlag = GetCaptureFlag(channel);
} }
~Ultrasonic() = default;
Ultrasonic(const Ultrasonic&) = delete;
Ultrasonic& operator=(const Ultrasonic&) = delete;
Ultrasonic(Ultrasonic&&) = delete;
Ultrasonic& operator=(Ultrasonic&&) = delete;
double GetDistance(uint32_t time = 1) { double GetDistance(uint32_t time = 1) {
double distance = 0; double distance = 0;
for (uint32_t cnt = 0; cnt < time; ++cnt) { for (uint32_t cnt = 0; cnt < time; ++cnt) {
@@ -46,6 +52,7 @@ private:
double MeasureEchoTime() { double MeasureEchoTime() {
timer->Instance->CNT = 0; timer->Instance->CNT = 0;
uint32_t data[2]; uint32_t data[2];
__HAL_TIM_CLEAR_FLAG(timer, captureFlag);
HAL_TIM_IC_Start(timer, channel); HAL_TIM_IC_Start(timer, channel);
try { try {
for (auto& value : data) { for (auto& value : data) {

View File

@@ -6,6 +6,12 @@
class GpioHelper { class GpioHelper {
public: public:
GpioHelper() = delete;
GpioHelper(const GpioHelper&) = delete;
GpioHelper& operator=(const GpioHelper&) = delete;
GpioHelper(GpioHelper&&) = delete;
GpioHelper& operator=(GpioHelper&&) = delete;
struct Gpio { struct Gpio {
GPIO_TypeDef* port; GPIO_TypeDef* port;
uint16_t pin; uint16_t pin;
@@ -56,7 +62,8 @@ public:
return {port, pin}; return {port, pin};
} }
static Gpio GpioInit(const Gpio& gpio, const uint32_t mode, const uint32_t pull, const GPIO_PinState state) { static Gpio GpioInit(const Gpio& gpio, const uint32_t mode, const uint32_t pull,
const std::optional<GPIO_PinState> state = std::nullopt) {
return GpioInit(gpio.port, gpio.pin, mode, pull, state); return GpioInit(gpio.port, gpio.pin, mode, pull, state);
} }

View File

@@ -4,16 +4,15 @@
#include <cstdint> #include <cstdint>
#include <stdexcept> #include <stdexcept>
class TaskHelper { namespace TaskHelper {
public:
template <typename Func> template <typename Func>
static void WaitFor(Func func, int timeoutMilliseconds) { static void WaitFor(Func func, uint32_t timeoutMilliseconds) {
auto start = HAL_GetTick(); auto start = HAL_GetTick();
while (!func()) { while (!func()) {
uint32_t now = HAL_GetTick(); uint32_t now = HAL_GetTick();
if ((now - start) > static_cast<uint32_t>(timeoutMilliseconds)) { if ((now - start) > timeoutMilliseconds) {
throw std::runtime_error("Operation timed out"); throw std::runtime_error("Operation timed out");
} }
} }
} }
}; }; // namespace TaskHelper

View File

@@ -1,36 +1,65 @@
#include "Helper/delay_helper.h" #include "Helper/delay_helper.h"
#include "stm32h563xx.h" #include "stm32h563xx.h"
#include <string>
#include "Center/common_center.hpp" #include "Center/common_center.hpp"
#include "Common/serial_port.hpp"
#include "Helper/gpio_helper.hpp" #include "Helper/gpio_helper.hpp"
#include "Helper/delay_helper.h" #include "config.hpp"
void TerminateHandler() { void TerminateHandler() {
auto led = GpioHelper::GpioInit(GPIOB, GPIO_PIN_0, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_PIN_SET); auto led = Config::kLed;
auto& debugSerialPort = CommonCenter::GetDebugSerialPort();
std::string message;
std::exception_ptr exceptionPtr = std::current_exception();
if (exceptionPtr) {
try {
std::rethrow_exception(exceptionPtr);
} catch (const std::exception& e) {
message = e.what();
} catch (...) {
message = "Unknown exception type";
}
} else {
message = "No active exception, but terminate() was called";
}
while (true) { while (true) {
debugSerialPort.WriteLineBlocking("FATAL ERROR: %s", message.c_str());
led.Toggle(); led.Toggle();
DelayS(1); DelayS(1);
} }
} }
void Setup() { void GpioSetup() {
GpioHelper::EnableAllGpioPeripheral(); GpioHelper::EnableAllGpioPeripheral();
GpioHelper::GpioInit(GPIOB, GPIO_PIN_0, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_PIN_RESET);
}
void CommonSetup() {
CommonCenter::GetUltrasonic();
CommonCenter::GetDfPlayer();
CommonCenter::GetCanMv();
CommonCenter::GetDebugSerialPort();
CommonCenter::GetHc05();
}
void Setup() {
GpioSetup();
DelaySetup(); DelaySetup();
auto ultrasonic = CommonCenter::GetUltrasonic(); CommonSetup();
auto dfPlayer = CommonCenter::GetDfPlayer(); std::set_terminate(TerminateHandler);
auto canMv = CommonCenter::GetCanMv();
} }
extern "C" void AppStart() { extern "C" void AppStart() {
Setup(); Setup();
auto ultrasonic = CommonCenter::GetUltrasonic(); auto& ultrasonic = CommonCenter::GetUltrasonic();
auto dfPlayer = CommonCenter::GetDfPlayer(); auto& debugSerialPort = CommonCenter::GetDebugSerialPort();
auto canMv = CommonCenter::GetCanMv();
while (true) { while (true) {
// Example usage of the classes // Example usage of the classes
ultrasonic.GetDistance(); auto disatnce = ultrasonic.GetDistance();
dfPlayer.PlayTrack(1); debugSerialPort.WriteLineBlocking("Distance: %.2f cm", disatnce);
DelayS(1); // Delay for 1 second
DelayMs(1000); // Delay for 1 second
} }
} }

View File

@@ -6,13 +6,23 @@
#include "./Helper/gpio_helper.hpp" #include "./Helper/gpio_helper.hpp"
struct Config { struct Config {
Config() = delete;
Config(const Config&) = delete;
Config& operator=(const Config&) = delete;
static inline struct { static inline struct {
GpioHelper::Gpio trigger; GpioHelper::Gpio trigger;
TIM_HandleTypeDef* timer; TIM_HandleTypeDef* timer;
uint32_t channel; uint32_t channel;
} kCaptureConfig = {{GPIOA, GPIO_PIN_0}, &htim7, TIM_CHANNEL_1}; } kCaptureConfig = {{GPIOA, GPIO_PIN_0}, &htim7, TIM_CHANNEL_1};
static inline UART_HandleTypeDef* kDebugUart = &hcom_uart[COM1];
static inline UART_HandleTypeDef* kDfPlayerUart = &hcom_uart[COM1]; static inline UART_HandleTypeDef* kDfPlayerUart = &hcom_uart[COM1];
static inline UART_HandleTypeDef* kCanMvUart = &hcom_uart[COM1]; static inline UART_HandleTypeDef* kCanMvUart = &hcom_uart[COM1];
static inline UART_HandleTypeDef* kHc05Uart = &hcom_uart[COM1];
static inline GpioHelper::Gpio kLed = {GPIOB, GPIO_PIN_0};
}; };