Browse Source

V210 | 1. 支持DT600B, 且PWM输出调试通过

DT100B
zhaohe 3 weeks ago
parent
commit
5a1c773812
  1. 4
      .settings/language.settings.xml
  2. 3
      README.md
  3. 3
      flush.bat
  4. 13
      usrc/app_main.cpp
  5. 160
      usrc/board/hal/dbdm_power_ctrl_board.cpp
  6. 6
      usrc/board/hal/dbdm_power_ctrl_board.hpp
  7. 15
      usrc/board/public_board.cpp
  8. 2
      usrc/dmapp_service/air_compressor_ctrl_service.cpp
  9. 2
      usrc/dmapp_service/blower_ctrl_service.cpp
  10. 2
      usrc/project_configs.h
  11. 2
      usrc/version.hpp

4
.settings/language.settings.xml

@ -5,7 +5,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="843221905495606244" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="1478411668713819811" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@ -16,7 +16,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="749006685976287759" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="1384196449194501326" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>

3
README.md

@ -46,6 +46,9 @@
1. 添加新设备DT600B的支持
2. 重构风机和空压机控制相关代码
3. 支持风机状态和空压机状态读取协议支持
V210
1. 支持DT600B, 且PWM输出调试通过
```
```c

3
flush.bat

@ -1,2 +1 @@
C:\ST\STM32CubeIDE_1.17.0\STM32CubeIDE\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.12.3.rel1.win32_1.1.0.202410251130\tools\bin\STM32_Programmer_CLI.exe ^
-c port=SWD -w Debug\transmit_disinfection_micro.hex -rst
C:\ST\STM32CubeIDE_1.17.0\STM32CubeIDE\plugins\com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.win32_2.2.0.202409170845\tools\bin\STM32_Programmer_CLI.exe -c port=SWD -w Debug\transmit_disinfection_micro.hex -rst

13
usrc/app_main.cpp

@ -26,8 +26,7 @@ void StartDefaultTask(void const* argument) { umain(); }
* MAIN *
*******************************************************************************/
extern "C" {
}
extern "C" {}
void debug_light_ctrl() {
static uint32_t lastcall = 0;
@ -121,6 +120,16 @@ void umain() {
uint8_t resetReason = SysMgr::ins()->chipGetResetReason();
zcanbus_send_report(kreport_device_reset, &resetReason, 1, 100);
MX_IWDG_Init();
// ZGPIO gpio;
// DBDMPowerCtrlBoard::TIM8_CH1_INIT_AS_PWM_OUTPUT_PC6(false); //
// DBDMPowerCtrlBoard::TIM8_CH1_SET_DUTY(80);
// DBDMPowerCtrlBoard::TIM3_CH3_INIT_AS_PWM_OUTPUT_PC8(false); //
// DBDMPowerCtrlBoard::TIM3_CH3_SET_DUTY(30);
while (true) {
osDelay(30);
debug_light_ctrl();

160
usrc/board/hal/dbdm_power_ctrl_board.cpp

@ -1,7 +1,18 @@
#include "dbdm_power_ctrl_board.hpp"
using namespace iflytop;
void DBDMPowerCtrlBoard::INIT_PC8_AS_HTIM3_CH3_PWM_OUTPUT() {
static TIM_OC_InitTypeDef TIM3_CH3_sConfigOC = {0};
static bool TIM3_CH3_mirror = false;
void DBDMPowerCtrlBoard::TIM3_CH3_INIT_AS_PWM_OUTPUT_PC8(bool mirror) {
/**
* @brief
*
* 200HZ
*
*/
TIM3_CH3_mirror = mirror;
__HAL_RCC_TIM3_CLK_ENABLE();
/* USER CODE BEGIN TIM3_Init 0 */
@ -9,7 +20,7 @@ void DBDMPowerCtrlBoard::INIT_PC8_AS_HTIM3_CH3_PWM_OUTPUT() {
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
// TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM3_Init 1 */
@ -35,12 +46,14 @@ void DBDMPowerCtrlBoard::INIT_PC8_AS_HTIM3_CH3_PWM_OUTPUT() {
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK) {
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) {
TIM3_CH3_sConfigOC.OCMode = TIM_OCMODE_PWM1;
TIM3_CH3_sConfigOC.Pulse = 0;
TIM3_CH3_sConfigOC.OCPolarity = mirror ? TIM_OCPOLARITY_LOW : TIM_OCPOLARITY_HIGH;
TIM3_CH3_sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
TIM3_CH3_sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
TIM3_CH3_sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &TIM3_CH3_sConfigOC, TIM_CHANNEL_3) != HAL_OK) {
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
@ -48,53 +61,59 @@ void DBDMPowerCtrlBoard::INIT_PC8_AS_HTIM3_CH3_PWM_OUTPUT() {
/**TIM3 GPIO Configuration
PC8 ------> TIM3_CH3
*/
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
TIM3_CH3_SET_DUTY(0);
}
void DBDMPowerCtrlBoard::TIM3_CH3_SET_DUTY(int32_t duty) {
duty = 100 - duty;
if (duty < 0) duty = 0;
if (duty > 100) duty = 100;
if (duty > 98) duty = 98;
TIM_OC_InitTypeDef sConfigOC = {0};
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = duty / 100.0 * __HAL_TIM_GET_AUTORELOAD(&htim3);
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (duty == 0) {
TIM3_CH3_sConfigOC.Pulse = 0;
} else {
TIM3_CH3_sConfigOC.Pulse = duty / 100.0 * (__HAL_TIM_GET_AUTORELOAD(&htim3)+1);
}
HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3);
HAL_TIM_PWM_ConfigChannel(&htim3, &TIM3_CH3_sConfigOC, TIM_CHANNEL_3);
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_3);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
if (duty != 0) {
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
} else {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, TIM3_CH3_mirror ? GPIO_PIN_SET : GPIO_PIN_RESET);
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
}
void DBDMPowerCtrlBoard::INIT_PC6_AS_HTIM8_CH1_PWM_OUTPUT() {
__HAL_RCC_TIM8_CLK_ENABLE();
/***********************************************************************************************************************
* HTIM8_CH1 *
***********************************************************************************************************************/
static TIM_OC_InitTypeDef HTIM8_CH1_sConfigOC = {0};
static bool HTIM8_CH1_mirror = false;
/* USER CODE END TIM8_Init 0 */
void DBDMPowerCtrlBoard::TIM8_CH1_INIT_AS_PWM_OUTPUT_PC6(bool mirror) {
__HAL_RCC_TIM8_CLK_ENABLE();
HTIM8_CH1_mirror = mirror;
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
/* USER CODE BEGIN TIM8_Init 1 */
/* USER CODE END TIM8_Init 1 */
htim8.Instance = TIM8;
htim8.Init.Prescaler = 143;
htim8.Init.Prescaler = 71;
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 99;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
@ -115,14 +134,14 @@ void DBDMPowerCtrlBoard::INIT_PC6_AS_HTIM8_CH1_PWM_OUTPUT() {
if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK) {
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) {
HTIM8_CH1_sConfigOC.OCMode = TIM_OCMODE_PWM1;
HTIM8_CH1_sConfigOC.Pulse = 0;
HTIM8_CH1_sConfigOC.OCPolarity = mirror ? TIM_OCPOLARITY_LOW : TIM_OCPOLARITY_HIGH;
HTIM8_CH1_sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
HTIM8_CH1_sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HTIM8_CH1_sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
HTIM8_CH1_sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim8, &HTIM8_CH1_sConfigOC, TIM_CHANNEL_1) != HAL_OK) {
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
@ -135,38 +154,39 @@ void DBDMPowerCtrlBoard::INIT_PC6_AS_HTIM8_CH1_PWM_OUTPUT() {
if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig) != HAL_OK) {
Error_Handler();
}
/* USER CODE BEGIN TIM8_Init 2 */
/* USER CODE END TIM8_Init 2 */
// HAL_TIM_MspPostInit(&htim8);
__HAL_RCC_GPIOC_CLK_ENABLE();
/**TIM8 GPIO Configuration
PC6 ------> TIM8_CH1
*/
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF3_TIM8;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
TIM8_CH1_SET_DUTY(0);
}
void DBDMPowerCtrlBoard::TIM8_CH1_SET_DUTY(int32_t duty) {
duty = 100 - duty;
if (duty < 0) duty = 0;
if (duty > 100) duty = 100;
if (duty > 98) duty = 98;
TIM_OC_InitTypeDef sConfigOC = {0};
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = duty / 100.0 * __HAL_TIM_GET_AUTORELOAD(&htim8);
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (duty == 0) {
HTIM8_CH1_sConfigOC.Pulse = 0;
} else {
HTIM8_CH1_sConfigOC.Pulse = duty / 100.0 * (__HAL_TIM_GET_AUTORELOAD(&htim8) + 1);
}
HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_ConfigChannel(&htim8, &HTIM8_CH1_sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_Stop(&htim8, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_1);
if (duty != 0) {
HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_1);
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF3_TIM8;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
} else {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, HTIM8_CH1_mirror ? GPIO_PIN_SET : GPIO_PIN_RESET);
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
}

6
usrc/board/hal/dbdm_power_ctrl_board.hpp

@ -11,11 +11,11 @@ class DBDMPowerCtrlBoard {
* @brief
*
*/
static void INIT_PC8_AS_HTIM3_CH3_PWM_OUTPUT();
static void TIM3_CH3_INIT_AS_PWM_OUTPUT_PC8(bool mirror);
static void TIM3_CH3_SET_DUTY(int32_t duty);
static void INIT_PC6_AS_HTIM8_CH1_PWM_OUTPUT();
static void TIM8_CH1_SET_DUTY(int32_t duty);
static void TIM8_CH1_INIT_AS_PWM_OUTPUT_PC6(bool mirror);
static void TIM8_CH1_SET_DUTY(int32_t duty);
private:
};

15
usrc/board/public_board.cpp

@ -105,6 +105,9 @@ void PublicBoard::initialize() {
} else {
m_debugled.initAsOutput(DEBUG_LIGHT_GPIO, kxs_gpio_nopull, false, false);
}
// !!!! FOR DEBUG
// m_debugled.initAsOutput(PF9, kxs_gpio_nopull, false, false);
}
void PublicBoard::setDebugLightState(bool state) { m_debugled.write(state); }
@ -142,9 +145,9 @@ bool PORT::isDT600B() { return PublicBoard::ins()->getProjId() == DT600B; }
bool PORT::isLiquidCtrlBoard() {
if (PublicBoard::ins()->getBoardTypeId() == DT600N_LC_Board || //
PublicBoard::ins()->getBoardTypeId() == DT300N_LC_Board || //
PublicBoard::ins()->getBoardTypeId() == DT300W_LC_Board || //
PublicBoard::ins()->getBoardTypeId() == DT100N_LC_Board || //
PublicBoard::ins()->getBoardTypeId() == DT600B_LC_BOARD //
PublicBoard::ins()->getBoardTypeId() == DT300W_LC_Board || //
PublicBoard::ins()->getBoardTypeId() == DT100N_LC_Board || //
PublicBoard::ins()->getBoardTypeId() == DT600B_LC_BOARD //
) {
return true;
}
@ -153,9 +156,9 @@ bool PORT::isLiquidCtrlBoard() {
bool PORT::isPowerCtrlBoard() {
if (PublicBoard::ins()->getBoardTypeId() == DT600N_PC_Board || //
PublicBoard::ins()->getBoardTypeId() == DT300N_PC_Board || //
PublicBoard::ins()->getBoardTypeId() == DT300W_PC_Board || //
PublicBoard::ins()->getBoardTypeId() == DT100N_PC_Board || //
PublicBoard::ins()->getBoardTypeId() == DT600B_PC_BOARD //
PublicBoard::ins()->getBoardTypeId() == DT300W_PC_Board || //
PublicBoard::ins()->getBoardTypeId() == DT100N_PC_Board || //
PublicBoard::ins()->getBoardTypeId() == DT600B_PC_BOARD //
) {
return true;
}

2
usrc/dmapp_service/air_compressor_ctrl_service.cpp

@ -53,7 +53,7 @@ void AirCompressorCtrlService::initialize() {
// PC4 反馈每圈1个脉冲
m_type = kAirCompressorType_MiniPwmAirPump;
DBDMPowerCtrlBoard::INIT_PC6_AS_HTIM8_CH1_PWM_OUTPUT(); //
DBDMPowerCtrlBoard::TIM8_CH1_INIT_AS_PWM_OUTPUT_PC6(false); //
m_miniPwmAirPump.fbGpio.initAsInput(PC4, kxs_gpio_nopull, kxs_gpio_rising_irq, false /*mirror*/); //
AppPeriodTaskMgr::ins()->regTask("GPIO-IRQ_CNT_READ", []() { m_miniPwmAirPump.blowerFbCnt = PC4_IRQ_CNT; },

2
usrc/dmapp_service/blower_ctrl_service.cpp

@ -109,7 +109,7 @@ void BlowerCtrlService::initialize() {
// 宁波锚点调速风机
m_blowerType = kMiniPwmBlower;
DBDMPowerCtrlBoard::INIT_PC8_AS_HTIM3_CH3_PWM_OUTPUT(); // TIM3
DBDMPowerCtrlBoard::TIM3_CH3_INIT_AS_PWM_OUTPUT_PC8(false); // TIM3
miniPwmBlower.fbGpio.initAsInput(PC9, kxs_gpio_nopull, kxs_gpio_rising_irq, false /*mirror*/); // PC9
miniPwmBlower.enGpio.initAsOutput(PC10, kxs_gpio_nopull, true, false); // PC10

2
usrc/project_configs.h

@ -18,7 +18,7 @@
#define PROJECT "transmit_disinfection_micro_re" // 工程名称
#define SN_HEADER "SN" // SN号前缀
#define DEBUG_UART huart1 // 调试串口
#define DEBUG_LIGHT_GPIO PF9 // 调试指示灯
#define DEBUG_LIGHT_GPIO PE0 // 调试指示灯
#define H2O2_SENSOR_BOARD_DEBUG_LIGHT_GPIO PE2 // 过氧化氢板-调试指示灯
#define BOARD_TYPE_ID_FLASH_ADD 0x080E0000

2
usrc/version.hpp

@ -1,3 +1,3 @@
#pragma once
#define SOFTWARE_VERSION 204 // 软件版本
#define SOFTWARE_VERSION 210 // 软件版本
#define HARDWARE_VERSION 1 // 硬件版本
Loading…
Cancel
Save