Compare commits

...

2 Commits

Author SHA1 Message Date
chauyinn
5307aaa3d6 新增 DfPlayer 和 CanMv 类,优化 UART 读写方法,更新 CommonCenter 以支持新类实例化
Some checks failed
Build and Upload Artifact / build and upload-artifact (push) Has been cancelled
2025-05-10 19:37:31 +08:00
chauyinn
60b49d24c3 重构 SerialPort 类,移除静态成员,改为实例成员,优化 UART 读写方法 2025-05-10 18:58:32 +08:00
8 changed files with 188 additions and 82 deletions

View File

@@ -1,5 +1,7 @@
#pragma once
#include "../Common/can_mv.hpp"
#include "../Common/df_player.hpp"
#include "../Common/ultrasonic.hpp"
#include "../config.hpp"
@@ -13,4 +15,20 @@ public:
}
return *instance;
}
static DfPlayer& GetDfPlayer() {
static DfPlayer* instance = nullptr;
if (instance == nullptr) {
instance = new DfPlayer(Config::kDfPlayerUart);
}
return *instance;
}
static CanMv& GetCanMv() {
static CanMv* instance = nullptr;
if (instance == nullptr) {
instance = new CanMv(Config::kCanMvUart);
}
return *instance;
}
};

View File

@@ -0,0 +1,19 @@
#pragma once
#include <cstdint>
#include "../Common/serial_port.hpp"
class CanMv {
public:
explicit CanMv(UART_HandleTypeDef* uart) : serialPort(new SerialPort(uart, kLength, kTimeout)) {}
~CanMv() {
delete serialPort;
}
private:
static constexpr uint32_t kLength = 128;
static constexpr uint32_t kTimeout = 10;
SerialPort* serialPort;
};

View File

@@ -0,0 +1,41 @@
#include "df_player.hpp"
void DfPlayer::SendCommand(Command cmd, uint16_t param) {
uint8_t buffer[10];
buffer[0] = kStartByte;
buffer[1] = kVersion;
buffer[2] = 0x06;
buffer[3] = static_cast<uint8_t>(cmd);
buffer[4] = kFeedback;
buffer[5] = (param >> 8) & 0xFF;
buffer[6] = param & 0xFF;
uint16_t checksum = 0xFFFF - (kVersion + 0x06 + static_cast<uint8_t>(cmd) + kFeedback + buffer[5] + buffer[6]) + 1;
buffer[7] = (checksum >> 8) & 0xFF;
buffer[8] = checksum & 0xFF;
buffer[9] = kEndByte;
serialPort->WriteBytesBlocking(buffer, sizeof(buffer));
}
void DfPlayer::Play() {
SendCommand(Command::kPlay);
}
void DfPlayer::Stop() {
SendCommand(Command::kStop);
}
void DfPlayer::SetVolume(uint8_t volume) {
if (volume > 30) {
volume = 30;
}
SendCommand(Command::kSetVolume, volume);
}
void DfPlayer::PlayTrack(uint16_t track) {
if (track < 1 || track > 2999) {
return;
}
SendCommand(Command::kPlayTrack, track);
}

View File

@@ -0,0 +1,63 @@
#pragma once
#include <cstdint>
#include "../Common/serial_port.hpp"
class DfPlayer {
public:
explicit DfPlayer(UART_HandleTypeDef* uart) : serialPort(new SerialPort(uart, kLength, kTimeout)) {}
~DfPlayer() {
delete serialPort;
}
void Play();
void Stop();
void SetVolume(uint8_t volume);
void PlayTrack(uint16_t track);
private:
enum class Command : uint8_t {
kNext = 0x01,
kPrevious = 0x02,
kPlayTrack = 0x03,
kVolumeUp = 0x04,
kVolumeDown = 0x05,
kSetVolume = 0x06,
kSetEQ = 0x07,
kSingleLoopPlayTrack = 0x08,
kSetPlaybackDevice = 0x09,
kEnterSleep = 0x0A,
kResetModule = 0x0C,
kPlay = 0x0D,
kPause = 0x0E,
kPlayFolderTrack = 0x0F,
kSetAmplification = 0x10,
kLoopAll = 0x11,
kPlayMp3FolderTrack = 0x12,
kInsertAd = 0x13,
kStopAdPlayBackground = 0x15,
kStop = 0x16,
kQueryStatus = 0x42,
kQueryVolume = 0x43,
kQueryEQ = 0x44,
kQueryUDiskTotalFiles = 0x47,
kQueryTFCardTotalFiles = 0x48,
kQueryFlashTotalFiles = 0x49,
kQueryUDiskCurrentTrack = 0x4B,
kQueryTFCardCurrentTrack = 0x4C,
kQueryFlashCurrentTrack = 0x4D,
};
static constexpr uint32_t kLength = 128;
static constexpr uint32_t kTimeout = 10;
SerialPort* serialPort;
void SendCommand(Command cmd, uint16_t param = 0);
static constexpr uint8_t kStartByte = 0x7E;
static constexpr uint8_t kVersion = 0xFF;
static constexpr uint8_t kFeedback = 0x00;
static constexpr uint8_t kEndByte = 0xEF;
};

View File

@@ -1,5 +0,0 @@
#include "serial_port.hpp"
extern "C" void HAL_UART_TxCpltCallback([[maybe_unused]] UART_HandleTypeDef* huart) {
SerialPort::isTransmitting = false;
}

View File

@@ -1,43 +1,38 @@
#pragma once
#include "stm32h5xx_nucleo.h"
#include "main.h"
#include <cstdarg>
#include <cstdint>
#include <cstring>
#include <memory>
#include <string>
class SerialPort {
private:
static constexpr uint32_t kTransmitTimeout = 1000;
static constexpr auto* kHandle = &hcom_uart[COM1];
static inline char buffer[256] = {0};
friend void HAL_UART_TxCpltCallback(UART_HandleTypeDef* huart);
static inline volatile bool isTransmitting = false;
static void WaitTransmit() {
const auto tick = HAL_GetTick();
while (isTransmitting) {
if (HAL_GetTick() - tick > kTransmitTimeout) {
HAL_UART_AbortTransmit(kHandle);
isTransmitting = false;
}
}
}
UART_HandleTypeDef* handle;
uint32_t timeout;
std::unique_ptr<char[]> buffer;
public:
static uint8_t ReadByte() {
return kHandle->Instance->RDR;
SerialPort(UART_HandleTypeDef* uart, uint32_t length, uint32_t timeout)
: handle(uart), timeout(timeout), buffer(std::make_unique<char[]>(length)) {}
~SerialPort() = default;
uint8_t ReadByte() {
return handle->Instance->RDR;
}
static std::string ReadLine() {
std::string ReadLine() {
std::string result;
result.reserve(128);
char c;
ReadByte();
while (true) {
HAL_UART_Receive(kHandle, reinterpret_cast<uint8_t*>(&c), 1, HAL_MAX_DELAY);
auto r = HAL_UART_Receive(handle, reinterpret_cast<uint8_t*>(&c), sizeof(c), timeout);
if (r != HAL_OK) {
throw std::runtime_error("UART receive error");
}
if (c == '\n') {
if (!result.empty() && result.back() == '\r') {
result.pop_back();
@@ -49,70 +44,39 @@ public:
return result;
}
static void WriteLineDMA(const char* format, ...) {
WaitTransmit();
isTransmitting = true;
va_list args;
va_start(args, format);
int len = vsnprintf(buffer, sizeof(buffer) - 1, format, args);
va_end(args);
if (len < 0 || len > static_cast<int>(sizeof(buffer) - 1)) {
isTransmitting = false;
return;
void ReadBytesBlocking(uint8_t* data, size_t size) {
auto r = HAL_UART_Receive(handle, data, size, timeout);
if (r != HAL_OK) {
throw std::runtime_error("UART receive error");
}
buffer[len] = '\n';
len++;
HAL_UART_Transmit_DMA(kHandle, reinterpret_cast<uint8_t*>(buffer), len);
}
static void WriteLineBlocking(const char* format, ...) {
WaitTransmit();
void WriteBytesBlocking(const uint8_t* data, size_t size) {
HAL_UART_Transmit(handle, const_cast<uint8_t*>(data), size, timeout);
}
void WriteBlocking(const char* format, ...) {
va_list args;
va_start(args, format);
int len = vsnprintf(buffer, sizeof(buffer) - 1, format, args);
auto len = vsnprintf(buffer.get(), sizeof(buffer), format, args);
va_end(args);
if (len < 0 || len > static_cast<int>(sizeof(buffer))) {
return;
}
HAL_UART_Transmit(handle, reinterpret_cast<uint8_t*>(buffer.get()), strlen(buffer.get()), timeout);
}
void WriteLineBlocking(const char* format, ...) {
va_list args;
va_start(args, format);
int len = vsnprintf(buffer.get(), sizeof(buffer) - 1, format, args);
va_end(args);
if (len < 0 || len > static_cast<int>(sizeof(buffer) - 1)) {
return;
}
buffer[len] = '\n';
len++;
HAL_UART_Transmit(kHandle, reinterpret_cast<uint8_t*>(buffer), len, kTransmitTimeout);
}
static void WriteDMA(const char* format, ...) {
WaitTransmit();
isTransmitting = true;
va_list args;
va_start(args, format);
auto len = vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
if (len < 0 || len > static_cast<int>(sizeof(buffer))) {
isTransmitting = false;
return;
}
HAL_UART_Transmit_DMA(kHandle, reinterpret_cast<uint8_t*>(buffer), len);
}
static void WriteBlocking(const char* format, ...) {
WaitTransmit();
va_list args;
va_start(args, format);
auto len = vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
if (len < 0 || len > static_cast<int>(sizeof(buffer))) {
return;
}
HAL_UART_Transmit(kHandle, reinterpret_cast<uint8_t*>(buffer), strlen(buffer), kTransmitTimeout);
}
static void WriteBytesDMA(const uint8_t* data, size_t size) {
WaitTransmit();
isTransmitting = true;
HAL_UART_Transmit_DMA(kHandle, const_cast<uint8_t*>(data), size);
}
static void WriteBytesBlocking(const uint8_t* data, size_t size) {
WaitTransmit();
HAL_UART_Transmit(kHandle, const_cast<uint8_t*>(data), size, kTransmitTimeout);
HAL_UART_Transmit(handle, reinterpret_cast<uint8_t*>(buffer.get()), len, timeout);
}
};

View File

@@ -10,6 +10,8 @@ void Setup() {
GpioHelper::EnableAllGpioPeripheral();
DelaySetup();
auto ultrasonic = CommonCenter::GetUltrasonic();
auto dfPlayer = CommonCenter::GetDfPlayer();
auto canMv = CommonCenter::GetCanMv();
}
extern "C" void AppStart() {
@@ -17,7 +19,6 @@ extern "C" void AppStart() {
auto gpio = GpioHelper::GpioInit(GPIOB, GPIO_PIN_0, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_PIN_SET);
while (true) {
gpio.Toggle();
SerialPort::WriteBlocking("LED is toggled,current state: %s", gpio.Read() ? "OFF" : "ON");
DelayS(1);
}
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include "stm32h563xx.h"
#include "stm32h5xx_hal_uart.h"
#include "tim.h"
#include "./Helper/gpio_helper.hpp"
@@ -11,4 +12,8 @@ struct Config {
TIM_HandleTypeDef* timer;
uint32_t channel;
} kCaptureConfig = {{GPIOA, GPIO_PIN_0}, &htim7, TIM_CHANNEL_1};
static inline UART_HandleTypeDef* kDfPlayerUart = &hcom_uart[COM1];
static inline UART_HandleTypeDef* kCanMvUart = &hcom_uart[COM1];
};