diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..368f69766cf601dd0e3f9e85107d5ac2090093eb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+.vscode/
+.cache/
+build/
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ad4f8450e9f97474ee88f7bc82b8b834460a4355
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+ {
+ "useNewFormat": true
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1692777502148
+
+
+ 1692777502148
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..bc8687f4604c8afc4f3464aefae3e98161669794
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,38 @@
+
+cmake_minimum_required(VERSION 3.21)
+project(UIML)
+
+if(MSVC)
+ add_compile_options("/utf-8")
+endif()
+set(CMAKE_C_STANDARD 99)
+set(CMAKE_CXX_STANDARD 20)
+
+# 子模块添加
+add_subdirectory(tools)
+add_subdirectory(softbus)
+add_subdirectory(conf)
+
+# UIML 静态库部分
+add_library(uiml_static OBJECT
+ ${TOOLS_MODULE_SRC}
+ ${SOFTBUS_MODULE_SRC}
+ ${CONFIG_MODULE_SRC}
+)
+
+target_include_directories(uiml_static PUBLIC
+ ${TOOLS_MODULE_INCL}
+ ${SOFTBUS_MODULE_INCL}
+ ${CONFIG_MODULE_INCL}
+)
+
+if(PROJECT_IS_TOP_LEVEL)
+ target_include_directories(uiml_static PRIVATE test)
+
+ file(GLOB UIML_TEST_SRC test/*.cpp)
+ add_executable(${PROJECT_NAME}_test ${UIML_TEST_SRC} conf/yamlparser.cpp tools/hasher/hasher.c tools/universal_vector/vector.c)
+ # target_link_libraries(${PROJECT_NAME}_test uiml_static)
+ target_include_directories(${PROJECT_NAME}_test PRIVATE test tools/include)
+ add_test(RunTest ${PROJECT_NAME}_test)
+ set_tests_properties(RunTest PROPERTIES FAIL_REGULAR_EXPRESSION "^FAIL:")
+endif()
diff --git a/cmake/UimlUtil.cmake b/cmake/UimlUtil.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..c3ad1126020f0c6359c2cd297f1337661cbde0a5
--- /dev/null
+++ b/cmake/UimlUtil.cmake
@@ -0,0 +1,8 @@
+
+function(uiml_link_to_stm32_target TARGET_NAME CPU_TYPE)
+ get_target_property(TARGET_INCL ${TARGET_NAME} INCLUDE_DIRECTORIES)
+ target_include_directories(uiml_static PRIVATE ${TARGET_INCL})
+ target_compile_options(uiml_static PUBLIC -mcpu=${CPU_TYPE})
+
+ target_link_libraries(${TARGET_NAME} PRIVATE uiml_static)
+endfunction()
diff --git a/conf/CMakeLists.txt b/conf/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2f89024e6e46cbd7ae34c96bf387e41b66094c9f
--- /dev/null
+++ b/conf/CMakeLists.txt
@@ -0,0 +1,7 @@
+
+# 在上级作用域设置配置模块源码列表
+file(GLOB CONFIG_SRC *.c *.cpp)
+set(CONFIG_MODULE_SRC ${CONFIG_SRC} PARENT_SCOPE)
+
+# 添加包含目录
+set(CONFIG_MODULE_INCL ${CMAKE_CURRENT_LIST_DIR} PARENT_SCOPE)
diff --git a/conf/config.c b/conf/config.c
index 6ffcc0acef81b954aecf4cb05ebe89bc75c84c90..deda8d6b695a63d2793500013ca62677d9a2d02c 100644
--- a/conf/config.c
+++ b/conf/config.c
@@ -1,13 +1,16 @@
+
+#include "stddef.h"
+#include "string.h"
#include "config.h"
#include "sys_conf.h"
#include "cmsis_os.h"
-//ģص
+//声明服务模块回调函数
#define SERVICE(service,callback,priority,stackSize) extern void callback(void const *);
SERVICE_LIST
#undef SERVICE
-//бö
+//服务列表枚举
typedef enum
{
#define SERVICE(service,callback,priority,stackSize) service,
@@ -16,10 +19,10 @@ typedef enum
serviceNum
}Module;
-//
+//服务任务句柄
osThreadId serviceTaskHandle[serviceNum];
-//ȡñиֵûҵNULL
+//取出给定配置表中给定配置项的值,没找到则返回NULL
void* _Conf_GetValue(ConfItem* dict, const char* name)
{
if(!dict)
@@ -50,15 +53,15 @@ void* _Conf_GetValue(ConfItem* dict, const char* name)
return NULL;
}
-//FreeRTOSĬ
+//FreeRTOS默认任务
void StartDefaultTask(void const * argument)
{
- //зñֱΪ
+ //创建所有服务任务,将配置表分别作为参数传入
#define SERVICE(service,callback,priority,stackSize) \
osThreadDef(service, callback, priority, 0, stackSize); \
serviceTaskHandle[service] = osThreadCreate(osThread(service), Conf_GetPtr(systemConfig,#service,void));
SERVICE_LIST
#undef SERVICE
- //Լ
+ //销毁自己
vTaskDelete(NULL);
}
diff --git a/conf/config.h b/conf/config.h
index d1b15ce223274023944a49fd6ac23e53728daaa8..7521ed2719c2590bc2126bd50d0a9469946ed870 100644
--- a/conf/config.h
+++ b/conf/config.h
@@ -1,53 +1,67 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
-#include
-#include
-#include
#include
#include
-//
+//弱符号,定义来自STM32 HAL库
+#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /* ARM Compiler V6 */
+ #ifndef __weak
+ #define __weak __attribute__((weak))
+ #endif
+ #ifndef __packed
+ #define __packed __attribute__((packed))
+ #endif
+#elif defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */
+ #ifndef __weak
+ #define __weak __attribute__((weak))
+ #endif /* __weak */
+ #ifndef __packed
+ #define __packed __attribute__((__packed__))
+ #endif /* __packed */
+#endif /* __GNUC__ */
+
+//配置项类型
typedef struct {
- char *name; //
- void *value; //ֵ
+ char *name; //配置名
+ void *value; //配置值
} ConfItem;
-//ûļõĺװ
+//给用户配置文件用的宏封装
#define CF_DICT (ConfItem[])
#define CF_DICT_END {NULL,NULL}
#ifndef IM_PTR
-#define IM_PTR(type,...) (&(type){__VA_ARGS__}) //ȡĵַ
+#define IM_PTR(type,...) (&(type){__VA_ARGS__}) //取立即数的地址
#endif
-//ȡֵӦֱӵãӦʹ·ķװ
+//获取配置值,不应直接调用,应使用下方的封装宏
void* _Conf_GetValue(ConfItem* dict, const char* name);
/*
- @brief жֵǷ
- @param dict:Ŀֵ
- @param name:Ҫҵͨ'/'ָԲڲֵ
- @retval 0: 1:
+ @brief 判断字典中配置名是否存在
+ @param dict:目标字典
+ @param name:要查找的配置名,可通过'/'分隔以查找内层字典
+ @retval 0:不存在 1:存在
*/
#define Conf_ItemExist(dict,name) (_Conf_GetValue((dict),(name))!=NULL)
/*
- @brief ȡֵָ
- @param dict:Ŀֵ
- @param name:Ҫҵͨ'/'ָԲڲֵ
- @param type:ֵ
- @retval ֵָ(type*)ָ룬NULL
+ @brief 获取配置值指针
+ @param dict:目标字典
+ @param name:要查找的配置名,可通过'/'分隔以查找内层字典
+ @param type:配置值的类型
+ @retval 指向配置值的(type*)型指针,若配置名不存在则返回NULL
*/
#define Conf_GetPtr(dict,name,type) ((type*)_Conf_GetValue((dict),(name)))
/*
- @brief ȡֵ
- @param dict:Ŀֵ
- @param name:Ҫҵͨ'/'ָԲڲֵ
- @param type:ֵ
- @param def:Ĭֵ
- @retval typeֵݣdef
+ @brief 获取配置值
+ @param dict:目标字典
+ @param name:要查找的配置名,可通过'/'分隔以查找内层字典
+ @param type:配置值的类型
+ @param def:默认值
+ @retval type型配置值数据,若配置名不存在则返回def
*/
#define Conf_GetValue(dict,name,type,def) (_Conf_GetValue((dict),(name))?(*(type*)(_Conf_GetValue((dict),(name)))):(def))
diff --git a/conf/sys_conf.h b/conf/sys_conf.h
index ce804ef6aff2e9685754639843acf20686212256..e96d9c0c5c84ef634dd5696c903e263db53ff399 100644
--- a/conf/sys_conf.h
+++ b/conf/sys_conf.h
@@ -1,6 +1,6 @@
/*
sys_conf.h
- ϵͳļ
+ 系统配置文件
*/
#ifndef _SYSCONF_H_
@@ -8,8 +8,8 @@
#include "config.h"
-/****************** ******************/
-//ʹConfiguration Wizard
+/****************** 外设配置 ******************/
+//可使用Configuration Wizard配置
//<<< Use Configuration Wizard in Context Menu >>>
//BSP Config
@@ -46,9 +46,9 @@
#endif
// <<< end of configuration section >>>
-/****************** б (X-MACRO) ******************/
+/****************** 服务列表配置 (X-MACRO) ******************/
-//ÿʽ(,,ȼ,ջС)
+//每项格式(服务名,服务任务函数,任务优先级,任务栈大小)
#define SERVICE_LIST \
SERVICE(can, BSP_CAN_TaskCallback, osPriorityRealtime,128) \
SERVICE(uart, BSP_UART_TaskCallback, osPriorityNormal,128) \
@@ -64,13 +64,13 @@
//SERVICE(exti, BSP_EXTI_TaskCallback, osPriorityNormal,256)
-/****************** ñ ******************/
+/****************** 各服务配置表 ******************/
ConfItem* systemConfig = CF_DICT{
- //û
+ //用户逻辑服务配置
{"sys",CF_DICT{
- //̸PID
+ //底盘跟随PID配置
{"rotate-pid",CF_DICT{
{"p", IM_PTR(float, 1.5)},
{"i", IM_PTR(float, 0)},
@@ -82,11 +82,11 @@ ConfItem* systemConfig = CF_DICT{
CF_DICT_END
}},
- //̷
+ //底盘服务配置
{"chassis", CF_DICT{
- //ѭ
+ //任务循环周期
{"task-interval", IM_PTR(uint16_t, 2)},
- //̳ߴϢ
+ //底盘尺寸信息
{"info", CF_DICT{
{"wheelbase", IM_PTR(float, 100)},
{"wheeltrack", IM_PTR(float, 100)},
@@ -95,7 +95,7 @@ ConfItem* systemConfig = CF_DICT{
{"offset-y", IM_PTR(float, 0)},
CF_DICT_END
}},
- //ƶٶ/ٶ
+ //底盘移动速度/加速度配置
{"move", CF_DICT{
{"max-vx", IM_PTR(float, 2000)},
{"max-vy", IM_PTR(float, 2000)},
@@ -104,7 +104,7 @@ ConfItem* systemConfig = CF_DICT{
{"y-acc", IM_PTR(float, 1000)},
CF_DICT_END
}},
- //ǰ
+ //左前电机配置
{"motor-fl", CF_DICT{
{"type", "M3508"},
{"id", IM_PTR(uint16_t, 1)},
@@ -119,7 +119,7 @@ ConfItem* systemConfig = CF_DICT{
}},
CF_DICT_END
}},
- //ǰ
+ //右前电机配置
{"motor-fr", CF_DICT{
{"type", "M3508"},
{"id", IM_PTR(uint16_t, 2)},
@@ -134,7 +134,7 @@ ConfItem* systemConfig = CF_DICT{
}},
CF_DICT_END
}},
- //
+ //左后电机配置
{"motor-bl", CF_DICT{
{"type", "M3508"},
{"id", IM_PTR(uint16_t, 3)},
@@ -149,7 +149,7 @@ ConfItem* systemConfig = CF_DICT{
}},
CF_DICT_END
}},
- //Һ
+ //右后电机配置
{"motor-br", CF_DICT{
{"type", "M3508"},
{"id", IM_PTR(uint16_t, 4)},
@@ -167,14 +167,14 @@ ConfItem* systemConfig = CF_DICT{
CF_DICT_END
}},
- //̨
+ //云台服务配置
{"gimbal", CF_DICT{
- //yaw pitch е
+ //yaw pitch 机械零点
{"zero-yaw",IM_PTR(uint16_t,4010)},
{"zero-pitch",IM_PTR(uint16_t,5300)},
- //ѭ
+ //任务循环周期
{"task-interval", IM_PTR(uint16_t, 10)},
- //pidãΪǶ
+ //陀螺仪pid参数设置,作为角度外环
{"yaw-imu-pid",CF_DICT{
{"p", IM_PTR(float, -90)},
{"i", IM_PTR(float, 0)},
@@ -183,12 +183,12 @@ ConfItem* systemConfig = CF_DICT{
{"max-out", IM_PTR(float, 1000)},
CF_DICT_END
}},
- //̨
+ //云台电机配置
{"motor-yaw", CF_DICT{
{"type", "M6020"},
{"id", IM_PTR(uint16_t, 1)},
{"can-x", IM_PTR(uint8_t, 1)},
- //ڻ
+ //内环参数设置
{"speed-pid", CF_DICT{
{"p", IM_PTR(float, 15)},
{"i", IM_PTR(float, 0)},
@@ -199,7 +199,7 @@ ConfItem* systemConfig = CF_DICT{
}},
CF_DICT_END
}},
- //pidãΪǶ
+ //陀螺仪pid参数设置,作为角度外环
{"pitch-imu-pid",CF_DICT{
{"p", IM_PTR(float, 63)},
{"i", IM_PTR(float, 0)},
@@ -212,7 +212,7 @@ ConfItem* systemConfig = CF_DICT{
{"type", "M6020"},
{"id", IM_PTR(uint16_t, 4)},
{"can-x", IM_PTR(uint8_t, 2)},
- //ڻ
+ //内环参数设置
{"speed-pid", CF_DICT{
{"p", IM_PTR(float, 15)},
{"i", IM_PTR(float, 0)},
@@ -226,13 +226,13 @@ ConfItem* systemConfig = CF_DICT{
CF_DICT_END
}},
- //
+ //发射服务配置
{"shooter", CF_DICT{
- //ѭ
+ //任务循环周期
{"task-interval", IM_PTR(uint16_t, 10)},
- //һĽǶ
+ //拨一发弹丸的角度
{"trigger-angle",IM_PTR(float,45)},
- //
+ //发射机构电机配置
{"fric-motor-left", CF_DICT{
{"type", "M3508"},
{"id", IM_PTR(uint16_t, 2)},
@@ -292,9 +292,9 @@ ConfItem* systemConfig = CF_DICT{
CF_DICT_END
}},
- //CAN
+ //CAN服务配置
{"can", CF_DICT{
- //CANϢ
+ //CAN控制器信息
{"cans", CF_DICT{
{"0", CF_DICT{
{"hcan", &hcan1},
@@ -308,7 +308,7 @@ ConfItem* systemConfig = CF_DICT{
}},
CF_DICT_END
}},
- //ʱ֡
+ //定时帧配置
{"repeat-buffers", CF_DICT{
{"0", CF_DICT{
{"can-x", IM_PTR(uint8_t, 1)},
@@ -339,13 +339,13 @@ ConfItem* systemConfig = CF_DICT{
CF_DICT_END
}},
- //ңط
+ //遥控服务配置
{"rc",CF_DICT{
{"uart-x",IM_PTR(uint8_t, 3)},
CF_DICT_END
}},
- //ϵͳ
+ //裁判系统服务配置
{"judge",CF_DICT{
{"max-tx-queue-length",IM_PTR(uint16_t,20)},
{"task-interval",IM_PTR(uint16_t,150)},
@@ -353,7 +353,7 @@ ConfItem* systemConfig = CF_DICT{
CF_DICT_END
}},
- //ڷ
+ //串口服务配置
{"uart",CF_DICT{
{"uarts",CF_DICT{
{"0",CF_DICT{
@@ -373,12 +373,12 @@ ConfItem* systemConfig = CF_DICT{
CF_DICT_END
}},
- //ߵ
+ //惯导服务配置
{"ins",CF_DICT{
{"spi-x",IM_PTR(uint8_t,1)},
{"tim-x",IM_PTR(uint8_t,10)},
{"channel-x",IM_PTR(uint8_t,1)},
- //¶ȿPID
+ //温度控制PID配置
{"tmp-pid", CF_DICT{
{"p", IM_PTR(float, 0.15)},
{"i", IM_PTR(float, 0.01)},
@@ -390,7 +390,7 @@ ConfItem* systemConfig = CF_DICT{
CF_DICT_END
}},
- //SPI
+ //SPI驱动服务配置
{"spi",CF_DICT{
{"spis",CF_DICT{
{"0",CF_DICT{
@@ -419,7 +419,7 @@ ConfItem* systemConfig = CF_DICT{
CF_DICT_END
}},
- //ʱ
+ //定时器服务配置
{"tim",CF_DICT{
{"tims",CF_DICT{
{"0",CF_DICT{
@@ -433,7 +433,7 @@ ConfItem* systemConfig = CF_DICT{
CF_DICT_END
}},
- //ⲿжϷ
+ //外部中断服务配置
// {"exti",CF_DICT{
// {"extis",CF_DICT{
// {"0",CF_DICT{
diff --git a/conf/yamlparser.cpp b/conf/yamlparser.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..da25920ac67cdf5f819db73edf9d4c5dafd48a2c
--- /dev/null
+++ b/conf/yamlparser.cpp
@@ -0,0 +1,299 @@
+
+/**
+实现一个最小化的、类YAML的,在C板上消耗最小化资源的文本解析器。
+
+限制:
+只能使用最基础的数据类型:int32, uint32, float, 字符串;字典。
+字符串不支持任何形式的转义,而且必须以双引号包围。
+根对象必须为字典。
+一个键只能占用一行。
+元素节点不保存其值类型,读取者读取时必须自行选取与解析器输出行为一致的类型。
+
+只支持小数形式的浮点数(123.456),不支持指数形式。
+如数字被写作浮点形式,即使它的小数部分在当前精度下会变为0,值也会被按float存储。
+
+键名不得包含空格或者冒号(其他任意字符均可)。
+
+没有错误返回机制,因为将Children(字典)与其他32位长度的类型union起来时,已无法自动释放资源。
+检测到未预期的字符时,会直接试图跳转至结尾状态。
+*/
+
+#include
+#include "yamlparser.h"
+#include "hasher.h"
+extern "C" {
+#include "vector.h"
+}
+#include "cmsis_os.h"
+
+static UimlYamlNode* CreateYamlNode() {
+ UimlYamlNode* ret = (UimlYamlNode*)pvPortMalloc(sizeof(UimlYamlNode));
+ ret->Children = NULL;
+ ret->Next = NULL;
+ ret->NameRef = NULL;
+ ret->NameHash = 0;
+ ret->I32 = 0;
+ return ret;
+}
+
+static size_t UimlParseYamlDictIndent(const char* input, UimlYamlNode** output, int indentSpace) {
+ UimlYamlNode* out = nullptr, *current = nullptr;
+ auto inputLength = strlen(input);
+
+ enum { SkipWhitespace, Key, Colon, TryValue, SkipToNewLine, ValueString, ValueNumberBegin, ValueNumberInteger, ValueNumberDecimal, ValueDict } state = SkipWhitespace;
+ enum { NextKey, NextColon, NextValue, NextLine } nextElem = NextKey;
+ enum { Undetermined, vtU32, vtNeg32, vtF32, vtNegF32, vtString, vtDict } valueType = Undetermined;
+ int spacesToSkip = 0;
+ bool decrementSpacesToSkip = true;
+ const char * keyNameRef = nullptr;
+ size_t keyNameLength = 0;
+ union {
+ const char * strValueBegin = nullptr;
+ uint32_t integerPart;
+ };
+ union {
+ char * strValueRef = nullptr;
+ float decimalPart;
+ };
+ float decimalCoeff = 1.0f;
+
+ auto gotoNextElem = [&](){
+ switch (nextElem) {
+ case NextKey: state = Key; nextElem = NextColon; break;
+ case NextColon: state = Colon; nextElem = NextValue; break;
+ case NextValue: state = TryValue; nextElem = NextLine; break;
+ case NextLine: state = SkipToNewLine; break;
+ }
+ };
+
+ spacesToSkip = indentSpace;
+ char c;
+ size_t i, lasti = 0;
+ for (i = 0; i < inputLength; i++) {
+ c = input[i];
+ if (c == '#' && state != ValueString) state = SkipToNewLine; // 注释起始
+ switch (state) {
+ case SkipWhitespace:
+ if (c == '\n') {
+ if (nextElem == NextValue) {
+ state = ValueDict;
+ }
+ break;
+ } else if (c != ' ') {
+ if (spacesToSkip == 0) {
+ spacesToSkip = 0;
+ decrementSpacesToSkip = false;
+ i--;
+ } else if (spacesToSkip == 2) { // 少一格缩进,回退
+ goto BreakLoop;
+ } else {
+ state = SkipToNewLine;
+ }
+ gotoNextElem();
+ } else if (spacesToSkip < 0) {
+ state = SkipToNewLine;
+ } else {
+ if (decrementSpacesToSkip) spacesToSkip--;
+ }
+ break;
+
+ case Key:
+ if (keyNameLength == 0) { // 初始状态
+ keyNameRef = input + i;
+ keyNameLength++;
+ // 新建节点,串入链表
+ auto newNode = CreateYamlNode();
+ if (current != nullptr) current->Next = newNode;
+ current = newNode;
+ current->NameRef = keyNameRef;
+ if (out == nullptr) out = current;
+ } else { // 探测键名
+ if (c == ' ' || c == ':') { // 结束键名
+ i--;
+ state = SkipWhitespace;
+ current->NameHash = Hasher_UIML32((uint8_t*)keyNameRef, keyNameLength);
+ } else { // 键名继续
+ keyNameLength++;
+ }
+ }
+ break;
+
+ case Colon:
+ if (c != ':') {
+ state = SkipToNewLine;
+ }
+ state = SkipWhitespace;
+ break;
+
+ case TryValue:
+ if (c == '"') state = ValueString;
+ else if ((c >= '0' && c <= '9') || c == '-') { state = ValueNumberBegin; i--; }
+ else if (c == ' ') state = SkipWhitespace;
+ else if (c == '\n') state = ValueDict;
+ else state = SkipToNewLine;
+ break;
+
+ case ValueString:
+ if (strValueBegin == nullptr) {
+ strValueBegin = input + i;
+ } else if (c == '"') {
+ auto length = input + i - strValueBegin;
+ valueType = vtString;
+ strValueRef = (char*)pvPortMalloc(length + 1);
+ memcpy(strValueRef, strValueBegin, length);
+ strValueRef[length] = '\0';
+ state = SkipToNewLine;
+ }
+ break;
+
+ case ValueNumberBegin:
+ integerPart = 0;
+ decimalPart = 0.0f;
+ valueType = vtU32;
+ if (c == '-') { valueType = vtNeg32; } // 拿Neg32表示是负数
+ else i--; // 没有负号就回退一位,保证下一位读出来是数字
+ state = ValueNumberInteger; // 直接交给专门处理数字的部分处理
+ break;
+
+ case ValueNumberInteger:
+ if (c >= '0' && c <= '9') {
+ integerPart *= 10;
+ integerPart += (c - '0');
+ } else if (c == '.') {
+ state = ValueNumberDecimal; // 去处理小数
+ valueType = (valueType == vtNeg32) ? vtNegF32 : vtF32;
+ } else if (c == ' ' || c == '\n') {
+ i--;
+ state = SkipToNewLine; // 尝试结束
+ } else {
+ // return UimlYamlInvalidValue;
+ state = SkipToNewLine;
+ }
+ break;
+
+ case ValueNumberDecimal:
+ if (c >= '0' && c <= '9') {
+ decimalCoeff *= 0.1f;
+ decimalPart += decimalCoeff * (c - '0');
+ } else if (c == ' ' || c == '\n') {
+ i--;
+ state = SkipToNewLine; // 尝试结束
+ } else {
+ // return UimlYamlInvalidValue;
+ state = SkipToNewLine;
+ }
+ break;
+
+ case ValueDict:
+ {
+ valueType = vtDict;
+ auto dictResult = UimlParseYamlDictIndent(input + i, ¤t->Children, indentSpace + 2);
+ if ((int)dictResult < 0) { // 如果子级出错,递归退出
+ return dictResult;
+ }
+ i += dictResult;
+ i--; // 加上lasti之后会指向\n,向前退一个字节,确保可以正确结束行
+ state = SkipToNewLine; // 复用这部分代码做好下一个元素的准备
+ break;
+ }
+
+ case SkipToNewLine:
+ if (c == '\n') { // 一行结束
+ if (strValueRef) {
+ } // TODO
+
+ switch (valueType) {
+ case Undetermined: // 没有值也没有Key的空行
+ break;
+ case vtU32: // 没有负号的整数
+ current->U32 = integerPart;
+ break;
+ case vtNeg32: // 负的整数
+ current->I32 = -(int32_t)integerPart;
+ break;
+ case vtF32: // 没有负号的小数
+ current->F32 = integerPart + decimalPart;
+ break;
+ case vtNegF32: // 负的小数
+ current->F32 = -(integerPart + decimalPart);
+ break;
+ case vtString:
+ current->Str = strValueRef;
+ strValueRef = nullptr;
+ break;
+ case vtDict: break;
+ }
+
+ spacesToSkip = indentSpace; // 解析下一个键值对
+ state = SkipWhitespace;
+ nextElem = NextKey;
+ decrementSpacesToSkip = true;
+ keyNameLength = 0;
+ strValueBegin = 0;
+ strValueRef = nullptr;
+ decimalCoeff = 1.0f;
+ lasti = i;
+ break;
+ } else if (c != ' ') {
+ // return UimlYamlInvalidValue;
+ }
+ break;
+ }
+ }
+
+BreakLoop:
+
+ *output = out;
+
+ return lasti == 0 ? i : lasti;
+}
+
+size_t UimlYamlParse(const char* input, UimlYamlNode** output) {
+ *output = CreateYamlNode();
+ return UimlParseYamlDictIndent(input, &((*output)->Children), 0);
+}
+
+UimlYamlNode* UimlYamlGetValue(UimlYamlNode* input, const char* childName) {
+ auto nameLength = strlen(childName);
+ auto nameHash = Hasher_UIML32((uint8_t*)childName, nameLength);
+ UimlYamlNode* ret = input;
+
+ while (ret != NULL) {
+ if (ret->NameHash == nameHash && !strncmp(ret->NameRef, childName, nameLength)) {
+ return ret;
+ }
+ ret = ret->Next;
+ }
+
+ return NULL;
+}
+
+UimlYamlNode* UimlYamlGetValueByPath(UimlYamlNode* input, const char* path) {
+ const char *begin = path, *end;
+ UimlYamlNode *ret = input;
+
+ do {
+ end = strchr(begin, '/');
+ if (end > begin || end == NULL) {
+ auto nameLength = (end == NULL) ? strlen(begin) : (end - begin);
+ auto nameHash = Hasher_UIML32((uint8_t*)begin, nameLength);
+
+ ret = ret->Children;
+
+ while (ret != NULL) {
+ if (ret->NameHash == nameHash && !strncmp(ret->NameRef, begin, nameLength)) {
+ goto Found; // 跳出内循环并跳过错误情况处理
+ }
+ ret = ret->Next;
+ }
+
+ return NULL;
+Found:
+ begin = end + 1;
+ } else if (end == begin) {
+ begin = end + 1; // 没用的单/,只跳过
+ }
+ } while (end != NULL);
+
+ return ret;
+}
diff --git a/conf/yamlparser.h b/conf/yamlparser.h
new file mode 100644
index 0000000000000000000000000000000000000000..d0b00bdd49a362b20e3fbf9b0c476fbad2a384aa
--- /dev/null
+++ b/conf/yamlparser.h
@@ -0,0 +1,29 @@
+
+#include
+#include
+
+struct UimlYamlNode {
+ uint32_t NameHash;
+ const char* NameRef;
+ UimlYamlNode* Next;
+ union {
+ UimlYamlNode* Children;
+ uint32_t U32;
+ int32_t I32;
+ float F32;
+ char* Str;
+ };
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+size_t UimlYamlParse(const char* input, struct UimlYamlNode** output);
+
+struct UimlYamlNode* UimlYamlGetValue(struct UimlYamlNode* input, const char* childName);
+struct UimlYamlNode* UimlYamlGetValueByPath(struct UimlYamlNode* input, const char* path);
+
+#ifdef __cplusplus
+} // extern "C" {
+#endif
diff --git a/inc/bmi088/AHRS.h b/inc/bmi088/AHRS.h
new file mode 100644
index 0000000000000000000000000000000000000000..4beba342324318cef69aa650d946c30a97a28af2
--- /dev/null
+++ b/inc/bmi088/AHRS.h
@@ -0,0 +1,61 @@
+#ifndef AHRS_H
+#define AHRS_H
+
+#include "AHRS_MiddleWare.h"
+
+/**
+ * @brief 根据加速度的数据,磁力计的数据进行四元数初始化
+ * @param[in] 需要初始化的四元数数组
+ * @param[in] 用于初始化的加速度计,(x,y,z)不为空 单位 m/s2
+ * @param[in] 用于初始化的磁力计计,(x,y,z)不为空 单位 uT
+ * @retval 返回空
+ */
+extern void AHRS_init(fp32 quat[4], const fp32 accel[3], const fp32 mag[3]);
+
+/**
+ * @brief 根据陀螺仪的数据,加速度的数据,磁力计的数据进行四元数更新
+ * @param[in] 需要更新的四元数数组
+ * @param[in] 更新定时时间,固定定时调用,例如1000Hz,传入的数据为0.001f,
+ * @param[in] 用于更新的陀螺仪数据,数组顺序(x,y,z) 单位 rad
+ * @param[in] 用于初始化的加速度数据,数组顺序(x,y,z) 单位 m/s2
+ * @param[in] 用于初始化的磁力计数据,数组顺序(x,y,z) 单位 uT
+ * @retval 1:更新成功, 0:更新失败
+ */
+extern bool_t AHRS_update(fp32 quat[4], const fp32 timing_time, const fp32 gyro[3], const fp32 accel[3], const fp32 mag[3]);
+
+/**
+ * @brief 根据四元数大小计算对应的欧拉角偏航yaw
+ * @param[in] 四元数数组,不为NULL
+ * @retval 返回的偏航角yaw 单位 rad
+ */
+extern fp32 get_yaw(const fp32 quat[4]);
+
+/**
+ * @brief 根据四元数大小计算对应的欧拉角俯仰角 pitch
+ * @param[in] 四元数数组,不为NULL
+ * @retval 返回的俯仰角 pitch 单位 rad
+ */
+extern fp32 get_pitch(const fp32 quat[4]);
+/**
+ * @brief 根据四元数大小计算对应的欧拉角横滚角 roll
+ * @param[in] 四元数数组,不为NULL
+ * @retval 返回的横滚角 roll 单位 rad
+ */
+extern fp32 get_roll(const fp32 quat[4]);
+
+/**
+ * @brief 根据四元数大小计算对应的欧拉角yaw,pitch,roll
+ * @param[in] 四元数数组,不为NULL
+ * @param[in] 返回的偏航角yaw 单位 rad
+ * @param[in] 返回的俯仰角pitch 单位 rad
+ * @param[in] 返回的横滚角roll 单位 rad
+ */
+extern void get_angle(const fp32 quat[4], fp32 *yaw, fp32 *pitch, fp32 *roll);
+/**
+ * @brief 返回当前的重力加速度
+ * @param[in] 空
+ * @retval 返回重力加速度 单位 m/s2
+ */
+extern fp32 get_carrier_gravity(void);
+
+#endif
diff --git a/services/ins/bmi088/AHRS_middleware.h b/inc/bmi088/AHRS_middleware.h
similarity index 66%
rename from services/ins/bmi088/AHRS_middleware.h
rename to inc/bmi088/AHRS_middleware.h
index 2351731bbb2c4443a2e28e4c7c294fda7eaafcd0..ab9010af50ebd9b8324bcf0405ff3d184337a2ac 100644
--- a/services/ins/bmi088/AHRS_middleware.h
+++ b/inc/bmi088/AHRS_middleware.h
@@ -2,11 +2,11 @@
/**
****************************(C) COPYRIGHT 2019 DJI****************************
* @file AHRS_MiddleWare.c/h
- * @brief ̬м㣬Ϊ̬ṩغ
+ * @brief 姿态解算中间层,为姿态解算提供相关函数
* @note
* @history
* Version Date Author Modification
- * V1.0.0 Dec-26-2018 RM 1.
+ * V1.0.0 Dec-26-2018 RM 1. 完成
*
@verbatim
==============================================================================
@@ -19,37 +19,37 @@
#ifndef AHRS_MIDDLEWARE_H
#define AHRS_MIDDLEWARE_H
-//¶Ӧ
-typedef signed char int8_t;
-typedef signed short int int16_t;
-typedef signed int int32_t;
-typedef signed long long int64_t;
+// //重新对应的数据类型
+// typedef signed char int8_t;
+// typedef signed short int int16_t;
+// typedef signed int int32_t;
+// typedef signed long long int64_t;
-/* exact-width unsigned integer types */
-typedef unsigned char uint8_t;
-typedef unsigned short int uint16_t;
-typedef unsigned int uint32_t;
-typedef unsigned long long uint64_t;
+// /* exact-width unsigned integer types */
+// typedef unsigned char uint8_t;
+// typedef unsigned short int uint16_t;
+// typedef unsigned int uint32_t;
+// typedef unsigned long long uint64_t;
typedef unsigned char bool_t;
typedef float fp32;
typedef double fp64;
-// NULL
+//定义 NULL
#ifndef NULL
#define NULL 0
#endif
-//PI ֵ
+//定义PI 值
#ifndef PI
#define PI 3.14159265358979f
#endif
-// Ƕ()ת ȵı
+//定义 角度(度)转换到 弧度的比例
#ifndef ANGLE_TO_RAD
#define ANGLE_TO_RAD 0.01745329251994329576923690768489f
#endif
-// ת Ƕȵı
+//定义 弧度 转换到 角度的比例
#ifndef RAD_TO_ANGLE
#define RAD_TO_ANGLE 57.295779513082320876798154814105f
#endif
diff --git a/services/ins/bmi088/BMI088reg.h b/inc/bmi088/BMI088reg.h
similarity index 100%
rename from services/ins/bmi088/BMI088reg.h
rename to inc/bmi088/BMI088reg.h
diff --git a/services/ins/bmi088/bmi088_driver.h b/inc/bmi088/bmi088_driver.h
similarity index 100%
rename from services/ins/bmi088/bmi088_driver.h
rename to inc/bmi088/bmi088_driver.h
diff --git a/services/ins/bmi088/AHRS.lib b/lib/AHRS.lib
similarity index 100%
rename from services/ins/bmi088/AHRS.lib
rename to lib/AHRS.lib
diff --git a/services/bsp/bsp_can.c b/services/bsp/bsp_can.c
index 8e7eefb672b664ef42dfa5e68408c5d826e2e4e1..a1738c8dfd2393a0d38506b5351dabdc2f58c7ed 100644
--- a/services/bsp/bsp_can.c
+++ b/services/bsp/bsp_can.c
@@ -1,34 +1,34 @@
#include "config.h"
#include "softbus.h"
#include "cmsis_os.h"
-
+#include
#include "can.h"
-//CANϢ
+//CAN句柄信息
typedef struct {
CAN_HandleTypeDef* hcan;
- uint8_t number; //canXеX
- SoftBusReceiverHandle fastHandle; //ٹ㲥
+ uint8_t number; //canX中的X
+ SoftBusReceiverHandle fastHandle; //快速广播句柄
}CANInfo;
-//ѭͻ
+//循环发送缓冲区
typedef struct {
- CANInfo* canInfo; //ָCANInfo
- uint16_t frameID; //can֡ID
- uint8_t* data; //can֡8ֽ
+ CANInfo* canInfo; //指向所绑定的CANInfo
+ uint16_t frameID; //can帧ID
+ uint8_t* data; //can帧8字节数据
}CANRepeatBuffer;
-//CAN
+//本CAN服务数据
typedef struct {
- CANInfo* canList; //canб
- uint8_t canNum; //can
- CANRepeatBuffer* repeatBuffers; //ѭͻ
- uint8_t bufferNum; //ѭͻ
- uint8_t initFinished; //ʼɱ־
+ CANInfo* canList; //can列表
+ uint8_t canNum; //can数量
+ CANRepeatBuffer* repeatBuffers; //循环发送缓冲区
+ uint8_t bufferNum; //循环发送缓冲区数量
+ uint8_t initFinished; //初始化完成标志
}CANService;
CANService canService = {0};
-//
+//函数声明
void BSP_CAN_Init(ConfItem* dict);
void BSP_CAN_InitInfo(CANInfo* info, ConfItem* dict);
void BSP_CAN_InitHardware(CANInfo* info);
@@ -38,7 +38,7 @@ bool BSP_CAN_SendOnceCallback(const char* name, SoftBusFrame* frame, void* bindD
void BSP_CAN_TimerCallback(void const *argument);
uint8_t BSP_CAN_SendFrame(CAN_HandleTypeDef* hcan,uint16_t StdId,uint8_t* data);
-//canսж
+//can接收结束中断
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
CAN_RxHeaderTypeDef header;
@@ -52,19 +52,19 @@ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
for(uint8_t i = 0; i < canService.canNum; i++)
{
CANInfo* canInfo = &canService.canList[i];
- if(hcan == canInfo->hcan) //ҵжϻصжӦcanбcan
+ if(hcan == canInfo->hcan) //找到中断回调函数中对应can列表的can
{
uint16_t frameID = header.StdId;
- Bus_FastBroadcastSend(canInfo->fastHandle, {&frameID, rx_data}); //ٹ㲥
+ Bus_FastBroadcastSend(canInfo->fastHandle, {&frameID, rx_data}); //快速广播发布数据
break;
}
}
}
-//canص
+//can任务回调函数
void BSP_CAN_TaskCallback(void const * argument)
{
- //ٽ
+ //进入临界区
portENTER_CRITICAL();
BSP_CAN_Init((ConfItem*)argument);
portEXIT_CRITICAL();
@@ -74,7 +74,7 @@ void BSP_CAN_TaskCallback(void const * argument)
void BSP_CAN_Init(ConfItem* dict)
{
- //ûõcan
+ //计算用户配置的can数量
canService.canNum = 0;
for(uint8_t num = 0; ; num++)
{
@@ -85,7 +85,7 @@ void BSP_CAN_Init(ConfItem* dict)
else
break;
}
- //ʼcanϢ
+ //初始化各can信息
canService.canList = pvPortMalloc(canService.canNum * sizeof(CANInfo));
for(uint8_t num = 0; num < canService.canNum; num++)
{
@@ -93,12 +93,12 @@ void BSP_CAN_Init(ConfItem* dict)
confName[5] = num + '0';
BSP_CAN_InitInfo(&canService.canList[num], Conf_GetPtr(dict, confName, ConfItem));
}
- //ʼCANӲ
+ //初始化CAN硬件参数
for(uint8_t num = 0; num < canService.canNum; num++)
{
BSP_CAN_InitHardware(&canService.canList[num]);
}
- //ûõѭͻ
+ //计算用户配置的循环发送缓冲区数量
canService.bufferNum = 0;
for(uint8_t num = 0; ; num++)
{
@@ -109,7 +109,7 @@ void BSP_CAN_Init(ConfItem* dict)
else
break;
}
- //ʼѭ
+ //初始化各循环缓冲区
canService.repeatBuffers = pvPortMalloc(canService.bufferNum * sizeof(CANRepeatBuffer));
for(uint8_t num = 0; num < canService.bufferNum; num++)
{
@@ -117,14 +117,14 @@ void BSP_CAN_Init(ConfItem* dict)
confName[15] = num + '0';
BSP_CAN_InitRepeatBuffer(&canService.repeatBuffers[num], Conf_GetPtr(dict, confName, ConfItem));
}
- //Ĺ㲥
+ //订阅广播
Bus_RegisterRemoteFunc(NULL, BSP_CAN_SetBufCallback, "/can/set-buf");
Bus_RegisterRemoteFunc(NULL, BSP_CAN_SetBufCallback, "/can/send-once");
canService.initFinished = 1;
}
-//ʼCANϢ
+//初始化CAN信息
void BSP_CAN_InitInfo(CANInfo* info, ConfItem* dict)
{
info->hcan = Conf_GetPtr(dict, "hcan", CAN_HandleTypeDef);
@@ -134,10 +134,10 @@ void BSP_CAN_InitInfo(CANInfo* info, ConfItem* dict)
info->fastHandle = Bus_CreateReceiverHandle(name);
}
-//ʼӲ
+//初始化硬件参数
void BSP_CAN_InitHardware(CANInfo* info)
{
- //CANʼ
+ //CAN过滤器初始化
CAN_FilterTypeDef canFilter = {0};
canFilter.FilterActivation = ENABLE;
canFilter.FilterMode = CAN_FILTERMODE_IDMASK;
@@ -157,30 +157,30 @@ void BSP_CAN_InitHardware(CANInfo* info)
canFilter.FilterBank = 0;
}
HAL_CAN_ConfigFilter(info->hcan, &canFilter);
- //CAN
+ //开启CAN
HAL_CAN_Start(info->hcan);
HAL_CAN_ActivateNotification(info->hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
}
-//ʼѭͻ
+//初始化循环发送缓冲区
void BSP_CAN_InitRepeatBuffer(CANRepeatBuffer* buffer, ConfItem* dict)
{
- //ظ֡can
+ //重复帧绑定can
uint8_t canX = Conf_GetValue(dict, "can-x", uint8_t, 0);
for(uint8_t i = 0; i < canService.canNum; ++i)
if(canService.canList[i].number == canX)
buffer->canInfo = &canService.canList[i];
- //ظ֡canid
+ //设置重复帧can的id域
buffer->frameID = Conf_GetValue(dict, "id", uint16_t, 0x00);
buffer->data = pvPortMalloc(8);
memset(buffer->data, 0, 8);
- //ʱʱظ֡
+ //开启软件定时器定时发送重复帧
uint16_t sendInterval = Conf_GetValue(dict, "interval", uint16_t, 100);
osTimerDef(CAN, BSP_CAN_TimerCallback);
osTimerStart(osTimerCreate(osTimer(CAN), osTimerPeriodic, buffer), sendInterval);
}
-//ϵͳʱص
+//系统定时器回调
void BSP_CAN_TimerCallback(void const *argument)
{
if(!canService.initFinished)
@@ -189,7 +189,7 @@ void BSP_CAN_TimerCallback(void const *argument)
BSP_CAN_SendFrame(buffer->canInfo->hcan, buffer->frameID, buffer->data);
}
-//CAN֡
+//CAN发送数据帧
uint8_t BSP_CAN_SendFrame(CAN_HandleTypeDef* hcan,uint16_t stdId,uint8_t* data)
{
CAN_TxHeaderTypeDef txHeader;
@@ -205,7 +205,7 @@ uint8_t BSP_CAN_SendFrame(CAN_HandleTypeDef* hcan,uint16_t stdId,uint8_t* data)
return retVal;
}
-//ѭijֽԶ̺ص
+//设置循环缓存区某部分字节数据远程函数回调
bool BSP_CAN_SetBufCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
if(!Bus_CheckMapKeys(frame, {"can-x", "id", "pos", "len", "data"}))
@@ -228,7 +228,7 @@ bool BSP_CAN_SetBufCallback(const char* name, SoftBusFrame* frame, void* bindDat
}
return false;
}
-//һ֡canԶ̺ص
+//发送一帧can数据远程函数回调
bool BSP_CAN_SendOnceCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
if(!Bus_CheckMapKeys(frame, {"can-x", "id", "data"}))
diff --git a/services/bsp/bsp_exti.c b/services/bsp/bsp_exti.c
index 225e57c1c9b793975c4902f4384d5d3d73e1f5f4..dd5bfa3fbe170c05822394c6a7525a4644297705 100644
--- a/services/bsp/bsp_exti.c
+++ b/services/bsp/bsp_exti.c
@@ -4,7 +4,7 @@
#include "gpio.h"
#include "stdio.h"
-//EXTI GPIOϢ
+//EXTI GPIO信息
typedef struct
{
GPIO_TypeDef* gpioX;
@@ -12,43 +12,43 @@ typedef struct
SoftBusReceiverHandle fastHandle;
}EXTIInfo;
-//EXTI
+//EXTI服务数据
typedef struct {
EXTIInfo extiList[16];
uint8_t extiNum;
uint8_t initFinished;
}EXTIService;
-//
+//函数声明
void BSP_EXTI_Init(ConfItem* dict);
void BSP_EXIT_InitInfo(EXTIInfo* info, ConfItem* dict);
EXTIService extiService={0};
-//ⲿжϷ
+//外部中断服务函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(!extiService.initFinished)
return;
- uint8_t pin = 31 - __clz((uint32_t)GPIO_Pin);//ʹں˺__clzGPIO_Pinǰ0ĸӶõжߺ
+ uint8_t pin = 31 - __CLZ((uint32_t)GPIO_Pin);//使用内核函数__clz就算GPIO_Pin前导0的个数,从而得到中断线号
EXTIInfo* extiInfo = &extiService.extiList[pin];
GPIO_PinState state = HAL_GPIO_ReadPin(extiInfo->gpioX, GPIO_Pin);
Bus_FastBroadcastSend(extiInfo->fastHandle,{&state});
}
-//EXTIص
+//EXTI任务回调函数
void BSP_EXTI_TaskCallback(void const * argument)
{
- //ٽ
+ //进入临界区
portENTER_CRITICAL();
BSP_EXTI_Init((ConfItem*)argument);
portEXIT_CRITICAL();
vTaskDelete(NULL);
}
-//EXTIʼ
+//EXTI初始化
void BSP_EXTI_Init(ConfItem* dict)
{
- //ûõexit
+ //计算用户配置的exit数量
extiService.extiNum = 0;
for(uint8_t num = 0; ; num++)
{
@@ -59,7 +59,7 @@ void BSP_EXTI_Init(ConfItem* dict)
else
break;
}
- //ʼextiϢ
+ //初始化各exti信息
for(uint8_t num = 0; num < extiService.extiNum; num++)
{
char confName[9] = {0};
@@ -69,14 +69,14 @@ void BSP_EXTI_Init(ConfItem* dict)
extiService.initFinished=1;
}
-//ʼEXTIϢ
+//初始化EXTI信息
void BSP_EXIT_InitInfo(EXTIInfo* info, ConfItem* dict)
{
uint8_t pin = Conf_GetValue(dict, "pin-x", uint8_t, 0);
info[pin].gpioX = Conf_GetPtr(dict, "gpio-x", GPIO_TypeDef);
char name[12] = {0};
sprintf(name,"/exti/pin%d",pin);
- //ӳGPIO_PIN=2^pin
+ //重新映射至GPIO_PIN=2^pin
info[pin].pin = 1 << pin;
info[pin].fastHandle = Bus_CreateReceiverHandle(name);
}
diff --git a/services/bsp/bsp_spi.c b/services/bsp/bsp_spi.c
index f1f8879ee82fab6a88ddbc3ae53e22543648f129..b9806ba053e65fa739bfec1f98e42149b15bde24 100644
--- a/services/bsp/bsp_spi.c
+++ b/services/bsp/bsp_spi.c
@@ -5,6 +5,7 @@
#include "gpio.h"
#include "spi.h"
#include
+#include
typedef struct
{
@@ -13,10 +14,10 @@ typedef struct
uint16_t pin;
}CSInfo;
-//SPIϢ
+//SPI句柄信息
typedef struct {
SPI_HandleTypeDef* hspi;
- uint8_t number; //SPIXеX
+ uint8_t number; //SPIX中的X
osSemaphoreId lock;
CSInfo* csList;
@@ -30,7 +31,7 @@ typedef struct {
SoftBusReceiverHandle fastHandle;
}SPIInfo;
-//SPI
+//SPI服务数据
typedef struct {
SPIInfo* spiList;
uint8_t spiNum;
@@ -39,7 +40,7 @@ typedef struct {
SPIService spiService = {0};
-//
+//函数声明
void BSP_SPI_Init(ConfItem* dict);
void BSP_SPI_InitInfo(SPIInfo* info, ConfItem* dict);
void BSP_SPI_InitCS(SPIInfo* info, ConfItem* dict);
@@ -51,25 +52,25 @@ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
for(uint8_t num = 0; num < spiService.spiNum; num++)
{
SPIInfo* spiInfo = &spiService.spiList[num];
- if(hspi == spiInfo->hspi) //ҵжϻصжӦspiбspi
+ if(hspi == spiInfo->hspi) //找到中断回调函数中对应spi列表的spi
{
- Bus_FastBroadcastSend(spiInfo->fastHandle, {spiService.spiList->recvBuffer.data, &spiService.spiList->recvBuffer.dataLen}); //
- //Ƭѡȫ
+ Bus_FastBroadcastSend(spiInfo->fastHandle, {spiService.spiList->recvBuffer.data, &spiService.spiList->recvBuffer.dataLen}); //发送数据
+ //将片选全部拉高
for(uint8_t i = 0; i < spiService.spiList[num].csNum; i++)
{
HAL_GPIO_WritePin(spiService.spiList[num].csList[i].gpioX, spiService.spiList[num].csList[i].pin, GPIO_PIN_SET);
}
- //
+ //解锁
osSemaphoreRelease(spiService.spiList[num].lock);
break;
}
}
}
-//SPIص
+//SPI任务回调函数
void BSP_SPI_TaskCallback(void const * argument)
{
- //ٽ
+ //进入临界区
portENTER_CRITICAL();
BSP_SPI_Init((ConfItem*)argument);
portEXIT_CRITICAL();
@@ -78,7 +79,7 @@ void BSP_SPI_TaskCallback(void const * argument)
}
void BSP_SPI_Init(ConfItem* dict)
{
- //ûõspi
+ //计算用户配置的spi数量
spiService.spiNum = 0;
for(uint8_t num = 0; ; num++)
{
@@ -90,7 +91,7 @@ void BSP_SPI_Init(ConfItem* dict)
break;
}
- //ʼspiϢ
+ //初始化各spi信息
spiService.spiList = pvPortMalloc(spiService.spiNum * sizeof(SPIInfo));
for(uint8_t num = 0; num < spiService.spiNum; num++)
{
@@ -99,12 +100,12 @@ void BSP_SPI_Init(ConfItem* dict)
BSP_SPI_InitInfo(&spiService.spiList[num], Conf_GetPtr(dict, confName, ConfItem));
}
- //עԶ̷
+ //注册远程服务
Bus_RegisterRemoteFunc(NULL, BSP_SPI_BlockCallback, "/spi/block");
Bus_RegisterRemoteFunc(NULL,BSP_SPI_DMACallback, "/spi/trans/dma");
spiService.initFinished = 1;
}
-//ʼspiϢ
+//初始化spi信息
void BSP_SPI_InitInfo(SPIInfo* info, ConfItem* dict)
{
info->hspi = Conf_GetPtr(dict, "hspi", SPI_HandleTypeDef);
@@ -115,15 +116,15 @@ void BSP_SPI_InitInfo(SPIInfo* info, ConfItem* dict)
info->fastHandle=Bus_CreateReceiverHandle(name);
osSemaphoreDef(lock);
info->lock = osSemaphoreCreate(osSemaphore(lock), 1);
- //ʼƬѡ
+ //初始化片选引脚
BSP_SPI_InitCS(info, Conf_GetPtr(dict, "cs", ConfItem));
- //ʼ
+ //初始化缓冲区
info->recvBuffer.maxBufSize = Conf_GetValue(dict, "max-recv-size", uint16_t, 1);
info->recvBuffer.data = pvPortMalloc(info->recvBuffer.maxBufSize);
memset(info->recvBuffer.data,0,info->recvBuffer.maxBufSize);
}
-//ʼƬѡ
+//初始化片选引脚
void BSP_SPI_InitCS(SPIInfo* info, ConfItem* dict)
{
for(uint8_t num = 0; ; num++)
@@ -135,13 +136,13 @@ void BSP_SPI_InitCS(SPIInfo* info, ConfItem* dict)
else
break;
}
- //ʼspiϢ
+ //初始化各spi信息
info->csList = pvPortMalloc(info->csNum * sizeof(CSInfo));
for(uint8_t num = 0; num < info->csNum; num++)
{
char confName[11] = {0};
sprintf(confName, "%d/pin", num);
- //ӳGPIO_PIN=2^pin
+ //重新映射至GPIO_PIN=2^pin
info->csList[num].pin =1<csList[num].name = Conf_GetPtr(dict, confName, char);
@@ -158,27 +159,27 @@ bool BSP_SPI_DMACallback(const char* name, SoftBusFrame* frame, void* bindData)
uint8_t* txData = (uint8_t*)Bus_GetMapValue(frame, "tx-data");
uint8_t* rxData = NULL;
if(Bus_IsMapKeyExist(frame, "rx-data"))
- rxData = (uint8_t*)Bus_GetMapValue(frame, "rx-data"); //ΪΪnullָspi
+ rxData = (uint8_t*)Bus_GetMapValue(frame, "rx-data"); //不检查该项是因为若为null则指向spi缓冲区
uint16_t len = *(uint16_t*)Bus_GetMapValue(frame, "len");
char* csName = (char*)Bus_GetMapValue(frame, "cs-name");
uint32_t waitTime = (*(bool*)Bus_GetMapValue(frame, "is-block"))? osWaitForever: 0;
for(uint8_t num = 0; num < spiService.spiNum; num++)
{
- if(spiX == spiService.spiList[num].number) //ҵӦspi
+ if(spiX == spiService.spiList[num].number) //找到对应的spi
{
- if(rxData == NULL) //δָջָspi
+ if(rxData == NULL) //若未指定接收缓冲区则指向spi缓冲区
rxData = spiService.spiList[num].recvBuffer.data;
- if(len > spiService.spiList[num].recvBuffer.maxBufSize) //ճȴڻȣش
+ if(len > spiService.spiList[num].recvBuffer.maxBufSize) //若接收长度大于缓冲区长度,则返回错误
return false;
for (uint8_t i = 0; i < spiService.spiList[num].csNum; i++)
{
- if(!strcmp(csName, spiService.spiList[num].csList[i].name)) //ҵӦƬѡ
+ if(!strcmp(csName, spiService.spiList[num].csList[i].name)) //找到对应的片选引脚
{
- //
+ //上锁
if(osSemaphoreWait(spiService.spiList[num].lock, waitTime) != osOK)
return false;
- HAL_GPIO_WritePin(spiService.spiList[num].csList[i].gpioX, spiService.spiList[num].csList[i].pin, GPIO_PIN_RESET); //Ƭѡ,ʼͨ
- HAL_SPI_TransmitReceive_DMA(spiService.spiList[num].hspi, txData, rxData, len); //ʼ
+ HAL_GPIO_WritePin(spiService.spiList[num].csList[i].gpioX, spiService.spiList[num].csList[i].pin, GPIO_PIN_RESET); //拉低片选,开始通信
+ HAL_SPI_TransmitReceive_DMA(spiService.spiList[num].hspi, txData, rxData, len); //开始传输
return true;
}
}
@@ -196,31 +197,31 @@ bool BSP_SPI_BlockCallback(const char* name, SoftBusFrame* frame, void* bindData
uint8_t* txData = (uint8_t*)Bus_GetMapValue(frame, "tx-data");
uint8_t* rxData = NULL;
if(Bus_IsMapKeyExist(frame, "rx-data"))
- rxData = (uint8_t*)Bus_GetMapValue(frame, "rx-data"); //ΪΪnullָspi
+ rxData = (uint8_t*)Bus_GetMapValue(frame, "rx-data"); //不检查该项是因为若为null则指向spi缓冲区
uint16_t len = *(uint16_t*)Bus_GetMapValue(frame, "len");
uint32_t timeout = *(uint32_t*)Bus_GetMapValue(frame, "timeout");
char* csName = (char*)Bus_GetMapValue(frame, "cs-name");
uint32_t waitTime = (*(bool*)Bus_GetMapValue(frame, "is-block"))? osWaitForever: 0;
for(uint8_t num = 0; num < spiService.spiNum; num++)
{
- if(spiX == spiService.spiList[num].number) //ҵӦspi
+ if(spiX == spiService.spiList[num].number) //找到对应的spi
{
- if(rxData == NULL) //δָջָspi
+ if(rxData == NULL) //若未指定接收缓冲区则指向spi缓冲区
rxData = spiService.spiList[num].recvBuffer.data;
- if(len > spiService.spiList[num].recvBuffer.maxBufSize) //ճȴڻȣش
+ if(len > spiService.spiList[num].recvBuffer.maxBufSize) //若接收长度大于缓冲区长度,则返回错误
return false;
spiService.spiList[num].recvBuffer.dataLen = len;
- for (uint8_t i = 0; i < spiService.spiList[num].csNum; i++) //ҵӦƬѡ
+ for (uint8_t i = 0; i < spiService.spiList[num].csNum; i++) //找到对应的片选引脚
{
if(!strcmp(csName, spiService.spiList[num].csList[i].name))
{
- //
+ //上锁
if(osSemaphoreWait(spiService.spiList[num].lock, waitTime) != osOK)
return false;
- HAL_GPIO_WritePin(spiService.spiList[num].csList[i].gpioX, spiService.spiList[num].csList[i].pin, GPIO_PIN_RESET); //Ƭѡ,ʼͨ
- HAL_SPI_TransmitReceive(spiService.spiList[num].hspi, txData, rxData, len, timeout); //ʼ
- HAL_GPIO_WritePin(spiService.spiList[num].csList[i].gpioX, spiService.spiList[num].csList[i].pin, GPIO_PIN_SET); //Ƭѡ,ͨ
- //
+ HAL_GPIO_WritePin(spiService.spiList[num].csList[i].gpioX, spiService.spiList[num].csList[i].pin, GPIO_PIN_RESET); //拉低片选,开始通信
+ HAL_SPI_TransmitReceive(spiService.spiList[num].hspi, txData, rxData, len, timeout); //开始传输
+ HAL_GPIO_WritePin(spiService.spiList[num].csList[i].gpioX, spiService.spiList[num].csList[i].pin, GPIO_PIN_SET); //拉高片选,结束通信
+ //解锁
osSemaphoreRelease(spiService.spiList[num].lock);
return true;
}
diff --git a/services/bsp/bsp_tim.c b/services/bsp/bsp_tim.c
index 086d8d6f86bb4d93bec09306b2f59804fa174790..654aa46ee16114fc5c5dc0799a48ac2cc12980a4 100644
--- a/services/bsp/bsp_tim.c
+++ b/services/bsp/bsp_tim.c
@@ -1,6 +1,8 @@
#include "config.h"
#include "softbus.h"
#include "cmsis_os.h"
+#include
+#include
#include "tim.h"
@@ -8,7 +10,7 @@
#define LIMIT(x,min,max) (x)=(((x)<=(min))?(min):(((x)>=(max))?(max):(x)))
#endif
-//TIMϢ
+//TIM句柄信息
typedef struct
{
TIM_HandleTypeDef *htim;
@@ -16,7 +18,7 @@ typedef struct
SoftBusReceiverHandle fastHandle;
}TIMInfo;
-//TIM
+//TIM服务数据
typedef struct
{
TIMInfo *timList;
@@ -24,7 +26,7 @@ typedef struct
uint8_t initFinished;
}TIMService;
-//
+//函数声明
void BSP_TIM_Init(ConfItem* dict);
void BSP_TIM_InitInfo(TIMInfo* info,ConfItem* dict);
void BSP_TIM_StartHardware(TIMInfo* info,ConfItem* dict);
@@ -38,7 +40,7 @@ void BSP_TIM_UpdateCallback(TIM_HandleTypeDef *htim)
{
for(uint8_t num = 0;numfastHandle,{""});
@@ -46,10 +48,10 @@ void BSP_TIM_UpdateCallback(TIM_HandleTypeDef *htim)
}
}
-//TIMص
+//TIM任务回调函数
void BSP_TIM_TaskCallback(void const * argument)
{
- //ٽ
+ //进入临界区
portENTER_CRITICAL();
BSP_TIM_Init((ConfItem*)argument);
portEXIT_CRITICAL();
@@ -57,10 +59,10 @@ void BSP_TIM_TaskCallback(void const * argument)
vTaskDelete(NULL);
}
-//TIMʼ
+//TIM初始化
void BSP_TIM_Init(ConfItem* dict)
{
- //ûõtim
+ //计算用户配置的tim数量
timService.timNum = 0;
for(uint8_t num = 0; ; num++)
{
@@ -80,14 +82,14 @@ void BSP_TIM_Init(ConfItem* dict)
BSP_TIM_InitInfo(&timService.timList[num], Conf_GetPtr(dict, confName, ConfItem));
BSP_TIM_StartHardware(&timService.timList[num], Conf_GetPtr(dict, confName, ConfItem));
}
- //עԶ̷
+ //注册远程服务
Bus_RegisterRemoteFunc(NULL,BSP_TIM_SettingCallback,"/tim/setting");
Bus_RegisterRemoteFunc(NULL,BSP_TIM_SetDutyCallback,"/tim/pwm/set-duty");
Bus_RegisterRemoteFunc(NULL,BSP_TIM_GetEncodeCallback,"/tim/encode");
timService.initFinished=1;
}
-//ʼTIMϢ
+//初始化TIM信息
void BSP_TIM_InitInfo(TIMInfo* info,ConfItem* dict)
{
info->htim = Conf_GetPtr(dict,"htim",TIM_HandleTypeDef);
@@ -98,7 +100,7 @@ void BSP_TIM_InitInfo(TIMInfo* info,ConfItem* dict)
info->fastHandle=Bus_CreateReceiverHandle(name);
}
-//TIMӲ
+//开启TIM硬件
void BSP_TIM_StartHardware(TIMInfo* info,ConfItem* dict)
{
if(!strcmp(Conf_GetPtr(dict,"mode",char),"encode"))
@@ -114,13 +116,13 @@ void BSP_TIM_StartHardware(TIMInfo* info,ConfItem* dict)
}
else if(!strcmp(Conf_GetPtr(dict,"mode",char),"update-interrupted"))
{
- //ʱжϱ־λһж
+ //清除定时器中断标志位,避免一开启就中断
__HAL_TIM_CLEAR_IT(info->htim, TIM_IT_UPDATE);
HAL_TIM_Base_Start_IT(info->htim);
}
}
-//TIMԶ̺ص
+//TIM设置配置远程函数回调
bool BSP_TIM_SettingCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
if(!Bus_IsMapKeyExist(frame,"tim-x"))
@@ -129,7 +131,7 @@ bool BSP_TIM_SettingCallback(const char* name, SoftBusFrame* frame, void* bindDa
TIMInfo* timInfo = NULL;
for(uint8_t num = 0;num
#include "usart.h"
#define UART_IRQ \
@@ -16,10 +16,10 @@
#define UART_TOTAL_NUM 8
-//UARTϢ
+//UART句柄信息
typedef struct {
UART_HandleTypeDef* huart;
- uint8_t number; //uartXеX
+ uint8_t number; //uartX中的X
struct
{
uint8_t *data;
@@ -29,7 +29,7 @@ typedef struct {
SoftBusReceiverHandle fastHandle;
}UARTInfo;
-//UART
+//UART服务数据
typedef struct {
UARTInfo uartList[UART_TOTAL_NUM];
uint8_t uartNum;
@@ -37,7 +37,7 @@ typedef struct {
}UARTService;
UARTService uartService = {0};
-//
+//函数声明
void BSP_UART_Init(ConfItem* dict);
void BSP_UART_InitInfo(UARTInfo* info, ConfItem* dict);
void BSP_UART_Start_IT(UARTInfo* info);
@@ -46,12 +46,12 @@ bool BSP_UART_ItCallback(const char* name, SoftBusFrame* frame, void* bindData);
bool BSP_UART_DMACallback(const char* name, SoftBusFrame* frame, void* bindData);
void BSP_UART_InitRecvBuffer(UARTInfo* info);
-//uartжϻص
+//uart接收中断回调函数
void BSP_UART_IRQCallback(uint8_t huartX)
{
UARTInfo* uartInfo = &uartService.uartList[huartX - 1];
- if(!uartService.initFinished)//ʼδ־λ
+ if(!uartService.initFinished)//如果初始化未完成则清除标志位
{
(void)uartInfo->huart->Instance->SR;
(void)uartInfo->huart->Instance->DR;
@@ -60,7 +60,7 @@ void BSP_UART_IRQCallback(uint8_t huartX)
if (__HAL_UART_GET_FLAG(uartInfo->huart, UART_FLAG_RXNE))
{
- //ֹԽ
+ //防止数组越界
if(uartInfo->recvBuffer.pos < uartInfo->recvBuffer.maxBufSize)
uartInfo->recvBuffer.data[uartInfo->recvBuffer.pos++] = uartInfo->huart->Instance->DR;
}
@@ -69,16 +69,16 @@ void BSP_UART_IRQCallback(uint8_t huartX)
{
/* clear idle it flag avoid idle interrupt all the time */
__HAL_UART_CLEAR_IDLEFLAG(uartInfo->huart);
- uint16_t recSize=uartInfo->recvBuffer.pos; //ʱposֵΪһ֡ݵij
- Bus_FastBroadcastSend(uartInfo->fastHandle, {uartInfo->recvBuffer.data, &recSize}); //жΪһ֡һ֡
+ uint16_t recSize=uartInfo->recvBuffer.pos; //此时pos值为一帧数据的长度
+ Bus_FastBroadcastSend(uartInfo->fastHandle, {uartInfo->recvBuffer.data, &recSize}); //空闲中断为一帧,发送一帧数据
uartInfo->recvBuffer.pos = 0;
}
}
-//uartص
+//uart任务回调函数
void BSP_UART_TaskCallback(void const * argument)
{
- //ٽ
+ //进入临界区
portENTER_CRITICAL();
BSP_UART_Init((ConfItem*)argument);
portEXIT_CRITICAL();
@@ -88,7 +88,7 @@ void BSP_UART_TaskCallback(void const * argument)
void BSP_UART_Init(ConfItem* dict)
{
- //ûõuart
+ //计算用户配置的uart数量
uartService.uartNum = 0;
for(uint8_t num = 0; ; num++)
{
@@ -99,7 +99,7 @@ void BSP_UART_Init(ConfItem* dict)
else
break;
}
- //ʼuartϢ
+ //初始化各uart信息
for(uint8_t num = 0; num < uartService.uartNum; num++)
{
char confName[] = "uarts/_";
@@ -107,14 +107,14 @@ void BSP_UART_Init(ConfItem* dict)
BSP_UART_InitInfo(uartService.uartList, Conf_GetPtr(dict, confName, ConfItem));
}
- //עԶ̺
+ //注册远程函数
Bus_RegisterRemoteFunc(NULL, BSP_UART_BlockCallback, "/uart/trans/block");
Bus_RegisterRemoteFunc(NULL, BSP_UART_ItCallback, "/uart/trans/it");
Bus_RegisterRemoteFunc(NULL, BSP_UART_DMACallback, "/uart/trans/dma");
uartService.initFinished = 1;
}
-//ʼuartϢ
+//初始化uart信息
void BSP_UART_InitInfo(UARTInfo* info, ConfItem* dict)
{
uint8_t number = Conf_GetValue(dict, "number", uint8_t, 0);
@@ -124,19 +124,19 @@ void BSP_UART_InitInfo(UARTInfo* info, ConfItem* dict)
char name[] = "/uart_/recv";
name[5] = info[number-1].number + '0';
info[number-1].fastHandle = Bus_CreateReceiverHandle(name);
- //ʼջ
+ //初始化接收缓冲区
BSP_UART_InitRecvBuffer(&info[number-1]);
- //uartж
+ //开启uart中断
BSP_UART_Start_IT(&info[number-1]);
}
-//uartж
+//开启uart中断
void BSP_UART_Start_IT(UARTInfo* info)
{
__HAL_UART_ENABLE_IT(info->huart, UART_IT_RXNE);
__HAL_UART_ENABLE_IT(info->huart, UART_IT_IDLE);
}
-//ʼջ
+//初始化接收缓冲区
void BSP_UART_InitRecvBuffer(UARTInfo* info)
{
info->recvBuffer.pos=0;
@@ -144,7 +144,7 @@ void BSP_UART_InitRecvBuffer(UARTInfo* info)
memset(info->recvBuffer.data,0,info->recvBuffer.maxBufSize);
}
-//ص
+//阻塞回调
bool BSP_UART_BlockCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
if(!Bus_CheckMapKeys(frame, {"uart-x", "data", "trans-size", "timeout"}))
@@ -158,7 +158,7 @@ bool BSP_UART_BlockCallback(const char* name, SoftBusFrame* frame, void* bindDat
return true;
}
-//жϷͻص
+//中断发送回调
bool BSP_UART_ItCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
if(!Bus_CheckMapKeys(frame, {"uart-x","data","trans-size"}))
@@ -171,7 +171,7 @@ bool BSP_UART_ItCallback(const char* name, SoftBusFrame* frame, void* bindData)
return true;
}
-//DMAͻص
+//DMA发送回调
bool BSP_UART_DMACallback(const char* name, SoftBusFrame* frame, void* bindData)
{
if(!Bus_CheckMapKeys(frame, {"uart-x","data","trans-size"}))
@@ -184,7 +184,7 @@ bool BSP_UART_DMACallback(const char* name, SoftBusFrame* frame, void* bindData)
return true;
}
-//жϷ
+//生成中断服务函数
#define IRQ_FUN(irq, number) \
void irq(void) \
{ \
diff --git a/services/chassis/chassis_mecanum.c b/services/chassis/chassis_mecanum.c
index 14e3dda1489f0993f8b0f29c1d13f7c2d5011c96..1d4a6cd42e5e8864266186d94d83322014780f35 100644
--- a/services/chassis/chassis_mecanum.c
+++ b/services/chassis/chassis_mecanum.c
@@ -3,6 +3,7 @@
#include "softbus.h"
#include "motor.h"
#include "cmsis_os.h"
+#include "stm32f4xx.h"
#include "arm_math.h"
#ifndef LIMIT
@@ -12,29 +13,29 @@
typedef struct _Chassis
{
- //̳ߴϢ
+ //底盘尺寸信息
struct Info
{
- float wheelbase;//
- float wheeltrack;//־
- float wheelRadius;//ְ뾶
- float offsetX;//xyϵƫ
+ float wheelbase;//轴距
+ float wheeltrack;//轮距
+ float wheelRadius;//轮半径
+ float offsetX;//重心在xy轴上的偏移
float offsetY;
}info;
- //4
+ //4个电机
Motor* motors[4];
- //ƶϢ
+ //底盘移动信息
struct Move
{
- float vx;//ǰƽٶ mm/s
- float vy;//ǰǰƶٶ mm/s
- float vw;//ǰתٶ rad/s
+ float vx;//当前左右平移速度 mm/s
+ float vy;//当前前后移动速度 mm/s
+ float vw;//当前旋转速度 rad/s
- float maxVx,maxVy,maxVw; //ٶ
- Slope xSlope,ySlope; //б
+ float maxVx,maxVy,maxVw; //三个分量最大速度
+ Slope xSlope,ySlope; //斜坡
}move;
- float relativeAngle; //̵ƫǣλ
+ float relativeAngle; //与底盘的偏离角,单位度
uint16_t taskInterval;
@@ -51,23 +52,27 @@ bool Chassis_SetAccCallback(const char* name, SoftBusFrame* frame, void* bindDat
bool Chassis_SetRelativeAngleCallback(const char* name, SoftBusFrame* frame, void* bindData);
void Chassis_StopCallback(const char* name, SoftBusFrame* frame, void* bindData);
-//ص
+static Chassis* GlobalChassis;
+
+//底盘任务回调函数
void Chassis_TaskCallback(void const * argument)
{
- //ٽ
+ //进入临界区
portENTER_CRITICAL();
Chassis chassis={0};
Chassis_Init(&chassis, (ConfItem*)argument);
portEXIT_CRITICAL();
+
+ GlobalChassis = &chassis;
osDelay(2000);
while(1)
{
- /*************ƽٶ**************/
+ /*************计算底盘平移速度**************/
- Chassis_UpdateSlope(&chassis);//˶бº
+ Chassis_UpdateSlope(&chassis);//更新运动斜坡函数数据
- //̨ϵƽٶȽ㵽ƽٶ(̨ƫ)
+ //将云台坐标系下平移速度解算到底盘平移速度(根据云台偏离角)
float gimbalAngleSin=arm_sin_f32(chassis.relativeAngle*PI/180);
float gimbalAngleCos=arm_cos_f32(chassis.relativeAngle*PI/180);
chassis.move.vx=Slope_GetVal(&chassis.move.xSlope) * gimbalAngleCos
@@ -76,7 +81,7 @@ void Chassis_TaskCallback(void const * argument)
+Slope_GetVal(&chassis.move.ySlope) * gimbalAngleCos;
float vw = chassis.move.vw/180*PI;
- /*************ת**************/
+ /*************解算各轮子转速**************/
float rotateRatio[4];
rotateRatio[0]=(chassis.info.wheelbase+chassis.info.wheeltrack)/2.0f-chassis.info.offsetY+chassis.info.offsetX;
@@ -100,47 +105,47 @@ void Chassis_TaskCallback(void const * argument)
void Chassis_Init(Chassis* chassis, ConfItem* dict)
{
- //
+ //任务间隔
chassis->taskInterval = Conf_GetValue(dict, "task-interval", uint16_t, 2);
- //̳ߴϢڽ٣
+ //底盘尺寸信息(用于解算轮速)
chassis->info.wheelbase = Conf_GetValue(dict, "info/wheelbase", float, 0);
chassis->info.wheeltrack = Conf_GetValue(dict, "info/wheeltrack", float, 0);
chassis->info.wheelRadius = Conf_GetValue(dict, "info/wheel-radius", float, 76);
chassis->info.offsetX = Conf_GetValue(dict, "info/offset-x", float, 0);
chassis->info.offsetY = Conf_GetValue(dict, "info/offset-y", float, 0);
- //ƶʼ
+ //移动参数初始化
chassis->move.maxVx = Conf_GetValue(dict, "move/max-vx", float, 2000);
chassis->move.maxVy = Conf_GetValue(dict, "move/max-vy", float, 2000);
chassis->move.maxVw = Conf_GetValue(dict, "move/max-vw", float, 180);
- //̼ٶȳʼ
+ //底盘加速度初始化
float xAcc = Conf_GetValue(dict, "move/x-acc", float, 1000);
float yAcc = Conf_GetValue(dict, "move/y-acc", float, 1000);
Slope_Init(&chassis->move.xSlope, CHASSIS_ACC2SLOPE(chassis->taskInterval, xAcc),0);
Slope_Init(&chassis->move.ySlope, CHASSIS_ACC2SLOPE(chassis->taskInterval, yAcc),0);
- //̵ʼ
+ //底盘电机初始化
chassis->motors[0] = Motor_Init(Conf_GetPtr(dict, "motor-fl", ConfItem));
chassis->motors[1] = Motor_Init(Conf_GetPtr(dict, "motor-fr", ConfItem));
chassis->motors[2] = Motor_Init(Conf_GetPtr(dict, "motor-bl", ConfItem));
chassis->motors[3] = Motor_Init(Conf_GetPtr(dict, "motor-br", ConfItem));
- //õ̵Ϊٶģʽ
+ //设置底盘电机为速度模式
for(uint8_t i = 0; i<4; i++)
{
chassis->motors[i]->changeMode(chassis->motors[i], MOTOR_SPEED_MODE);
}
- //߹㲥Զ̺nameӳ
+ //软总线广播、远程函数name重映射
char* temp = Conf_GetPtr(dict, "name", char);
temp = temp ? temp : "chassis";
uint8_t len = strlen(temp);
- chassis->speedName = pvPortMalloc(len + 7+ 1); //7Ϊ"/ /speed"ijȣ1Ϊ'\0'ij
+ chassis->speedName = pvPortMalloc(len + 7+ 1); //7为"/ /speed"的长度,1为'\0'的长度
sprintf(chassis->speedName, "/%s/speed", temp);
- chassis->accName = pvPortMalloc(len + 5+ 1); //5Ϊ"/ /acc"ijȣ1Ϊ'\0'ij
+ chassis->accName = pvPortMalloc(len + 5+ 1); //5为"/ /acc"的长度,1为'\0'的长度
sprintf(chassis->accName, "/%s/acc", temp);
- chassis->relAngleName = pvPortMalloc(len + 16+ 1); //16Ϊ"/ /relative-angle"ijȣ1Ϊ'\0'ij
+ chassis->relAngleName = pvPortMalloc(len + 16+ 1); //16为"/ /relative-angle"的长度,1为'\0'的长度
sprintf(chassis->relAngleName, "/%s/relative-angle", temp);
- //עԶ̺
+ //注册远程函数
Bus_RegisterRemoteFunc(chassis, Chassis_SetSpeedCallback, chassis->speedName);
Bus_RegisterRemoteFunc(chassis, Chassis_SetAccCallback, chassis->accName);
Bus_RegisterRemoteFunc(chassis, Chassis_SetRelativeAngleCallback, chassis->relAngleName);
@@ -148,13 +153,13 @@ void Chassis_Init(Chassis* chassis, ConfItem* dict)
}
-//б¼ٶ
+//更新斜坡计算速度
void Chassis_UpdateSlope(Chassis* chassis)
{
Slope_NextVal(&chassis->move.xSlope);
Slope_NextVal(&chassis->move.ySlope);
}
-//õٶȻص
+//设置底盘速度回调
bool Chassis_SetSpeedCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
Chassis* chassis = (Chassis*)bindData;
@@ -177,7 +182,7 @@ bool Chassis_SetSpeedCallback(const char* name, SoftBusFrame* frame, void* bindD
}
return true;
}
-//õ̼ٶȻص
+//设置底盘加速度回调
bool Chassis_SetAccCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
Chassis* chassis = (Chassis*)bindData;
@@ -187,7 +192,7 @@ bool Chassis_SetAccCallback(const char* name, SoftBusFrame* frame, void* bindDat
Slope_SetStep(&chassis->move.ySlope, CHASSIS_ACC2SLOPE(chassis->taskInterval, *(float*)Bus_GetMapValue(frame, "ay")));
return true;
}
-//õϵǶȻص
+//设置底盘坐标系分离角度回调
bool Chassis_SetRelativeAngleCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
Chassis* chassis = (Chassis*)bindData;
@@ -195,7 +200,7 @@ bool Chassis_SetRelativeAngleCallback(const char* name, SoftBusFrame* frame, voi
chassis->relativeAngle = *(float*)Bus_GetMapValue(frame, "angle");
return true;
}
-//̼ͣص
+//底盘急停回调
void Chassis_StopCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
Chassis* chassis = (Chassis*)bindData;
diff --git a/services/control/README.md b/services/control/README.md
index 470a6256d43f5f89d545ff1c1b874960193a02d9..95d55f0a9d9ee20c40108abce926506cd781ba49 100644
--- a/services/control/README.md
+++ b/services/control/README.md
@@ -1,7 +1,7 @@
-# ϵͳۺϿģ
+# 系统综合控制模块
---
-## ģ
+## 模块介绍
-ģΪϲ߲ģ飬ңݺһЩٷֱ̨ģݽִУͬ˸ԻӦڴļнбд`sys_control.c`ļֻʾԱдڸҪƵuiͬ˱ʾļδuiƣʵϴڱļнв䡣
\ No newline at end of file
+该模块为最上层决策层模块,负责接收遥控器数据后,进行一些逻辑处理后再分别给底盘云台等模块数据进行执行,不同机器人个性化操作应当在此文件中进行编写,`sys_control.c`文件只进行示例性编写,由于各个机器人需要绘制的ui并不相同,因此本示例文件并未进行ui绘制,实际上次需在本文件中进行补充。
\ No newline at end of file
diff --git a/services/control/sys_control.c b/services/control/sys_control.c
index 43e4fbd10328c7791d90b3eaa8253b6ec9e209e4..099ce1718165c99ef9c0cdbf142412ddc8d9789d 100644
--- a/services/control/sys_control.c
+++ b/services/control/sys_control.c
@@ -3,37 +3,38 @@
#include "config.h"
#include "pid.h"
#include "main.h"
+#include
typedef enum
{
- SYS_FOLLOW_MODE,
- SYS_SPIN_MODE,
- SYS_SEPARATE_MODE
+ SYS_FOLLOW_MODE,
+ SYS_SPIN_MODE,
+ SYS_SEPARATE_MODE
}SysCtrlMode;
typedef struct
{
- struct
- {
- float vx,vy,vw;
- float ax,ay;
- }chassisData; //
+ struct
+ {
+ float vx,vy,vw;
+ float ax,ay;
+ } chassisData; //底盘数据
- struct
- {
- float yaw,pitch;
- float relativeAngle; //̨ƫǶ
- }gimbalData; //̨
+ struct
+ {
+ float targetYaw, targetPitch; // 操纵云台欲达到的目标偏离角度
+ float relativeAngle; //云台偏离角度
+ } gimbalData; //云台数据
- uint8_t mode;
- bool rockerCtrl; // ңƱ־λ
- bool errFlag; // ͣ־λ
- PID rotatePID;
+ uint8_t mode;
+ bool rockerCtrl; // 遥控器控制标志位
+ bool errFlag; // 急停标志位
+ PID rotatePID;
}SysControl;
SysControl sysCtrl={0};
-//
+//函数声明
void Sys_InitInfo(ConfItem *dict);
void Sys_InitReceiver(void);
void Sys_Broadcast(void);
@@ -45,254 +46,258 @@ void Sys_Gimbal_RotateCallback(const char* name, SoftBusFrame* frame, void* bind
void Sys_Shoot_Callback(const char* name, SoftBusFrame* frame, void* bindData);
void Sys_ErrorHandle(void);
-//ʼϢ
+//初始化控制信息
void Sys_InitInfo(ConfItem *dict)
{
- sysCtrl.mode = Conf_GetValue(dict, "init-mode", uint8_t, SYS_FOLLOW_MODE); //Ĭϸģʽ
- sysCtrl.rockerCtrl = Conf_GetValue(dict, "rocker-ctrl", bool, false); //Ĭϼ
- PID_Init(&sysCtrl.rotatePID, Conf_GetPtr(dict, "rotate-pid", ConfItem));
+ sysCtrl.mode = Conf_GetValue(dict, "init-mode", uint8_t, SYS_FOLLOW_MODE); //默认跟随模式
+ sysCtrl.rockerCtrl = Conf_GetValue(dict, "rocker-ctrl", bool, false); //默认键鼠控制
+ PID_Init(&sysCtrl.rotatePID, Conf_GetPtr(dict, "rotate-pid", ConfItem));
}
-//ʼ
+//初始化接收
void Sys_InitReceiver()
{
- //
- Bus_MultiRegisterReceiver(NULL, Sys_Chassis_MoveCallback, {"/rc/key/on-pressing","/rc/left-stick"});
- Bus_RegisterReceiver(NULL, Sys_Chassis_StopCallback, "/rc/key/on-up");
- //̨
- Bus_MultiRegisterReceiver(NULL, Sys_Gimbal_RotateCallback, {"/rc/mouse-move",
- "/rc/right-stick",
- "/gimbal/yaw/relative-angle"});
- //ģʽл
- Bus_MultiRegisterReceiver(NULL, Sys_Mode_ChangeCallback, {"/rc/key/on-click","/rc/switch"});
- //
- Bus_MultiRegisterReceiver(NULL, Sys_Shoot_Callback, {"/rc/key/on-click",
- "/rc/key/on-long-press",
- "/rc/key/on-up",
- "/rc/wheel"});
+ //底盘
+ Bus_MultiRegisterReceiver(NULL, Sys_Chassis_MoveCallback, {"/rc/key/on-pressing","/rc/left-stick"});
+ Bus_RegisterReceiver(NULL, Sys_Chassis_StopCallback, "/rc/key/on-up");
+ //云台
+ Bus_MultiRegisterReceiver(NULL, Sys_Gimbal_RotateCallback, {"/rc/mouse-move",
+ "/rc/right-stick",
+ "/gimbal/yaw/relative-angle"});
+ //模式切换
+ Bus_MultiRegisterReceiver(NULL, Sys_Mode_ChangeCallback, {"/rc/key/on-click","/rc/switch"});
+ //发射
+ Bus_MultiRegisterReceiver(NULL, Sys_Shoot_Callback, {"/rc/key/on-click",
+ "/rc/key/on-long-press",
+ "/rc/key/on-up",
+ "/rc/wheel"});
}
void SYS_CTRL_TaskCallback(void const * argument)
{
- //ٽ
- portENTER_CRITICAL();
- Sys_InitInfo((ConfItem *)argument);
- Sys_InitReceiver();
- portEXIT_CRITICAL();
- while(1)
- {
- if(sysCtrl.errFlag==1)
- Sys_ErrorHandle();
+ //进入临界区
+ portENTER_CRITICAL();
+ Sys_InitInfo((ConfItem *)argument);
+ Sys_InitReceiver();
+ portEXIT_CRITICAL();
+ while(1)
+ {
+ if(sysCtrl.errFlag==1)
+ Sys_ErrorHandle();
- if(sysCtrl.mode==SYS_FOLLOW_MODE)//ģʽ
- {
- PID_SingleCalc(&sysCtrl.rotatePID, 0, sysCtrl.gimbalData.relativeAngle);
- sysCtrl.chassisData.vw = sysCtrl.rotatePID.output;
- }
- else if(sysCtrl.mode==SYS_SPIN_MODE)//Сģʽ
- {
- sysCtrl.chassisData.vw = 240;
- }
- else if(sysCtrl.mode==SYS_SEPARATE_MODE)// ģʽ
- {
- sysCtrl.chassisData.vw = 0;
- }
- Sys_Broadcast();
- osDelay(10);
- }
+ if(sysCtrl.mode==SYS_FOLLOW_MODE)//跟随模式
+ {
+ PID_SingleCalc(&sysCtrl.rotatePID, 0, sysCtrl.gimbalData.relativeAngle);
+ sysCtrl.chassisData.vw = sysCtrl.rotatePID.output;
+ }
+ else if(sysCtrl.mode==SYS_SPIN_MODE)//小陀螺模式
+ {
+ sysCtrl.chassisData.vw = 240;
+ }
+ else if(sysCtrl.mode==SYS_SEPARATE_MODE)// 分离模式
+ {
+ sysCtrl.chassisData.vw = 0;
+ }
+ Sys_Broadcast();
+ osDelay(10);
+ }
}
-//㲥
+//发送广播
void Sys_Broadcast()
{
- Bus_RemoteCall("/chassis/speed", {{"vx", &sysCtrl.chassisData.vx},
- {"vy", &sysCtrl.chassisData.vy},
- {"vw", &sysCtrl.chassisData.vw}});
- Bus_RemoteCall("/chassis/relative-angle", {{"angle", &sysCtrl.gimbalData.relativeAngle}});
- Bus_RemoteCall("/gimbal/setting", {{"yaw", &sysCtrl.gimbalData.yaw},{"pitch", &sysCtrl.gimbalData.pitch}});
+ Bus_RemoteCall("/chassis/speed", {{"vx", {.F32 = sysCtrl.chassisData.vx}},
+ {"vy", {.F32 = sysCtrl.chassisData.vy}},
+ {"vw", {.F32 = sysCtrl.chassisData.vw}}});
+ Bus_RemoteCall("/chassis/relative-angle", {{"angle", {.F32 = sysCtrl.gimbalData.relativeAngle}}});
+ Bus_RemoteCall("/gimbal/setting", {{"yaw", {.F32 = sysCtrl.gimbalData.targetYaw}},
+ {"pitch", {.F32 = sysCtrl.gimbalData.targetPitch}}});
}
-//˶ֹͣص
+//底盘运动及停止回调函数
void Sys_Chassis_MoveCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
- float speedRatio=0;
- if(!strcmp(name,"/rc/key/on-pressing") && !sysCtrl.rockerCtrl) //
- {
- if(!Bus_CheckMapKeys(frame,{"combine-key","key"}))
- return;
- if(!strcmp(Bus_GetMapValue(frame,"combine-key"), "none")) //
- speedRatio=1;
- else if(!strcmp(Bus_GetMapValue(frame,"combine-key"), "shift")) //
- speedRatio=5;
- else if(!strcmp(Bus_GetMapValue(frame,"combine-key"), "ctrl")) //
- speedRatio=0.2;
- switch(*(char*)Bus_GetMapValue(frame,"key"))
- {
- case 'A':
- sysCtrl.chassisData.vx = 200*speedRatio;
- break;
- case 'D':
- sysCtrl.chassisData.vx = -200*speedRatio;
- break;
- case 'W':
- sysCtrl.chassisData.vy = 200*speedRatio;
- break;
- case 'S':
- sysCtrl.chassisData.vy = -200*speedRatio;
- break;
- }
- }
- else if(!strcmp(name,"/rc/left-stick") && sysCtrl.rockerCtrl) //ң
- {
- if(!Bus_CheckMapKeys(frame,{"x","y"}))
- return;
- sysCtrl.chassisData.vx = *(int16_t*)Bus_GetMapValue(frame,"x");
- sysCtrl.chassisData.vy = *(int16_t*)Bus_GetMapValue(frame,"y");
- }
+ float speedRatio=0;
+ if(!strcmp(name,"/rc/key/on-pressing") && !sysCtrl.rockerCtrl) //键鼠控制
+ {
+ if(!Bus_CheckMapKeys(frame,{"combine-key","key"}))
+ return;
+ if(!strcmp(Bus_GetMapValue(frame,"combine-key"), "none")) //正常
+ speedRatio=1;
+ else if(!strcmp(Bus_GetMapValue(frame,"combine-key"), "shift")) //快速
+ speedRatio=5;
+ else if(!strcmp(Bus_GetMapValue(frame,"combine-key"), "ctrl")) //慢速
+ speedRatio=0.2;
+ switch(*(char*)Bus_GetMapValue(frame,"key"))
+ {
+ case 'A':
+ sysCtrl.chassisData.vx = 200*speedRatio;
+ break;
+ case 'D':
+ sysCtrl.chassisData.vx = -200*speedRatio;
+ break;
+ case 'W':
+ sysCtrl.chassisData.vy = 200*speedRatio;
+ break;
+ case 'S':
+ sysCtrl.chassisData.vy = -200*speedRatio;
+ break;
+ }
+ }
+ else if(!strcmp(name,"/rc/left-stick") && sysCtrl.rockerCtrl) //遥控器控制
+ {
+ if(!Bus_CheckMapKeys(frame,{"x","y"}))
+ return;
+ sysCtrl.chassisData.vx = *(int16_t*)Bus_GetMapValue(frame,"x");
+ sysCtrl.chassisData.vy = *(int16_t*)Bus_GetMapValue(frame,"y");
+ }
}
void Sys_Chassis_StopCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
- if(sysCtrl.rockerCtrl || !Bus_IsMapKeyExist(frame, "key"))
- return;
- switch(*(char*)Bus_GetMapValue(frame,"key"))
- {
- case 'A':
- case 'D':
- sysCtrl.chassisData.vx = 0;
- break;
- case 'W':
- case 'S':
- sysCtrl.chassisData.vy = 0;
- break;
- }
+ if(sysCtrl.rockerCtrl || !Bus_IsMapKeyExist(frame, "key"))
+ return;
+ switch(*(char*)Bus_GetMapValue(frame,"key"))
+ {
+ case 'A':
+ case 'D':
+ sysCtrl.chassisData.vx = 0;
+ break;
+ case 'W':
+ case 'S':
+ sysCtrl.chassisData.vy = 0;
+ break;
+ }
}
-//̨תص
+//云台旋转回调函数
void Sys_Gimbal_RotateCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
- if(!strcmp(name,"/rc/mouse-move") && !sysCtrl.rockerCtrl) //
- {
- if(!Bus_CheckMapKeys(frame,{"x","y"}))
- return;
- sysCtrl.gimbalData.yaw +=*(int16_t*)Bus_GetMapValue(frame,"x");
- sysCtrl.gimbalData.pitch +=*(int16_t*)Bus_GetMapValue(frame,"y");
- }
- else if(!strcmp(name,"/rc/right-stick") && sysCtrl.rockerCtrl) //ң
- {
- if(!Bus_CheckMapKeys(frame,{"x","y"}))
- return;
- sysCtrl.gimbalData.yaw +=*(int16_t*)Bus_GetMapValue(frame,"x")*0.01;
- sysCtrl.gimbalData.pitch +=*(int16_t*)Bus_GetMapValue(frame,"y")*0.01;
- }
- else if(!strcmp(name,"/gimbal/yaw/relative-angle"))
- {
- if(!Bus_IsMapKeyExist(frame,"angle"))
- return;
- sysCtrl.gimbalData.relativeAngle = *(float*)Bus_GetMapValue(frame,"angle");
- }
+ if(!strcmp(name,"/rc/mouse-move") && !sysCtrl.rockerCtrl) //键鼠控制
+ {
+ if(!Bus_CheckMapKeys(frame,{"x","y"}))
+ return;
+ // FIXME:鼠标能打多少量未知
+ // sysCtrl.gimbalData.targetYaw +=*(int16_t*)Bus_GetMapValue(frame,"x");
+ // sysCtrl.gimbalData.targetPitch +=*(int16_t*)Bus_GetMapValue(frame,"y");
+ }
+ else if(!strcmp(name,"/rc/right-stick") && sysCtrl.rockerCtrl) //遥控器控制
+ {
+ if(!Bus_CheckMapKeys(frame,{"x","y"}))
+ return;
+ // Yaw:【1 / 660 * 30 = 0.04545】(遥控器满杆量时,期望云台能转到偏移角30度位置)
+ // Pitch:【1 / 660 * 10 = 0.01515】(满杆量时相对转动10度)//FIXME
+ sysCtrl.gimbalData.targetYaw = *(int16_t*)Bus_GetMapValue(frame,"x")*0.045;
+ sysCtrl.gimbalData.targetPitch = *(int16_t*)Bus_GetMapValue(frame,"y")*0.015;
+ }
+ else if(!strcmp(name,"/gimbal/yaw/relative-angle"))
+ {
+ if(!Bus_IsMapKeyExist(frame,"angle"))
+ return;
+ sysCtrl.gimbalData.relativeAngle = *(float*)Bus_GetMapValue(frame,"angle");
+ }
}
-//ģʽлص
+//模式切换回调
void Sys_Mode_ChangeCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
- if(!strcmp(name,"/rc/key/on-click") && !sysCtrl.rockerCtrl) //
- {
- if(!Bus_IsMapKeyExist(frame,"key"))
- return;
- switch(*(char*)Bus_GetMapValue(frame,"key"))
- {
- case 'Q':
- sysCtrl.mode = SYS_SPIN_MODE; //Сģʽ
- break;
- case 'E':
- sysCtrl.mode = SYS_FOLLOW_MODE; //ģʽ
- break;
- case 'R':
- sysCtrl.mode = SYS_SEPARATE_MODE; //ģʽ
- break;
- }
- }
- else if(!strcmp(name,"/rc/switch") ) //ң
- {
- if(Bus_IsMapKeyExist(frame, "right")&& sysCtrl.rockerCtrl)
- {
- switch(*(uint8_t*)Bus_GetMapValue(frame, "right"))
- {
- case 1:
- sysCtrl.mode = SYS_SPIN_MODE; //Сģʽ
- break;
- case 3:
- sysCtrl.mode = SYS_FOLLOW_MODE; //ģʽ
- break;
- case 2:
- sysCtrl.mode = SYS_SEPARATE_MODE; //ģʽ
- break;
- }
- }
- if(Bus_IsMapKeyExist(frame, "left"))
- {
- switch(*(uint8_t*)Bus_GetMapValue(frame, "left"))
- {
- case 1:
- sysCtrl.rockerCtrl = true; //лң
- sysCtrl.errFlag = 0;
- break;
- case 3:
- sysCtrl.rockerCtrl = false; //л
- sysCtrl.errFlag = 0;
- break;
- case 2:
- sysCtrl.errFlag = 1;
- break;
- }
- }
- }
+ if(!strcmp(name,"/rc/key/on-click") && !sysCtrl.rockerCtrl) //键鼠控制
+ {
+ if(!Bus_IsMapKeyExist(frame,"key"))
+ return;
+ switch(*(char*)Bus_GetMapValue(frame,"key"))
+ {
+ case 'Q':
+ sysCtrl.mode = SYS_SPIN_MODE; //小陀螺模式
+ break;
+ case 'E':
+ sysCtrl.mode = SYS_FOLLOW_MODE; //跟随模式
+ break;
+ case 'R':
+ sysCtrl.mode = SYS_SEPARATE_MODE; //分离模式
+ break;
+ }
+ }
+ else if(!strcmp(name,"/rc/switch") ) //遥控器控制
+ {
+ if(Bus_IsMapKeyExist(frame, "right")&& sysCtrl.rockerCtrl)
+ {
+ switch(*(uint8_t*)Bus_GetMapValue(frame, "right"))
+ {
+ case 1:
+ sysCtrl.mode = SYS_SPIN_MODE; //小陀螺模式
+ break;
+ case 3:
+ sysCtrl.mode = SYS_FOLLOW_MODE; //跟随模式
+ break;
+ case 2:
+ sysCtrl.mode = SYS_SEPARATE_MODE; //分离模式
+ break;
+ }
+ }
+ if(Bus_IsMapKeyExist(frame, "left"))
+ {
+ switch(*(uint8_t*)Bus_GetMapValue(frame, "left"))
+ {
+ case 1:
+ sysCtrl.rockerCtrl = true; //切换至遥控器控制
+ sysCtrl.errFlag = 0;
+ break;
+ case 3:
+ sysCtrl.rockerCtrl = false; //切换至键鼠控制
+ sysCtrl.errFlag = 0;
+ break;
+ case 2:
+ sysCtrl.errFlag = 1;
+ break;
+ }
+ }
+ }
}
-//ص
+//发射回调函数
void Sys_Shoot_Callback(const char* name, SoftBusFrame* frame, void* bindData)
{
- if(!strcmp(name,"/rc/key/on-click") && !sysCtrl.rockerCtrl)//
- {
- if(!Bus_IsMapKeyExist(frame,"left"))
- return;
- Bus_RemoteCall("/shooter/mode",{{"mode", "once"}}); //
- }
- else if(!strcmp(name,"/rc/key/on-long-press") && !sysCtrl.rockerCtrl)
- {
- if(!Bus_IsMapKeyExist(frame,"left"))
- return;
- Bus_RemoteCall("/shooter/mode",{{"mode", "continue"}, {"interval-time", IM_PTR(uint16_t, 100)}}); //
- }
- else if(!strcmp(name,"/rc/key/on-up") && !sysCtrl.rockerCtrl)
- {
- if(!Bus_IsMapKeyExist(frame,"left"))
- return;
- Bus_RemoteCall("/shooter/mode",{{"mode", "idle"}}); //
- }
- else if(!strcmp(name,"/rc/wheel") && sysCtrl.rockerCtrl)//ң
- {
- if(!Bus_IsMapKeyExist(frame,"value"))
- return;
- int16_t wheel = *(int16_t*)Bus_GetMapValue(frame,"value");
+ if(!strcmp(name,"/rc/key/on-click") && !sysCtrl.rockerCtrl)//键鼠控制
+ {
+ if(!Bus_IsMapKeyExist(frame,"left"))
+ return;
+ Bus_RemoteCall("/shooter/mode",{{"mode", {"once"}}}); //点射
+ }
+ else if(!strcmp(name,"/rc/key/on-long-press") && !sysCtrl.rockerCtrl)
+ {
+ if(!Bus_IsMapKeyExist(frame,"left"))
+ return;
+ Bus_RemoteCall("/shooter/mode",{{"mode", {"continue"}}, {"interval-time", {.U32 = 100}}}); //连发
+ }
+ else if(!strcmp(name,"/rc/key/on-up") && !sysCtrl.rockerCtrl)
+ {
+ if(!Bus_IsMapKeyExist(frame,"left"))
+ return;
+ Bus_RemoteCall("/shooter/mode",{{"mode", {"idle"}}}); //连发
+ }
+ else if(!strcmp(name,"/rc/wheel") && sysCtrl.rockerCtrl)//遥控器控制
+ {
+ if(!Bus_IsMapKeyExist(frame,"value"))
+ return;
+ int16_t wheel = *(int16_t*)Bus_GetMapValue(frame, "value");
- if(wheel > 600)
- Bus_RemoteCall("/shooter/mode", {{"mode","once"}}); //
- }
+ if(wheel > 600)
+ Bus_RemoteCall("/shooter/mode", {{"mode", {"once"}}}); //点射
+ }
}
-//ͣ
+//急停
void Sys_ErrorHandle(void)
{
- Bus_BroadcastSend("/system/stop",{"",0});
- while(1)
- {
- if(!sysCtrl.errFlag)
- {
- __disable_irq();
- NVIC_SystemReset();
- }
- osDelay(2);
- }
+ Bus_BroadcastSend("/system/stop",{"",0});
+ while(1)
+ {
+ if(!sysCtrl.errFlag)
+ {
+ __disable_irq();
+ NVIC_SystemReset();
+ }
+ osDelay(2);
+ }
}
diff --git a/services/gimbal/gimbal.c b/services/gimbal/gimbal.c
index eb85b027eb82359e1261bb954e1535952864b17a..c3d30aeaceee251d51d43090dc5845a1d5f4d528 100644
--- a/services/gimbal/gimbal.c
+++ b/services/gimbal/gimbal.c
@@ -10,21 +10,21 @@
typedef struct _Gimbal
{
- //yawpitch
+ //yaw、pitch电机
Motor* motors[2];
- uint16_t zeroAngle[2]; //
- float relativeAngle; //̨ƫǶ
+ uint16_t zeroAngle[2]; //零点
+ float relativeAngle; //云台偏离角度
struct
{
- // float eulerAngle[3]; //ŷ
+ // float eulerAngle[3]; //欧拉角
float lastEulerAngle[3];
float totalEulerAngle[3];
PID pid[2];
}imu;
- float angle[2]; //̨Ƕ
+ float angle[2]; //云台角度
uint16_t taskInterval;
- //߹㲥Զ̺name
+ //软总线广播、远程函数name
char* yawRelAngleName;
char* imuEulerAngleName;
char* settingName;
@@ -38,72 +38,77 @@ void Gimbal_BroadcastCallback(const char* name, SoftBusFrame* frame, void* bindD
bool Gimbal_SettingCallback(const char* name, SoftBusFrame* frame, void* bindData);
void Gimbal_StopCallback(const char* name, SoftBusFrame* frame, void* bindData);
+static Gimbal* GlobalGimbal;
+
void Gimbal_TaskCallback(void const * argument)
{
- //ٽ
+ //进入临界区
portENTER_CRITICAL();
Gimbal gimbal={0};
Gimbal_Init(&gimbal, (ConfItem*)argument);
portEXIT_CRITICAL();
osDelay(2000);
- Gimbal_TotalAngleInit(&gimbal); //̨
- //̨ĵģʽimuǶٶȷڻ
+ Gimbal_TotalAngleInit(&gimbal); //计算云台零点
+ //计算好云台零点后,更改电机模式,imu反馈做角度外环电机速度反馈做内环
gimbal.motors[0]->changeMode(gimbal.motors[0], MOTOR_SPEED_MODE);
gimbal.motors[1]->changeMode(gimbal.motors[1], MOTOR_SPEED_MODE);
+
+ GlobalGimbal = &gimbal;
+
while(1)
{
- //Ƕȴpid
- PID_SingleCalc(&gimbal.imu.pid[0], gimbal.angle[0], gimbal.imu.totalEulerAngle[0]);
+ //计算角度串级pid
+ PID_SingleCalc(&gimbal.imu.pid[0], gimbal.angle[0], gimbal.relativeAngle/*gimbal.imu.totalEulerAngle[0]*/);
PID_SingleCalc(&gimbal.imu.pid[1], gimbal.angle[1], gimbal.imu.totalEulerAngle[1]);
gimbal.motors[0]->setTarget(gimbal.motors[0], gimbal.imu.pid[0].output);
gimbal.motors[1]->setTarget(gimbal.motors[1], gimbal.imu.pid[1].output);
- //̨ĽǶ
+ //解算云台距离零点的角度
gimbal.relativeAngle = gimbal.motors[0]->getData(gimbal.motors[0], "totalAngle");
- int16_t turns = (int32_t)gimbal.relativeAngle / 360; //ת
- turns = turns < 0 ? turns - 1 : turns; //ǸһȦʹƫDZ
- gimbal.relativeAngle -= turns*360; //0-360
- Bus_BroadcastSend(gimbal.yawRelAngleName, {{"angle", &gimbal.relativeAngle}}); //㲥̨ƫ
+ int16_t turns = (int32_t)gimbal.relativeAngle / 360; //转数
+ turns = turns < 0 ? turns - 1 : turns; //如果是负数多减一圈使偏离角变成正数
+ gimbal.relativeAngle -= turns*360; //0-360度
+ Bus_BroadcastSend(gimbal.yawRelAngleName, {{"angle", &gimbal.relativeAngle}}); //广播云台偏离角
osDelay(gimbal.taskInterval);
}
}
void Gimbal_Init(Gimbal* gimbal, ConfItem* dict)
{
- //
+ //任务间隔
gimbal->taskInterval = Conf_GetValue(dict, "task-interval", uint16_t, 2);
- //̨
+ //云台零点
gimbal->zeroAngle[0] = Conf_GetValue(dict, "zero-yaw", uint16_t, 0);
gimbal->zeroAngle[1] = Conf_GetValue(dict, "zero-pitch", uint16_t, 0);
- //̨ʼ
+ //云台电机初始化
gimbal->motors[0] = Motor_Init(Conf_GetPtr(dict, "motor-yaw", ConfItem));
gimbal->motors[1] = Motor_Init(Conf_GetPtr(dict, "motor-pitch", ConfItem));
PID_Init(&gimbal->imu.pid[0], Conf_GetPtr(dict, "yaw-imu-pid", ConfItem));
PID_Init(&gimbal->imu.pid[1], Conf_GetPtr(dict, "pitch-imu-pid", ConfItem));
- //㲥Զ̺nameӳ
+ //广播、远程函数name重映射
char* temp = Conf_GetPtr(dict, "name", char);
temp = temp ? temp : "gimbal";
uint8_t len = strlen(temp);
- gimbal->settingName = pvPortMalloc(len + 9+ 1); //9Ϊ"/ /setting"ijȣ1Ϊ'\0'ij
+ gimbal->settingName = pvPortMalloc(len + 9+ 1); //9为"/ /setting"的长度,1为'\0'的长度
sprintf(gimbal->settingName, "/%s/setting", temp);
- gimbal->yawRelAngleName = pvPortMalloc(len + 20+ 1); //20Ϊ"/ /yaw/relative-angle"ijȣ1Ϊ'\0'ij
+ gimbal->yawRelAngleName = pvPortMalloc(len + 20+ 1); //20为"/ /yaw/relative-angle"的长度,1为'\0'的长度
sprintf(gimbal->yawRelAngleName, "/%s/yaw/relative-angle", temp);
temp = Conf_GetPtr(dict, "ins-name", char);
temp = temp ? temp : "ins";
len = strlen(temp);
- gimbal->imuEulerAngleName = pvPortMalloc(len + 13+ 1); //13Ϊ"/ /euler-angle"ijȣ1Ϊ'\0'ij
+ gimbal->imuEulerAngleName = pvPortMalloc(len + 13+ 1); //13为"/ /euler-angle"的长度,1为'\0'的长度
sprintf(gimbal->imuEulerAngleName, "/%s/euler-angle", temp);
- //õģʽΪδúǰpidʹﵽimuijʼ
+ //不在这里设置电机模式,因为在未设置好零点前,pid会驱使电机达到编码器的零点或者imu的初始化零点
- //ע㲥Զ̺ص
+ //注册广播、远程函数回调函数
Bus_RegisterReceiver(gimbal, Gimbal_BroadcastCallback, gimbal->imuEulerAngleName);
Bus_RegisterRemoteFunc(gimbal, Gimbal_SettingCallback, gimbal->settingName);
- Bus_RegisterReceiver(gimbal, Gimbal_StopCallback, "/system/stop"); //ͣ
+ Bus_RegisterReceiver(gimbal, Gimbal_StopCallback, "/system/stop"); //急停
}
void Gimbal_BroadcastCallback(const char* name, SoftBusFrame* frame, void* bindData)
@@ -117,7 +122,7 @@ void Gimbal_BroadcastCallback(const char* name, SoftBusFrame* frame, void* bindD
float yaw = *(float*)Bus_GetMapValue(frame, "yaw");
float pitch = *(float*)Bus_GetMapValue(frame, "pitch");
float roll = *(float*)Bus_GetMapValue(frame, "roll");
- Gimbal_StatAngle(gimbal, yaw, pitch, roll); //ͳ̨Ƕ
+ Gimbal_StatAngle(gimbal, yaw, pitch, roll); //统计云台角度
}
}
bool Gimbal_SettingCallback(const char* name, SoftBusFrame* frame, void* bindData)
@@ -135,7 +140,7 @@ bool Gimbal_SettingCallback(const char* name, SoftBusFrame* frame, void* bindDat
return true;
}
-void Gimbal_StopCallback(const char* name, SoftBusFrame* frame, void* bindData) //ͣ
+void Gimbal_StopCallback(const char* name, SoftBusFrame* frame, void* bindData) //急停
{
Gimbal* gimbal = (Gimbal*)bindData;
for(uint8_t i = 0; i<2; i++)
@@ -156,9 +161,9 @@ void Gimbal_StatAngle(Gimbal* gimbal, float yaw, float pitch, float roll)
dAngle = -gimbal->imu.lastEulerAngle[i] - (360 - eulerAngle[i]);
else
dAngle = eulerAngle[i] - gimbal->imu.lastEulerAngle[i];
- //Ƕ
+ //将角度增量加入计数器
gimbal->imu.totalEulerAngle[i] += dAngle;
- //¼Ƕ
+ //记录角度
gimbal->imu.lastEulerAngle[i] = eulerAngle[i];
}
}
@@ -169,12 +174,12 @@ void Gimbal_TotalAngleInit(Gimbal* gimbal)
{
float angle = 0;
angle = gimbal->motors[i]->getData(gimbal->motors[i], "angle");
- angle = angle - (float)gimbal->zeroAngle[i]*360/8191; //ĽǶ
- if(angle < -180) //Ƕת-180~180ȣʹ̨ת
+ angle = angle - (float)gimbal->zeroAngle[i]*360/8191; //计算距离零点的角度
+ if(angle < -180) //将角度转化到-180~180度,这样可以使云台以最近距离旋转至零点
angle += 360;
else if(angle > 180)
angle -= 360;
gimbal->imu.totalEulerAngle[i] = angle;
- gimbal->motors[i]->initTotalAngle(gimbal->motors[i], angle); //õʼǶ
+ gimbal->motors[i]->initTotalAngle(gimbal->motors[i], angle); //设置电机的起始角度
}
}
diff --git a/services/ins/bmi088/AHRS.h b/services/ins/bmi088/AHRS.h
deleted file mode 100644
index 3ad6a343cad64bb26768eb9cad182c28ec92400c..0000000000000000000000000000000000000000
--- a/services/ins/bmi088/AHRS.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef AHRS_H
-#define AHRS_H
-
-#include "AHRS_MiddleWare.h"
-
-/**
- * @brief ݼٶȵݣƵݽԪʼ
- * @param[in] ҪʼԪ
- * @param[in] ڳʼļٶȼ,(x,y,z)Ϊ λ m/s2
- * @param[in] ڳʼĴƼ,(x,y,z)Ϊ λ uT
- * @retval ؿ
- */
-extern void AHRS_init(fp32 quat[4], const fp32 accel[3], const fp32 mag[3]);
-
-/**
- * @brief ǵݣٶȵݣƵݽԪ
- * @param[in] ҪµԪ
- * @param[in] ¶ʱʱ䣬̶ʱã1000HzΪ0.001f,
- * @param[in] ڸµ,˳(x,y,z) λ rad
- * @param[in] ڳʼļٶ,˳(x,y,z) λ m/s2
- * @param[in] ڳʼĴ,˳(x,y,z) λ uT
- * @retval 1:³ɹ, 0:ʧ
- */
-extern bool_t AHRS_update(fp32 quat[4], const fp32 timing_time, const fp32 gyro[3], const fp32 accel[3], const fp32 mag[3]);
-
-/**
- * @brief ԪСӦŷƫyaw
- * @param[in] Ԫ飬ΪNULL
- * @retval صƫyaw λ rad
- */
-extern fp32 get_yaw(const fp32 quat[4]);
-
-/**
- * @brief ԪСӦŷǸ pitch
- * @param[in] Ԫ飬ΪNULL
- * @retval صĸ pitch λ rad
- */
-extern fp32 get_pitch(const fp32 quat[4]);
-/**
- * @brief ԪСӦŷǺ roll
- * @param[in] Ԫ飬ΪNULL
- * @retval صĺ roll λ rad
- */
-extern fp32 get_roll(const fp32 quat[4]);
-
-/**
- * @brief ԪСӦŷyawpitchroll
- * @param[in] Ԫ飬ΪNULL
- * @param[in] صƫyaw λ rad
- * @param[in] صĸpitch λ rad
- * @param[in] صĺroll λ rad
- */
-extern void get_angle(const fp32 quat[4], fp32 *yaw, fp32 *pitch, fp32 *roll);
-/**
- * @brief صǰٶ
- * @param[in]
- * @retval ٶ λ m/s2
- */
-extern fp32 get_carrier_gravity(void);
-
-#endif
diff --git a/services/ins/bmi088/AHRS_middleware.c b/services/ins/bmi088/AHRS_middleware.c
index 9e370e8e1811bf1184b221b661ac57fbbdda7120..413acd2677b3dd16d20ab8418531d77033b9d653 100644
--- a/services/ins/bmi088/AHRS_middleware.c
+++ b/services/ins/bmi088/AHRS_middleware.c
@@ -1,11 +1,11 @@
/**
****************************(C) COPYRIGHT 2019 DJI****************************
* @file AHRS_MiddleWare.c/h
- * @brief ̬м㣬Ϊ̬ṩغ
+ * @brief 姿态解算中间层,为姿态解算提供相关函数
* @note
* @history
* Version Date Author Modification
- * V1.0.0 Dec-26-2018 RM 1.
+ * V1.0.0 Dec-26-2018 RM 1. 完成
*
@verbatim
==============================================================================
@@ -17,13 +17,14 @@
#include "AHRS_MiddleWare.h"
#include "AHRS.h"
+#include "stm32f4xx.h"
#include "arm_math.h"
#include "main.h"
/**
- * @brief ڻȡǰ߶
+ * @brief 用于获取当前高度
* @author RM
- * @param[in] ߶ȵָ룬fp32
- * @retval ؿ
+ * @param[in] 高度的指针,fp32
+ * @retval 返回空
*/
void AHRS_get_height(fp32* high)
@@ -35,10 +36,10 @@ void AHRS_get_height(fp32* high)
}
/**
- * @brief ڻȡǰγ
+ * @brief 用于获取当前纬度
* @author RM
- * @param[in] γȵָ룬fp32
- * @retval ؿ
+ * @param[in] 纬度的指针,fp32
+ * @retval 返回空
*/
void AHRS_get_latitude(fp32* latitude)
@@ -50,10 +51,10 @@ void AHRS_get_latitude(fp32* latitude)
}
/**
- * @brief ٿ
+ * @brief 快速开方函数,
* @author RM
- * @param[in] Ҫĸfp32
- * @retval 1/sqrt ĵ
+ * @param[in] 输入需要开方的浮点数,fp32
+ * @retval 返回1/sqrt 开方后的倒数
*/
fp32 AHRS_invSqrt(fp32 num)
@@ -71,10 +72,10 @@ fp32 AHRS_invSqrt(fp32 num)
}
/**
- * @brief sin
+ * @brief sin函数
* @author RM
- * @param[in] Ƕ λ rad
- * @retval ضӦǶȵsinֵ
+ * @param[in] 角度 单位 rad
+ * @retval 返回对应角度的sin值
*/
fp32 AHRS_sinf(fp32 angle)
@@ -82,10 +83,10 @@ fp32 AHRS_sinf(fp32 angle)
return sin(angle);
}
/**
- * @brief cos
+ * @brief cos函数
* @author RM
- * @param[in] Ƕ λ rad
- * @retval ضӦǶȵcosֵ
+ * @param[in] 角度 单位 rad
+ * @retval 返回对应角度的cos值
*/
fp32 AHRS_cosf(fp32 angle)
@@ -94,10 +95,10 @@ fp32 AHRS_cosf(fp32 angle)
}
/**
- * @brief tan
+ * @brief tan函数
* @author RM
- * @param[in] Ƕ λ rad
- * @retval ضӦǶȵtanֵ
+ * @param[in] 角度 单位 rad
+ * @retval 返回对应角度的tan值
*/
fp32 AHRS_tanf(fp32 angle)
@@ -105,10 +106,10 @@ fp32 AHRS_tanf(fp32 angle)
return tanf(angle);
}
/**
- * @brief 32λķǺ asin
+ * @brief 用于32位浮点数的反三角函数 asin函数
* @author RM
- * @param[in] sinֵ1.0fС-1.0f
- * @retval ؽǶ λ
+ * @param[in] 输入sin值,最大1.0f,最小-1.0f
+ * @retval 返回角度 单位弧度
*/
fp32 AHRS_asinf(fp32 sin)
@@ -118,10 +119,10 @@ fp32 AHRS_asinf(fp32 sin)
}
/**
- * @brief Ǻacos
+ * @brief 反三角函数acos函数
* @author RM
- * @param[in] cosֵ1.0fС-1.0f
- * @retval ضӦĽǶ λ
+ * @param[in] 输入cos值,最大1.0f,最小-1.0f
+ * @retval 返回对应的角度 单位弧度
*/
fp32 AHRS_acosf(fp32 cos)
@@ -131,11 +132,11 @@ fp32 AHRS_acosf(fp32 cos)
}
/**
- * @brief Ǻatan
+ * @brief 反三角函数atan函数
* @author RM
- * @param[in] tanֵеyֵ С
- * @param[in] tanֵеxֵ С
- * @retval ضӦĽǶ λ
+ * @param[in] 输入tan值中的y值 最大正无穷,最小负无穷
+ * @param[in] 输入tan值中的x值 最大正无穷,最小负无穷
+ * @retval 返回对应的角度 单位弧度
*/
fp32 AHRS_atan2f(fp32 y, fp32 x)
diff --git a/services/ins/bmi088/bmi088_driver.c b/services/ins/bmi088/bmi088_driver.c
index fe8c2d97c8a46afee0bbc3a465ea324266ca11e8..824f32415c3161583887e897089de85c892aec91 100644
--- a/services/ins/bmi088/bmi088_driver.c
+++ b/services/ins/bmi088/bmi088_driver.c
@@ -2,21 +2,24 @@
#include "BMI088reg.h"
#include "softbus.h"
#include "cmsis_os.h"
+#include "spi.h"
+#include "stm32f4xx_hal_spi.h"
+#include
-#define spiWriteAddr(addr) ((addr)&0x7f)
-#define spiReadAddr(addr) ((addr)|0x80)
+#define spiWriteAddr(addr) ((addr) & (~0x80))
+#define spiReadAddr(addr) ((addr) | 0x80)
#define BMI088_ACCEL_SEN BMI088_ACCEL_6G_SEN;
#define BMI088_GYRO_SEN BMI088_GYRO_2000_SEN;
-//ٶȼơλ(ֻд2ֽĿǰbug3ֽھûˣĿǰûҵԭҴ3ֽ)
+//加速度计、陀螺仪软复位命令(只写2个字节目前测出bug,但传3个字节就没问题了,目前没找到原因暂且传3个字节)
uint8_t accSoftResetCmd[] = {spiWriteAddr(BMI088_ACC_SOFTRESET), BMI088_ACC_SOFTRESET_VALUE, 0};
uint8_t gyroSoftResetCmd[] = {spiWriteAddr(BMI088_ACC_SOFTRESET), BMI088_ACC_SOFTRESET_VALUE, 0};
-//ٶȼơǶid
+//加速度计、陀螺仪读id命令
uint8_t accIdCmd[] = {spiReadAddr(BMI088_ACC_CHIP_ID), 0, 0};
uint8_t gyroIdCmd[] = {spiReadAddr(BMI088_GYRO_CHIP_ID), 0};
-//ٶȼ
+//加速度计配置命令
uint8_t accPwrCtrlCmd[]={spiWriteAddr(BMI088_ACC_PWR_CTRL), BMI088_ACC_ENABLE_ACC_ON};
uint8_t accPwrConfCmd[]={spiWriteAddr(BMI088_ACC_PWR_CONF), BMI088_ACC_PWR_ACTIVE_MODE};
uint8_t accConfCmd[]={spiWriteAddr(BMI088_ACC_CONF), BMI088_ACC_NORMAL| BMI088_ACC_800_HZ | BMI088_ACC_CONF_MUST_Set};
@@ -24,7 +27,7 @@ uint8_t accRangeCmd[]={spiWriteAddr(BMI088_ACC_RANGE), BMI088_ACC_RANGE_6G};
uint8_t accIOConfCmd[]={spiWriteAddr(BMI088_INT1_IO_CTRL), BMI088_ACC_INT1_IO_ENABLE | BMI088_ACC_INT1_GPIO_PP | BMI088_ACC_INT1_GPIO_LOW};
uint8_t accIOMapCmd[]={spiWriteAddr(BMI088_INT_MAP_DATA), BMI088_ACC_INT1_DRDY_INTERRUPT};
-//
+//陀螺仪配置命令
uint8_t gyroRangeCmd[]={spiWriteAddr(BMI088_GYRO_RANGE), BMI088_GYRO_2000};
uint8_t gyroBandWidthCmd[]={spiWriteAddr(BMI088_GYRO_BANDWIDTH), BMI088_GYRO_1000_116_HZ | BMI088_GYRO_BANDWIDTH_MUST_Set};
uint8_t gyroPwrConfCmd[]={spiWriteAddr(BMI088_GYRO_LPM1), BMI088_GYRO_NORMAL_MODE};
@@ -32,7 +35,7 @@ uint8_t gyroPwrCtrlCmd[]={spiWriteAddr(BMI088_GYRO_CTRL), BMI088_DRDY_ON};
uint8_t gyroIOConfCmd[]={spiWriteAddr(BMI088_GYRO_INT3_INT4_IO_CONF), BMI088_GYRO_INT3_GPIO_PP | BMI088_GYRO_INT3_GPIO_LOW};
uint8_t gyroIOMapCmd[]={spiWriteAddr(BMI088_GYRO_INT3_INT4_IO_MAP), BMI088_GYRO_DRDY_IO_INT3};
-//ٶȼǻȡ
+//加速度计陀螺仪获取数据命令
uint8_t accGetDataCmd[8]={spiReadAddr(BMI088_ACCEL_XOUT_L)};
uint8_t gyroGetDataCmd[7]={spiReadAddr(BMI088_GYRO_X_L)};
uint8_t tmpGetDataCmd[4]={spiReadAddr(BMI088_TEMP_M)};
@@ -41,26 +44,26 @@ uint8_t tmpGetDataCmd[4]={spiReadAddr(BMI088_TEMP_M)};
bool BMI088_AccelInit(uint8_t spiX)
{
uint8_t accId[3]= {0};
- Bus_RemoteCall("/spi/block", {{"spi-x", &spiX},
- {"tx-data", accIdCmd},
- {"len", IM_PTR(uint16_t, 3)},
- {"timeout", IM_PTR(uint32_t, 1000)},
- {"cs-name", "acc"},
- {"is-block", IM_PTR(bool, true)}}); //ٶȼid
+ Bus_RemoteCall("/spi/block", {{"spi-x", {&spiX}},
+ {"tx-data", {accIdCmd}},
+ {"len", {.U32 = 3}},
+ {"timeout", {.U32 = 1000}},
+ {"cs-name", {"acc"}},
+ {"is-block", {.Bool = true}}}); //读加速度计id
osDelay(1);
Bus_RemoteCall("/spi/block", {{"spi-x", &spiX},
{"tx-data", accPwrConfCmd},
{"len", IM_PTR(uint16_t, 2)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "acc"},
- {"is-block", IM_PTR(bool, true)}}); //ýģʽ
+ {"is-block", IM_PTR(bool, true)}}); //配置进入活动模式
osDelay(1);
Bus_RemoteCall("/spi/block", {{"spi-x", &spiX},
{"tx-data", accPwrCtrlCmd},
{"len", IM_PTR(uint16_t, 2)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "acc"},
- {"is-block", IM_PTR(bool, true)}}); //ٶȼƵԴ
+ {"is-block", IM_PTR(bool, true)}}); //打开加速度计电源
osDelay(1);
Bus_RemoteCall("/spi/block", {{"spi-x", &spiX},
{"tx-data", accIdCmd},
@@ -68,17 +71,17 @@ bool BMI088_AccelInit(uint8_t spiX)
{"len", IM_PTR(uint16_t, 3)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "acc"},
- {"is-block", IM_PTR(bool, true)}}); //ٶȼid
+ {"is-block", IM_PTR(bool, true)}}); //读加速度计id
osDelay(1);
- if(accId[2] != BMI088_ACC_CHIP_ID_VALUE) //ٶȼid
+ if(accId[2] != BMI088_ACC_CHIP_ID_VALUE) //如果加速度计id不对
{
Bus_RemoteCall("/spi/block", {{"spi-x", &spiX},
{"tx-data", accSoftResetCmd},
{"len", IM_PTR(uint16_t, 3)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "acc"},
- {"is-block", IM_PTR(bool, true)}}); //λ
+ {"is-block", IM_PTR(bool, true)}}); //软复位
osDelay(50);
return true;
}
@@ -88,28 +91,28 @@ bool BMI088_AccelInit(uint8_t spiX)
{"len", IM_PTR(uint16_t, 2)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "acc"},
- {"is-block", IM_PTR(bool, true)}}); //üٶȼ800Hz, Normalģʽ
+ {"is-block", IM_PTR(bool, true)}}); //配置加速度计输出速率800Hz, Normal输出模式
osDelay(1);
Bus_RemoteCall("/spi/block", {{"spi-x", &spiX},
{"tx-data", accRangeCmd},
{"len", IM_PTR(uint16_t, 2)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "acc"},
- {"is-block", IM_PTR(bool, true)}}); //üٶȼ+-3g
+ {"is-block", IM_PTR(bool, true)}}); //配置加速度计量程+-3g
osDelay(1);
Bus_RemoteCall("/spi/block", {{"spi-x", &spiX},
{"tx-data", accPwrConfCmd},
{"len", IM_PTR(uint16_t, 2)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "acc"},
- {"is-block", IM_PTR(bool, true)}}); //ýģʽ
+ {"is-block", IM_PTR(bool, true)}}); //配置进入正常模式
osDelay(1);
Bus_RemoteCall("/spi/block", {{"spi-x", &spiX},
{"tx-data", accPwrCtrlCmd},
{"len", IM_PTR(uint16_t, 2)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "acc"},
- {"is-block", IM_PTR(bool, true)}}); //ٶȼƵԴ
+ {"is-block", IM_PTR(bool, true)}}); //打开加速度计电源
osDelay(1);
Bus_RemoteCall("/spi/block", {{"spi-x", &spiX},
{"tx-data", accIOConfCmd},
@@ -136,7 +139,7 @@ bool BMI088_GyroInit(uint8_t spiX)
{"len", IM_PTR(uint16_t, 2)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "gyro"},
- {"is-block", IM_PTR(bool, true)}}); //id
+ {"is-block", IM_PTR(bool, true)}}); //读陀螺仪id
osDelay(1);
Bus_RemoteCall("/spi/block", {{"spi-x", &spiX},
{"tx-data", gyroIdCmd},
@@ -144,17 +147,17 @@ bool BMI088_GyroInit(uint8_t spiX)
{"len", IM_PTR(uint16_t, 2)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "gyro"},
- {"is-block", IM_PTR(bool, true)}}); //id
+ {"is-block", IM_PTR(bool, true)}}); //读陀螺仪id
osDelay(1);
- if(gyroId[1] != BMI088_GYRO_CHIP_ID_VALUE) //id
+ if(gyroId[1] != BMI088_GYRO_CHIP_ID_VALUE) //如果陀螺仪id不对
{
Bus_RemoteCall("/spi/block", {{"spi-x", &spiX},
{"tx-data", gyroSoftResetCmd},
{"len", IM_PTR(uint16_t, 3)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "gyro"},
- {"is-block", IM_PTR(bool, true)}}); //λ
+ {"is-block", IM_PTR(bool, true)}}); //软复位
osDelay(50);
return true;
}
@@ -164,21 +167,21 @@ bool BMI088_GyroInit(uint8_t spiX)
{"len", IM_PTR(uint16_t, 2)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "gyro"},
- {"is-block", IM_PTR(bool, true)}}); //1000Hz, 116Hz
+ {"is-block", IM_PTR(bool, true)}}); //配置陀螺仪输出速率1000Hz, 带宽116Hz
osDelay(1);
Bus_RemoteCall("/spi/block", {{"spi-x", &spiX},
{"tx-data", gyroRangeCmd},
{"len", IM_PTR(uint16_t, 2)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "gyro"},
- {"is-block", IM_PTR(bool, true)}}); //Χ+-2000/s
+ {"is-block", IM_PTR(bool, true)}}); //配置陀螺仪输出范围+-2000°/s
osDelay(1);
Bus_RemoteCall("/spi/block", {{"spi-x", &spiX},
{"tx-data", gyroPwrConfCmd},
{"len", IM_PTR(uint16_t, 2)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "gyro"},
- {"is-block", IM_PTR(bool, true)}}); //ýģʽ
+ {"is-block", IM_PTR(bool, true)}}); //配置进入活动模式
osDelay(1);
Bus_RemoteCall("/spi/block", {{"spi-x", &spiX},
{"tx-data", gyroIOConfCmd},
@@ -208,7 +211,7 @@ void BMI088_ReadData(uint8_t spiX, float gyro[3], float accel[3], float *tempera
{"len", IM_PTR(uint16_t, 8)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "acc"},
- {"is-block", IM_PTR(bool, true)}}); //ȡٶȼ
+ {"is-block", IM_PTR(bool, true)}}); //获取加速度计数据
temp = (int16_t)((buf[3]) << 8) | buf[2];
accel[0] = temp * BMI088_ACCEL_SEN;
temp = (int16_t)((buf[5]) << 8) | buf[4];
@@ -222,7 +225,7 @@ void BMI088_ReadData(uint8_t spiX, float gyro[3], float accel[3], float *tempera
{"len", IM_PTR(uint16_t, 7)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "gyro"},
- {"is-block", IM_PTR(bool, true)}}); //ȡ
+ {"is-block", IM_PTR(bool, true)}}); //获取陀螺仪数据
// if(buf[0] == BMI088_GYRO_CHIP_ID_VALUE)
// {
temp = (int16_t)((buf[2]) << 8) | buf[1];
@@ -239,7 +242,7 @@ void BMI088_ReadData(uint8_t spiX, float gyro[3], float accel[3], float *tempera
{"len", IM_PTR(uint16_t, 4)},
{"timeout", IM_PTR(uint32_t, 1000)},
{"cs-name", "acc"},
- {"is-block", IM_PTR(bool, true)}}); //ȡ¶
+ {"is-block", IM_PTR(bool, true)}}); //获取温度数据
temp = (int16_t)((buf[2] << 3) | (buf[3] >> 5));
if (temp > 1023)
diff --git a/services/ins/ins.c b/services/ins/ins.c
index c4d49f3b83c54708b904e8982392aa55a8e3bbd3..ef8f14a4ea29220ca885d3b4c70efaefe9dbef64 100644
--- a/services/ins/ins.c
+++ b/services/ins/ins.c
@@ -5,6 +5,7 @@
#include "AHRS.h"
#include "pid.h"
#include "filter.h"
+#include
typedef struct
{
@@ -26,7 +27,7 @@ typedef struct
PID tmpPID;
Filter *filter;
- uint16_t taskInterval; //ִм
+ uint16_t taskInterval; //任务执行间隔
char* eulerAngleName;
}INS;
@@ -42,7 +43,7 @@ void INS_TaskCallback(void const * argument)
osDelay(50);
INS_Init(&ins, (ConfItem*)argument);
AHRS_init(ins.imu.quat,ins.imu.accel,ins.imu.mag);
- //Уƫ
+ //校准零偏
// for(int i=0;i<10000;i++)
// {
// BMI088_ReadData(ins.spiX, ins.imu.gyro,ins.imu.accel, &ins.imu.tmp);
@@ -55,7 +56,7 @@ void INS_TaskCallback(void const * argument)
// ins.imu.gyroOffset[1] = ins.imu.gyroOffset[1]/10000.0f;
// ins.imu.gyroOffset[2] = ins.imu.gyroOffset[2]/10000.0f;
- ins.imu.gyroOffset[0] = -0.000767869; //10Уȡֵ
+ ins.imu.gyroOffset[0] = -0.000767869; //10次校准取均值
ins.imu.gyroOffset[1] = 0.000771033;
ins.imu.gyroOffset[2] = 0.001439746;
@@ -66,16 +67,16 @@ void INS_TaskCallback(void const * argument)
for(uint8_t i=0;i<3;i++)
ins.imu.gyro[i] -= ins.imu.gyroOffset[i];
- //˲
+ //滤波
// for(uint8_t i=0;i<3;i++)
// ins.imu.accel[i] = ins.filter->cala(ins.filter , ins.imu.accel[i]);
- //ں
+ //数据融合
AHRS_update(ins.imu.quat,ins.taskInterval/1000.0f,ins.imu.gyro,ins.imu.accel,ins.imu.mag);
get_angle(ins.imu.quat,&ins.yaw,&ins.pitch,&ins.roll);
ins.yaw = ins.yaw/PI*180;
ins.pitch = ins.pitch/PI*180;
ins.roll = ins.roll/PI*180;
- //
+ //发布数据
Bus_BroadcastSend(ins.eulerAngleName, {{"yaw",&ins.yaw}, {"pitch",&ins.pitch}, {"roll",&ins.roll}});
osDelay(ins.taskInterval);
}
@@ -96,7 +97,7 @@ void INS_Init(INS* ins, ConfItem* dict)
char* temp = Conf_GetPtr(dict, "name", char);
temp = temp ? temp : "ins";
uint8_t len = strlen(temp);
- ins->eulerAngleName = pvPortMalloc(len + 13+ 1); //13Ϊ"/ /euler-angle"ijȣ1Ϊ'\0'ij
+ ins->eulerAngleName = pvPortMalloc(len + 13+ 1); //13为"/ /euler-angle"的长度,1为'\0'的长度
sprintf(ins->eulerAngleName, "/%s/euler-angle", temp);
while(BMI088_AccelInit(ins->spiX) || BMI088_GyroInit(ins->spiX))
@@ -106,16 +107,18 @@ void INS_Init(INS* ins, ConfItem* dict)
BMI088_ReadData(ins->spiX, ins->imu.gyro,ins->imu.accel, &ins->imu.tmp);
- //ʱ¶pid
+ //创建定时器进行温度pid控制
osTimerDef(tmp, INS_TmpPIDTimerCallback);
osTimerStart(osTimerCreate(osTimer(tmp), osTimerPeriodic, ins), 2);
}
-//ʱص
+//软件定时器回调函数
void INS_TmpPIDTimerCallback(void const *argument)
{
INS* ins = pvTimerGetTimerID((TimerHandle_t)argument);
PID_SingleCalc(&ins->tmpPID, ins->targetTmp, ins->imu.tmp);
ins->tmpPID.output = ins->tmpPID.output > 0? ins->tmpPID.output : 0;
- Bus_RemoteCall("/tim/pwm/set-duty", {{"tim-x", &ins->timX}, {"channel-x", &ins->channelX}, {"duty", &ins->tmpPID.output}});
+ Bus_RemoteCall("/tim/pwm/set-duty", {{"tim-x", {.U8 = ins->timX}},
+ {"channel-x", {.U8 = ins->channelX}},
+ {"duty", {.F32 = ins->tmpPID.output}}});
}
diff --git a/services/judgement/judge.c b/services/judgement/judge.c
index 3c52e2d508658ee63272bb410c54c1d13392d29b..cf4605dcff5b69aa7095c9587e74031bc931621b 100644
--- a/services/judgement/judge.c
+++ b/services/judgement/judge.c
@@ -3,38 +3,39 @@
#include "softbus.h"
#include "cmsis_os.h"
#include "my_queue.h"
+#include
typedef struct _Judge
{
- JudgeRecInfo judgeRecInfo; //Ӳϵͳյ
- bool dataTF; //Ƿ,
- Queue txQueue; //Ͷ
+ JudgeRecInfo judgeRecInfo; //从裁判系统接收到的数据
+ bool dataTF; //裁判数据是否可用,辅助函数调用
+ Queue txQueue; //发送队列
JudgeTxFrame *queueBuf;
uint8_t uartX;
- uint16_t taskInterval; //ִм
+ uint16_t taskInterval; //任务执行间隔
}Judge;
void Judge_Init(Judge *judge,ConfItem* dict);
void Judge_Recv_SoftBusCallback(const char* topic, SoftBusFrame* frame, void* bindData);
-bool Judge_UiDrawTextCallback(const char* topic, SoftBusFrame* frame, void* bindData); //ı
-bool Judge_UiDrawLineCallback(const char* topic, SoftBusFrame* frame, void* bindData); //ֱ
-bool Judge_UiDrawRectCallback(const char* topic, SoftBusFrame* frame, void* bindData); //
-bool Judge_UiDrawCircleCallback(const char* topic, SoftBusFrame* frame, void* bindData); //Բ
-bool Judge_UiDrawOvalCallback(const char* topic, SoftBusFrame* frame, void* bindData); //Բ
-bool Judge_UiDrawArcCallback(const char* topic, SoftBusFrame* frame, void* bindData);//Բ
+bool Judge_UiDrawTextCallback(const char* topic, SoftBusFrame* frame, void* bindData); //画文本
+bool Judge_UiDrawLineCallback(const char* topic, SoftBusFrame* frame, void* bindData); //画直线
+bool Judge_UiDrawRectCallback(const char* topic, SoftBusFrame* frame, void* bindData); //画矩形
+bool Judge_UiDrawCircleCallback(const char* topic, SoftBusFrame* frame, void* bindData); //画圆
+bool Judge_UiDrawOvalCallback(const char* topic, SoftBusFrame* frame, void* bindData); //画椭圆
+bool Judge_UiDrawArcCallback(const char* topic, SoftBusFrame* frame, void* bindData);//画圆弧
bool Judge_UiDrawFloatCallback(const char* topic, SoftBusFrame* frame, void* bindData);
bool Judge_UiDrawIntCallback(const char* topic, SoftBusFrame* frame, void* bindData);
bool JUDGE_Read_Data(Judge *judge,uint8_t *ReadFromUsart);
void Judge_publishData(Judge * judge);
void Judge_TimerCallback(void const *argument);
-Judge judge={0}; //ڴ ʺΪľֲ
+Judge judge={0}; //大内存 不适合作为任务的局部变量
JudgeTxFrame debug;
void Judge_TaskCallback(void const * argument)
{
- //ٽ
+ //进入临界区
portENTER_CRITICAL();
Judge_Init(&judge, (ConfItem*)argument);
portEXIT_CRITICAL();
@@ -43,27 +44,27 @@ void Judge_TaskCallback(void const * argument)
{
if(!Queue_IsEmpty(&judge.txQueue))
{
- //ȡͷϢ
+ //取队头的消息发送
JudgeTxFrame *txframe=(JudgeTxFrame*)Queue_Dequeue(&judge.txQueue);
- //ui
- Bus_RemoteCall("/uart/trans/dma",{{"uart-x",&judge.uartX},
- {"data",(uint8_t *)txframe->data},
- {"trans-size",&txframe->frameLength}});
+ //发送ui
+ Bus_RemoteCall("/uart/trans/dma",{{"uart-x", {.U8 = judge.uartX}},
+ {"data", {txframe->data}},
+ {"trans-size", {.U16 = txframe->frameLength}}});
}
osDelay(judge.taskInterval);
}
}
-//ʼ
+//初始化
void Judge_Init(Judge* judge,ConfItem* dict)
{
- //ʼͶ
- uint16_t maxTxQueueLen = Conf_GetValue(dict, "max-tx-queue-length", uint16_t, 20); //Ͷ
+ //初始化发送队列
+ uint16_t maxTxQueueLen = Conf_GetValue(dict, "max-tx-queue-length", uint16_t, 20); //最大发送队列
judge->queueBuf=(JudgeTxFrame*)pvPortMalloc(maxTxQueueLen*sizeof(JudgeTxFrame));
Queue_Init(&judge->txQueue,maxTxQueueLen);
Queue_AttachBuffer(&judge->txQueue,judge->queueBuf,sizeof(JudgeTxFrame));
- judge->taskInterval = Conf_GetValue(dict, "task-interval", uint16_t, 150); //ִм
+ judge->taskInterval = Conf_GetValue(dict, "task-interval", uint16_t, 150); //任务执行间隔
char name[] = "/uart_/recv";
judge->uartX = Conf_GetValue(dict, "uart-x", uint8_t, 0);
name[5] = judge->uartX + '0';
@@ -77,16 +78,16 @@ void Judge_Init(Judge* judge,ConfItem* dict)
Bus_RegisterRemoteFunc(judge, Judge_UiDrawArcCallback, "/judge/send/ui/arc");
Bus_RegisterRemoteFunc(judge, Judge_UiDrawFloatCallback, "/judge/send/ui/float");
Bus_RegisterRemoteFunc(judge, Judge_UiDrawIntCallback, "/judge/send/ui/int");
- //ʱ ʱ㲥յ
+ //开启软件定时器 定时广播接收到的数据
osTimerDef(judge, Judge_TimerCallback);
osTimerStart(osTimerCreate(osTimer(judge), osTimerPeriodic, judge), 20);
}
-//ϵͳʱص
+//系统定时器回调
void Judge_TimerCallback(void const *argument)
{
Judge *judge =(Judge*)argument;
- Judge_publishData(judge); //㲥յ
+ Judge_publishData(judge); //广播接收到的数据
}
@@ -100,9 +101,9 @@ void Judge_Recv_SoftBusCallback(const char* topic, SoftBusFrame* frame, void* bi
/*
-uiͼnameڲУΪͻ˵Ψһֻ3ַ
-㲥uiƵӦС5hzӦݸʱ㲥
-Ӧͼβ
+ui的图形名(name)在操作中,作为客户端的唯一索引,有且只有3个字符
+各任务广播ui的频率应小于5hz,应仅在数据更新时广播
+立即数对应的图形操作
typedef enum _GraphOperation
{
Operation_Null=0,
@@ -110,12 +111,12 @@ typedef enum _GraphOperation
Operation_Change,
Operation_Delete
}GraphOperation;
-***UIʱOperation_AddOperation_ChangeOperation_Delete
+***添加UI时必须先Operation_Add,才能Operation_Change、Operation_Delete
-Ӧͼɫ
+立即数对应的图形颜色
typedef enum _GraphColor
{
- Color_Self=0,//ɫ
+ Color_Self=0,//己方主色
Color_Yellow,
Color_Green,
Color_Orange,
@@ -127,10 +128,10 @@ typedef enum _GraphColor
}GraphColor;
*/
-bool Judge_UiDrawTextCallback(const char* topic, SoftBusFrame* frame, void* bindData) //ı
+bool Judge_UiDrawTextCallback(const char* topic, SoftBusFrame* frame, void* bindData) //画文本
{
Judge *judge = (Judge*)bindData;
- // ı ɫ ͼ С ʽ
+ // 名字 文本 颜色 宽度 图层 坐标 字体大小 长度 操作方式
if(!Bus_CheckMapKeys(frame,{"name","text","color","width","layer","start-x","start-y","size","len","opera"}))
return false;
graphic_data_struct_t text;
@@ -153,10 +154,10 @@ bool Judge_UiDrawTextCallback(const char* topic, SoftBusFrame* frame, void* bind
return true;
}
-bool Judge_UiDrawLineCallback(const char* topic, SoftBusFrame* frame, void* bindData) //ֱ
+bool Judge_UiDrawLineCallback(const char* topic, SoftBusFrame* frame, void* bindData) //画直线
{
Judge *judge = (Judge*)bindData;
- // ɫ ͼ ʼ ʽ
+ // 名字 颜色 宽度 图层 开始坐标 结束坐标 操作方式
if(!Bus_CheckMapKeys(frame,{"name","color","width","layer","start-x","start-y","end-x","end-y","opera"}))
return false;
graphic_data_struct_t line;
@@ -170,17 +171,17 @@ bool Judge_UiDrawLineCallback(const char* topic, SoftBusFrame* frame, void* bind
line.start_y = *(int16_t*)Bus_GetMapValue(frame,"start-y");
line.end_x = *(int16_t*)Bus_GetMapValue(frame,"end-x");
line.end_y = *(int16_t*)Bus_GetMapValue(frame,"end-y");
- JudgeTxFrame txframe = JUDGE_PackGraphData(judge->judgeRecInfo.GameRobotStat.robot_id, //ID
- 0x100+judge->judgeRecInfo.GameRobotStat.robot_id, //IDͻˣ
+ JudgeTxFrame txframe = JUDGE_PackGraphData(judge->judgeRecInfo.GameRobotStat.robot_id, //发送者ID
+ 0x100+judge->judgeRecInfo.GameRobotStat.robot_id, //接收者ID(客户端)
&line);
Queue_Enqueue(&judge->txQueue,&txframe);
return true;
}
-bool Judge_UiDrawRectCallback(const char* topic, SoftBusFrame* frame, void* bindData) //
+bool Judge_UiDrawRectCallback(const char* topic, SoftBusFrame* frame, void* bindData) //画矩形
{
Judge *judge = (Judge*)bindData;
- // ɫ ͼ ʼ Խ ʽ
+ // 名字 颜色 宽度 图层 开始坐标 对角坐标 操作方式
if(!Bus_CheckMapKeys(frame,{"name","color","width","layer","start-x","start-y","end-x","end-y","opera"}))
return false;
graphic_data_struct_t rect;
@@ -194,17 +195,17 @@ bool Judge_UiDrawRectCallback(const char* topic, SoftBusFrame* frame, void* bind
rect.start_y=*(int16_t*)Bus_GetMapValue(frame,"start-y");
rect.end_x=*(int16_t*)Bus_GetMapValue(frame,"end-x");
rect.end_y=*(int16_t*)Bus_GetMapValue(frame,"end-y");
- JudgeTxFrame txframe = JUDGE_PackGraphData(judge->judgeRecInfo.GameRobotStat.robot_id,//ID
- 0x100+judge->judgeRecInfo.GameRobotStat.robot_id,//IDͻˣ
+ JudgeTxFrame txframe = JUDGE_PackGraphData(judge->judgeRecInfo.GameRobotStat.robot_id,//发送者ID
+ 0x100+judge->judgeRecInfo.GameRobotStat.robot_id,//接收者ID(客户端)
&rect);
Queue_Enqueue(&judge->txQueue,&txframe);
return true;
}
-bool Judge_UiDrawCircleCallback(const char* topic, SoftBusFrame* frame, void* bindData) //Բ
+bool Judge_UiDrawCircleCallback(const char* topic, SoftBusFrame* frame, void* bindData) //画圆
{
Judge *judge = (Judge*)bindData;
- // ɫ ͼ 뾶 ʽ
+ // 名字 颜色 宽度 图层 中心坐标 半径 操作方式
if(!Bus_CheckMapKeys(frame,{"name","color","width","layer","cent-x","cent-y","radius","opera"}))
return false;
graphic_data_struct_t circle;
@@ -217,17 +218,17 @@ bool Judge_UiDrawCircleCallback(const char* topic, SoftBusFrame* frame, void* bi
circle.start_x=*(int16_t*)Bus_GetMapValue(frame,"cent-x");
circle.start_y=*(int16_t*)Bus_GetMapValue(frame,"cent-y");
circle.radius=*(uint16_t*)Bus_GetMapValue(frame,"radius");
- JudgeTxFrame txframe = JUDGE_PackGraphData(judge->judgeRecInfo.GameRobotStat.robot_id,//ID
- 0x100+judge->judgeRecInfo.GameRobotStat.robot_id,//IDͻˣ
+ JudgeTxFrame txframe = JUDGE_PackGraphData(judge->judgeRecInfo.GameRobotStat.robot_id,//发送者ID
+ 0x100+judge->judgeRecInfo.GameRobotStat.robot_id,//接收者ID(客户端)
&circle);
Queue_Enqueue(&judge->txQueue,&txframe);
return true;
}
-bool Judge_UiDrawOvalCallback(const char* topic, SoftBusFrame* frame, void* bindData) //Բ
+bool Judge_UiDrawOvalCallback(const char* topic, SoftBusFrame* frame, void* bindData) //画椭圆
{
Judge *judge = (Judge*)bindData;
- // ɫ ͼ xy᳤ ʽ
+ // 名字 颜色 宽度 图层 中心坐标 xy半轴长 操作方式
if(!Bus_CheckMapKeys(frame,{"name","color","width","layer","cent-x","cent-y","semiaxis-x","semiaxis-y","opera"}))
return false;
graphic_data_struct_t oval;
@@ -241,17 +242,17 @@ bool Judge_UiDrawOvalCallback(const char* topic, SoftBusFrame* frame, void* bind
oval.start_y=*(int16_t*)Bus_GetMapValue(frame,"cent-y");
oval.end_x=*(int16_t*)Bus_GetMapValue(frame,"semiaxis-x");
oval.end_y=*(int16_t*)Bus_GetMapValue(frame,"semiaxis-y");
- JudgeTxFrame txframe = JUDGE_PackGraphData(judge->judgeRecInfo.GameRobotStat.robot_id,//ID
- 0x100+judge->judgeRecInfo.GameRobotStat.robot_id,//IDͻˣ
+ JudgeTxFrame txframe = JUDGE_PackGraphData(judge->judgeRecInfo.GameRobotStat.robot_id,//发送者ID
+ 0x100+judge->judgeRecInfo.GameRobotStat.robot_id,//接收者ID(客户端)
&oval);
Queue_Enqueue(&judge->txQueue,&txframe);
return true;
}
-bool Judge_UiDrawArcCallback(const char* topic, SoftBusFrame* frame, void* bindData) //Բ
+bool Judge_UiDrawArcCallback(const char* topic, SoftBusFrame* frame, void* bindData) //画圆弧
{
Judge *judge = (Judge*)bindData;
- // ɫ ͼ xy᳤ ʼֹǶ ʽ
+ // 名字 颜色 宽度 图层 中心坐标 xy半轴长 起始、终止角度 操作方式
if(!Bus_CheckMapKeys(frame,{"name","color","width","layer","cent-x","cent-y","semiaxis-x","semiaxis-y","start-angle","end-angle","opera"}))
return false;
graphic_data_struct_t arc;
@@ -267,8 +268,8 @@ bool Judge_UiDrawArcCallback(const char* topic, SoftBusFrame* frame, void* bindD
arc.end_y=*(int16_t*)Bus_GetMapValue(frame,"semiaxis-y");
arc.start_angle=*(int16_t*)Bus_GetMapValue(frame,"start-angle");
arc.end_angle=*(int16_t*)Bus_GetMapValue(frame,"end-angle");
- JudgeTxFrame txframe = JUDGE_PackGraphData(judge->judgeRecInfo.GameRobotStat.robot_id,//ID
- 0x100+judge->judgeRecInfo.GameRobotStat.robot_id,//IDͻˣ
+ JudgeTxFrame txframe = JUDGE_PackGraphData(judge->judgeRecInfo.GameRobotStat.robot_id,//发送者ID
+ 0x100+judge->judgeRecInfo.GameRobotStat.robot_id,//接收者ID(客户端)
&arc);
Queue_Enqueue(&judge->txQueue,&txframe);
return true;
@@ -277,7 +278,7 @@ bool Judge_UiDrawArcCallback(const char* topic, SoftBusFrame* frame, void* bindD
bool Judge_UiDrawFloatCallback(const char* topic, SoftBusFrame* frame, void* bindData)
{
Judge *judge = (Judge*)bindData;
- // ɫ ͼ ֵ С Чλ ʽ
+ // 名字 颜色 宽度 图层 值 坐标 大小 有效位数 操作方式
if(!Bus_CheckMapKeys(frame,{"name","color","width","layer","value","start-x","start-y","size","digit","opera"}))
return false;
graphic_data_struct_t float_num;
@@ -295,8 +296,8 @@ bool Judge_UiDrawFloatCallback(const char* topic, SoftBusFrame* frame, void* bin
float_num.radius=((int32_t)(value*1000))&0x3FF;
float_num.end_x=((int32_t)(value*1000)>>10)&0x7FF;
float_num.end_y=((int32_t)(value*1000)>>21)&0x7FF;
- JudgeTxFrame txframe = JUDGE_PackGraphData(judge->judgeRecInfo.GameRobotStat.robot_id,//ID
- 0x100+judge->judgeRecInfo.GameRobotStat.robot_id,//IDͻˣ
+ JudgeTxFrame txframe = JUDGE_PackGraphData(judge->judgeRecInfo.GameRobotStat.robot_id,//发送者ID
+ 0x100+judge->judgeRecInfo.GameRobotStat.robot_id,//接收者ID(客户端)
&float_num);
Queue_Enqueue(&judge->txQueue,&txframe);
return true;
@@ -305,7 +306,7 @@ bool Judge_UiDrawFloatCallback(const char* topic, SoftBusFrame* frame, void* bin
bool Judge_UiDrawIntCallback(const char* topic, SoftBusFrame* frame, void* bindData)
{
Judge *judge = (Judge*)bindData;
- // ɫ ͼ ֵ С ʽ
+ // 名字 颜色 宽度 图层 值 坐标 大小 操作方式
if(!Bus_CheckMapKeys(frame,{"name","color","width","layer","value","start-x","start-y","size","opera"}))
return false;
graphic_data_struct_t int_num;
@@ -322,33 +323,33 @@ bool Judge_UiDrawIntCallback(const char* topic, SoftBusFrame* frame, void* bindD
int_num.radius= value&0x3FF;
int_num.end_x=( value>>10)&0x7FF;
int_num.end_y=( value>>21)&0x7FF;
- JudgeTxFrame txframe = JUDGE_PackGraphData(judge->judgeRecInfo.GameRobotStat.robot_id,//ID
- 0x100+judge->judgeRecInfo.GameRobotStat.robot_id,//IDͻˣ
+ JudgeTxFrame txframe = JUDGE_PackGraphData(judge->judgeRecInfo.GameRobotStat.robot_id,//发送者ID
+ 0x100+judge->judgeRecInfo.GameRobotStat.robot_id,//接收者ID(客户端)
&int_num);
Queue_Enqueue(&judge->txQueue,&txframe);
return true;
}
-//㲥յ
+//广播接收到的数据
void Judge_publishData(Judge* judge)
{
// if(!judge->dataTF)
// return;
- //
+ //准备带发布的数据
uint8_t robot_id = judge->judgeRecInfo.GameRobotStat.robot_id;
- uint8_t robot_color = robot_id<10?RobotColor_Blue:RobotColor_Red;//ɫ
- uint16_t chassis_power_limit = judge->judgeRecInfo.GameRobotStat.chassis_power_limit; //̹
- bool isShooterPowerOutput = judge->judgeRecInfo.GameRobotStat.mains_power_shooter_output; //ܷǷϵ
- bool isChassisPowerOutput = judge->judgeRecInfo.GameRobotStat.mains_power_chassis_output; //ܵǷϵ
- float chassis_power = judge->judgeRecInfo.PowerHeatData.chassis_power; //̹
- uint16_t chassis_power_buffer = judge->judgeRecInfo.PowerHeatData.chassis_power_buffer; //̻
- float bullet_speed = judge->judgeRecInfo.ShootData.bullet_speed; //䵯ٶ
- //ݷ
- if(robot_id == 1|| robot_id == 101) //Ӣ
+ uint8_t robot_color = robot_id<10?RobotColor_Blue:RobotColor_Red;//机器人颜色
+ uint16_t chassis_power_limit = judge->judgeRecInfo.GameRobotStat.chassis_power_limit; //底盘功率限制
+ bool isShooterPowerOutput = judge->judgeRecInfo.GameRobotStat.mains_power_shooter_output; //电管发射机构是否断电
+ bool isChassisPowerOutput = judge->judgeRecInfo.GameRobotStat.mains_power_chassis_output; //电管底盘是否断电
+ float chassis_power = judge->judgeRecInfo.PowerHeatData.chassis_power; //底盘功率
+ uint16_t chassis_power_buffer = judge->judgeRecInfo.PowerHeatData.chassis_power_buffer; //底盘缓冲
+ float bullet_speed = judge->judgeRecInfo.ShootData.bullet_speed; //发射弹丸速度
+ //数据发布
+ if(robot_id == 1|| robot_id == 101) //英雄
{
- uint16_t shooter_id1_42mm_speed_limit = judge->judgeRecInfo.GameRobotStat.shooter_id1_42mm_speed_limit; //42mm
- uint16_t shooter_id1_42mm_cooling_heat = judge->judgeRecInfo.PowerHeatData.shooter_id1_42mm_cooling_heat; //42mmǹ
- uint16_t bullet_remaining_num_42mm = judge->judgeRecInfo.BulletRemaining.bullet_remaining_num_42mm; //42mmʣ൯
+ uint16_t shooter_id1_42mm_speed_limit = judge->judgeRecInfo.GameRobotStat.shooter_id1_42mm_speed_limit; //42mm弹速上限
+ uint16_t shooter_id1_42mm_cooling_heat = judge->judgeRecInfo.PowerHeatData.shooter_id1_42mm_cooling_heat; //42mm枪口热量
+ uint16_t bullet_remaining_num_42mm = judge->judgeRecInfo.BulletRemaining.bullet_remaining_num_42mm; //42mm剩余弹丸数量
Bus_BroadcastSend("/judge/recv/robot-state",{{"color",&robot_color},
{"42mm-speed-limit",&shooter_id1_42mm_speed_limit},
{"chassis-power-limit",&chassis_power_limit},
@@ -362,12 +363,12 @@ void Judge_publishData(Judge* judge)
Bus_BroadcastSend("/judge/recv/shoot",{{"bullet-speed",&bullet_speed}});
Bus_BroadcastSend("/judge/recv/bullet",{ {"42mm-bullet-remain",&bullet_remaining_num_42mm}});
}
- else //Ӣ۵λ
+ else //非英雄单位
{
- uint16_t shooter_id1_17mm_speed_limit = judge->judgeRecInfo.GameRobotStat.shooter_id1_17mm_speed_limit; //17mm
- uint16_t shooter_id1_17mm_cooling_heat = judge->judgeRecInfo.PowerHeatData.shooter_id1_17mm_cooling_heat; //17mmǹ
- uint16_t bullet_remaining_num_17mm = judge->judgeRecInfo.BulletRemaining.bullet_remaining_num_17mm; //17mmʣ൯
- bool isGimbalPowerOutput = judge->judgeRecInfo.GameRobotStat.mains_power_gimbal_output; //̨Ƿϵ
+ uint16_t shooter_id1_17mm_speed_limit = judge->judgeRecInfo.GameRobotStat.shooter_id1_17mm_speed_limit; //17mm弹速上限
+ uint16_t shooter_id1_17mm_cooling_heat = judge->judgeRecInfo.PowerHeatData.shooter_id1_17mm_cooling_heat; //17mm枪口热量
+ uint16_t bullet_remaining_num_17mm = judge->judgeRecInfo.BulletRemaining.bullet_remaining_num_17mm; //17mm剩余弹丸数量
+ bool isGimbalPowerOutput = judge->judgeRecInfo.GameRobotStat.mains_power_gimbal_output; //电管云台是否断电
Bus_BroadcastSend("/judge/recv/robot-state",{{"color",&robot_color},
{"17mm-speed-limit",&shooter_id1_17mm_speed_limit},
{"chassis-power-limit",&chassis_power_limit},
diff --git a/services/judgement/judge_drive.c b/services/judgement/judge_drive.c
index 762a5cf0171c31d1a372948f4cae92fd7a4225db..71e4209cdfd8b13c96155ff57b8c756e1f0dcf01 100644
--- a/services/judgement/judge_drive.c
+++ b/services/judgement/judge_drive.c
@@ -1,45 +1,45 @@
#include "judge_drive.h"
#include "string.h"
#include "crc_dji.h"
-/**************ϵͳݸ****************/
+/**************裁判系统数据辅助****************/
/**
- * @brief ȡ,жжȡ֤ٶ
- * @param
- * @retval Ƿж
- * @attention ڴж֡ͷCRCУ,дݣظж֡ͷ
+ * @brief 读取裁判数据,中断中读取保证速度
+ * @param 缓存数据
+ * @retval 是否对正误判断做处理
+ * @attention 在此判断帧头和CRC校验,无误再写入数据,不重复判断帧头
*/
bool JUDGE_Read_Data(JudgeRecInfo *judge,uint8_t *ReadFromUsart)
{
- uint16_t judge_length;//ͳһ֡ݳ
+ uint16_t judge_length;//统计一帧数据长度
- int CmdID = 0;//
+ int CmdID = 0;//数据命令码解析
/***------------------*****/
- //ݰκδ
+ //无数据包,则不作任何处理
if (ReadFromUsart == NULL)
{
return false;
}
- //д֡ͷ,жǷʼ洢
+ //写入帧头数据,用于判断是否开始存储裁判数据
memcpy(&judge->FrameHeader, ReadFromUsart, LEN_HEADER);
- //ж֡ͷǷΪ0xA5
+ //判断帧头数据是否为0xA5
if(ReadFromUsart[ SOF ] == JUDGE_FRAME_HEADER)
{
- //֡ͷCRC8У
+ //帧头CRC8校验
if (!Verify_CRC8_Check_Sum( ReadFromUsart, LEN_HEADER ))
return false;
- //ͳһ֡ݳ,CR16У
+ //统计一帧数据长度,用于CR16校验
judge_length = ReadFromUsart[ DATA_LENGTH ] + LEN_HEADER + LEN_CMDID + LEN_TAIL;
- //֡βCRC16У
+ //帧尾CRC16校验
if(!Verify_CRC16_Check_Sum(ReadFromUsart,judge_length))
return false;
CmdID = (ReadFromUsart[6] << 8 | ReadFromUsart[5]);
- //,ݿӦṹ(עݵij)
+ //解析数据命令码,将数据拷贝到相应结构体中(注意拷贝数据的长度)
switch(CmdID)
{
case ID_game_state: //0x0001
@@ -111,18 +111,18 @@ bool JUDGE_Read_Data(JudgeRecInfo *judge,uint8_t *ReadFromUsart)
memcpy(&judge->DartClientCmd, (ReadFromUsart + DATA), LEN_dart_client_cmd);
break;
}
- //ַ֡,ָCRC16һֽ,жǷΪ0xA5,жһݰǷж֡
+ //首地址加帧长度,指向CRC16下一字节,用来判断是否为0xA5,用来判断一个数据包是否有多帧数据
if(*(ReadFromUsart + sizeof(xFrameHeader) + LEN_CMDID + judge->FrameHeader.DataLength + LEN_TAIL) == 0xA5)
{
- //һݰ˶֡,ٴζȡ
+ //如果一个数据包出现了多帧数据,则再次读取
JUDGE_Read_Data(judge,ReadFromUsart + sizeof(xFrameHeader) + LEN_CMDID + judge->FrameHeader.DataLength + LEN_TAIL);
}
- return true;//У˵ݿ
+ return true;//都校验过了则说明数据可用
}
- return false;//֡ͷ
+ return false;//帧头有问题
}
-//ıݣΪı֡ͷУϢγһ֡
+//打包文本数据,为文本数据添加帧头,校验码等信息,形成一个完整的帧
JudgeTxFrame JUDGE_PackTextData(uint8_t sendID,uint8_t receiveID,graphic_data_struct_t *textConf,uint8_t text[30])
{
JudgeTxFrame txFrame;
@@ -130,13 +130,13 @@ JudgeTxFrame JUDGE_PackTextData(uint8_t sendID,uint8_t receiveID,graphic_data_st
textData.txFrameHeader.SOF=0xA5;
textData.txFrameHeader.DataLength=sizeof(ext_student_interactive_header_data_t)+sizeof(ext_client_custom_character_t);
textData.txFrameHeader.Seq=0;
- memcpy(txFrame.data, &textData.txFrameHeader, sizeof(xFrameHeader));//д֡ͷ
- Append_CRC8_Check_Sum(txFrame.data, sizeof(xFrameHeader));//д֡ͷCRC8У
+ memcpy(txFrame.data, &textData.txFrameHeader, sizeof(xFrameHeader));//写入帧头数据
+ Append_CRC8_Check_Sum(txFrame.data, sizeof(xFrameHeader));//写入帧头CRC8校验码
- textData.CmdID=0x301;//֡ID
- textData.dataFrameHeader.data_cmd_id=0x0110;//ݶID
- textData.dataFrameHeader.send_ID = sendID;//ߵID
- textData.dataFrameHeader.receiver_ID = receiveID; //ߵID
+ textData.CmdID=0x301;//数据帧ID
+ textData.dataFrameHeader.data_cmd_id=0x0110;//数据段ID
+ textData.dataFrameHeader.send_ID = sendID;//发送者的ID
+ textData.dataFrameHeader.receiver_ID = receiveID; //接收者的ID
textData.textData.grapic_data_struct=*textConf;
memcpy(textData.textData.data,text,30);
@@ -149,7 +149,7 @@ JudgeTxFrame JUDGE_PackTextData(uint8_t sendID,uint8_t receiveID,graphic_data_st
txFrame.frameLength=sizeof(textData);
return txFrame;
}
-//ͼݣΪͼ֡ͷУϢγһ֡
+//打包图像数据,为图像数据添加帧头,校验码等信息,形成一个完整的帧
JudgeTxFrame JUDGE_PackGraphData(uint8_t sendID,uint8_t receiveID,graphic_data_struct_t *data)
{
JudgeTxFrame txFrame;
@@ -157,13 +157,13 @@ JudgeTxFrame JUDGE_PackGraphData(uint8_t sendID,uint8_t receiveID,graphic_data_s
graphData.txFrameHeader.SOF=0xA5;
graphData.txFrameHeader.DataLength=sizeof(ext_student_interactive_header_data_t)+sizeof(ext_client_custom_graphic_single_t);
graphData.txFrameHeader.Seq=0;
- memcpy(txFrame.data, &graphData.txFrameHeader, sizeof(xFrameHeader));//д֡ͷ
- Append_CRC8_Check_Sum(txFrame.data, sizeof(xFrameHeader));//д֡ͷCRC8У
+ memcpy(txFrame.data, &graphData.txFrameHeader, sizeof(xFrameHeader));//写入帧头数据
+ Append_CRC8_Check_Sum(txFrame.data, sizeof(xFrameHeader));//写入帧头CRC8校验码
- graphData.CmdID=0x301;//֡ID
- graphData.dataFrameHeader.data_cmd_id=0x0101;//ݶID
- graphData.dataFrameHeader.send_ID = sendID;//ߵID
- graphData.dataFrameHeader.receiver_ID = receiveID;//ͻ˵IDֻΪ˶ӦĿͻ
+ graphData.CmdID=0x301;//数据帧ID
+ graphData.dataFrameHeader.data_cmd_id=0x0101;//数据段ID
+ graphData.dataFrameHeader.send_ID = sendID;//发送者的ID
+ graphData.dataFrameHeader.receiver_ID = receiveID;//客户端的ID,只能为发送者机器人对应的客户端
graphData.graphData.grapic_data_struct=*data;
diff --git a/services/judgement/judge_drive.h b/services/judgement/judge_drive.h
index 4679b7e087d3e1ea5c0e53d6ae0efbe49ceca10d..6bdcabd9d8026c77aa88fa233572bbf15b7f2092 100644
--- a/services/judgement/judge_drive.h
+++ b/services/judgement/judge_drive.h
@@ -3,18 +3,19 @@
#include "stdint.h"
#include "stdbool.h"
+#include "config.h"
#define JUDGE_DATA_ERROR 0
#define JUDGE_DATA_CORRECT 1
-#define LEN_HEADER 5 //֡ͷ
-#define LEN_CMDID 2 //볤
-#define LEN_TAIL 2 //֡βCRC16
+#define LEN_HEADER 5 //帧头长
+#define LEN_CMDID 2 //命令码长度
+#define LEN_TAIL 2 //帧尾CRC16
-//ʼֽ,Э̶Ϊ0xA5
+//起始字节,协议固定为0xA5
#define JUDGE_FRAME_HEADER (0xA5)
#define JUDGE_MAX_FRAME_LENGTH 128
-//ɫ
+//机器人颜色
typedef enum
{
RobotColor_Red,
@@ -28,64 +29,64 @@ typedef enum
DATA = 7,
}JudgeFrameOffset;
-//5ֽ֡ͷ,ƫλ
+//5字节帧头,偏移位置
typedef enum
{
- SOF = 0,//ʼλ
- DATA_LENGTH = 1,//֡ݳ,ȡݳ
- SEQ = 3,//
+ SOF = 0,//起始位
+ DATA_LENGTH = 1,//帧内数据长度,根据这个来获取数据长度
+ SEQ = 3,//包序号
CRC8 = 4 //CRC8
}FrameHeaderOffset;
-/***************ID********************/
+/***************命令码ID********************/
/*
- ID: 0x0001 Byte: 11 ״̬ Ƶ 1Hz
- ID: 0x0002 Byte: 1
- ID: 0x0003 Byte: 32 Ѫ 1Hz
- ID: 0x0101 Byte: 4 ¼ ¼ı
- ID: 0x0102 Byte: 4 زվʶ ı
- ID: 0x0104 Byte: 2 оϢ
- ID: 0x0105 Byte: 1 ڷڵʱ
- ID: 0X0201 Byte: 27 ״̬ 10Hz
- ID: 0X0202 Byte: 14 ʵʱ 50Hz
- ID: 0x0203 Byte: 16 λ 10Hz
- ID: 0x0204 Byte: 1 ״̬ı
- ID: 0x0205 Byte: 1 л״̬ 10Hz
- ID: 0x0206 Byte: 1 ˺״̬ ˺
- ID: 0x0207 Byte: 7 ʵʱ ӵ
- ID: 0x0208 Byte: 6 ӵʣ
- ID: 0x0209 Byte: 4 RFID״̬
- ID: 0x020A Byte: 6 ڻ˿ͻָ
- ID: 0x0301 Byte: n ˼佻 ͷ,10Hz
+ ID: 0x0001 Byte: 11 比赛状态数据 发送频率 1Hz
+ ID: 0x0002 Byte: 1 比赛结果数据 比赛结束后发送
+ ID: 0x0003 Byte: 32 比赛机器人血量数据 1Hz发送
+ ID: 0x0101 Byte: 4 场地事件数据 事件改变后发送
+ ID: 0x0102 Byte: 4 场地补给站动作标识数据 动作改变后发送
+ ID: 0x0104 Byte: 2 裁判警告信息
+ ID: 0x0105 Byte: 1 飞镖发射口倒计时
+ ID: 0X0201 Byte: 27 机器人状态数据 10Hz
+ ID: 0X0202 Byte: 14 实时功率热量数据 50Hz
+ ID: 0x0203 Byte: 16 机器人位置数据 10Hz
+ ID: 0x0204 Byte: 1 机器人增益数据 增益状态改变后发送
+ ID: 0x0205 Byte: 1 空中机器人能量状态数据 10Hz
+ ID: 0x0206 Byte: 1 伤害状态数据 伤害发生后发送
+ ID: 0x0207 Byte: 7 实时射击数据 子弹发射后发送
+ ID: 0x0208 Byte: 6 子弹剩余发射数
+ ID: 0x0209 Byte: 4 机器人RFID状态
+ ID: 0x020A Byte: 6 飞镖机器人客户端指令数据
+ ID: 0x0301 Byte: n 机器人间交互数据 发送方触发发送,10Hz
*/
-//ID,жϽյʲô
+//命令码ID,用来判断接收的是什么数据
typedef enum
{
- ID_game_state = 0x0001,//״̬
- ID_game_result = 0x0002,//
- ID_game_robot_HP = 0x0003,//Ѫ
- ID_event_data = 0x0101,//¼
- ID_supply_projectile_action = 0x0102,//زվʶ
- ID_referee_warning = 0x0104,//оϢ
- ID_dart_remaining_time = 0x0105,//ڷڵʱ
- ID_game_robot_state = 0x0201,//״̬
- ID_power_heat_data = 0x0202,//ʵʱ
- ID_game_robot_pos = 0x0203,//λ
- ID_buff_musk = 0x0204,//
- ID_aerial_robot_energy = 0x0205,//л״̬
- ID_robot_hurt = 0x0206,//˺״̬
- ID_shoot_data = 0x0207,//ʵʱ
- ID_bullet_remaining = 0x0208,//ӵʣ
- ID_rfid_status = 0x0209,//RFID״̬
- ID_dart_client_cmd = 0x020A,//ڻ˿ͻָ
+ ID_game_state = 0x0001,//比赛状态数据
+ ID_game_result = 0x0002,//比赛结果数据
+ ID_game_robot_HP = 0x0003,//比赛机器人血量数据
+ ID_event_data = 0x0101,//场地事件数据
+ ID_supply_projectile_action = 0x0102,//场地补给站动作标识数据
+ ID_referee_warning = 0x0104,//裁判警告信息
+ ID_dart_remaining_time = 0x0105,//飞镖发射口倒计时
+ ID_game_robot_state = 0x0201,//机器人状态数据
+ ID_power_heat_data = 0x0202,//实时功率热量数据
+ ID_game_robot_pos = 0x0203,//机器人位置数据
+ ID_buff_musk = 0x0204,//机器人增益数据
+ ID_aerial_robot_energy = 0x0205,//空中机器人能量状态数据
+ ID_robot_hurt = 0x0206,//伤害状态数据
+ ID_shoot_data = 0x0207,//实时射击数据
+ ID_bullet_remaining = 0x0208,//子弹剩余发射数
+ ID_rfid_status = 0x0209,//机器人RFID状态
+ ID_dart_client_cmd = 0x020A,//飞镖机器人客户端指令数据
} CmdID;
-//ݶγ,ݹٷЭ峤
+//命令码数据段长,根据官方协议来定义长度
typedef enum
{
LEN_game_state = 11, //0x0001
@@ -107,8 +108,8 @@ typedef enum
LEN_dart_client_cmd = 6, //0x020A
} JudgeDataLength;
-/* Զ֡ͷ */
-typedef __packed struct
+/* 自定义帧头 */
+typedef struct __packed
{
uint8_t SOF;
uint16_t DataLength;
@@ -116,8 +117,8 @@ typedef __packed struct
uint8_t CRC8;
} xFrameHeader;
-/* ID: 0x0001 Byte: 11 ״̬ */
-typedef __packed struct
+/* ID: 0x0001 Byte: 11 比赛状态数据 */
+typedef struct __packed
{
uint8_t game_type : 4;
uint8_t game_progress : 4;
@@ -125,14 +126,14 @@ typedef __packed struct
uint64_t SyncTimeStamp;
} ext_game_status_t;
-/* ID: 0x0002 Byte: 1 */
-typedef __packed struct
+/* ID: 0x0002 Byte: 1 比赛结果数据 */
+typedef struct __packed
{
uint8_t winner;
} ext_game_result_t;
-/* ID: 0x0003 Byte: 32 Ѫ */
-typedef __packed struct
+/* ID: 0x0003 Byte: 32 比赛机器人血量数据 */
+typedef struct __packed
{
uint16_t red_1_robot_HP;
uint16_t red_2_robot_HP;
@@ -152,14 +153,14 @@ typedef __packed struct
uint16_t blue_base_HP;
} ext_game_robot_HP_t;
-/* ID: 0x0101 Byte: 4 ¼ */
-typedef __packed struct
+/* ID: 0x0101 Byte: 4 场地事件数据 */
+typedef struct __packed
{
uint32_t event_type;
} ext_event_data_t;
-/* ID: 0x0102 Byte: 4 زվʶ */
-typedef __packed struct
+/* ID: 0x0102 Byte: 4 场地补给站动作标识数据 */
+typedef struct __packed
{
uint8_t supply_projectile_id;
uint8_t supply_robot_id;
@@ -167,21 +168,21 @@ typedef __packed struct
uint8_t supply_projectile_num;
} ext_supply_projectile_action_t;
-/* ID: 0x104 Byte: 2 оϢ */
-typedef __packed struct
+/* ID: 0x104 Byte: 2 裁判警告信息 */
+typedef struct __packed
{
uint8_t level;
uint8_t foul_robot_id;
} ext_referee_warning_t;
-/* ID: 0x105 Byte: 1 ڷڵʱ */
-typedef __packed struct
+/* ID: 0x105 Byte: 1 飞镖发射口倒计时 */
+typedef struct __packed
{
uint8_t dart_remaining_time;
} ext_dart_remaining_time_t;
-/* ID: 0X0201 Byte: 27 ״̬ */
-typedef __packed struct
+/* ID: 0X0201 Byte: 27 机器人状态数据 */
+typedef struct __packed
{
uint8_t robot_id;
uint8_t robot_level;
@@ -203,8 +204,8 @@ typedef __packed struct
} ext_game_robot_status_t;
-/* ID: 0X0202 Byte: 16 ʵʱ */
-typedef __packed struct
+/* ID: 0X0202 Byte: 16 实时功率热量数据 */
+typedef struct __packed
{
uint16_t chassis_volt;
uint16_t chassis_current;
@@ -216,8 +217,8 @@ typedef __packed struct
} ext_power_heat_data_t;
-/* ID: 0x0203 Byte: 16 λ */
-typedef __packed struct
+/* ID: 0x0203 Byte: 16 机器人位置数据 */
+typedef struct __packed
{
float x;
float y;
@@ -226,30 +227,30 @@ typedef __packed struct
} ext_game_robot_pos_t;
-/* ID: 0x0204 Byte: 1 */
-typedef __packed struct
+/* ID: 0x0204 Byte: 1 机器人增益数据 */
+typedef struct __packed
{
uint8_t power_rune_buff;
} ext_buff_musk_t;
-/* ID: 0x0205 Byte: 1 л״̬ */
-typedef __packed struct
+/* ID: 0x0205 Byte: 1 空中机器人能量状态数据 */
+typedef struct __packed
{
uint8_t attack_time;
} aerial_robot_energy_t;
-/* ID: 0x0206 Byte: 1 ˺״̬ */
-typedef __packed struct
+/* ID: 0x0206 Byte: 1 伤害状态数据 */
+typedef struct __packed
{
uint8_t armor_id : 4;
uint8_t hurt_type : 4;
} ext_robot_hurt_t;
-/* ID: 0x0207 Byte: 7 ʵʱ */
-typedef __packed struct
+/* ID: 0x0207 Byte: 7 实时射击数据 */
+typedef struct __packed
{
uint8_t bullet_type;
uint8_t shooter_id;
@@ -257,22 +258,22 @@ typedef __packed struct
float bullet_speed;
} ext_shoot_data_t;
-/* ID: 0x0208 Byte: 6 ӵʣ */
-typedef __packed struct
+/* ID: 0x0208 Byte: 6 子弹剩余发射数 */
+typedef struct __packed
{
uint16_t bullet_remaining_num_17mm;
uint16_t bullet_remaining_num_42mm;
uint16_t coin_remaining_num;
} ext_bullet_remaining_t;
-/* ID: 0x0209 Byte: 4 RFID״̬ */
-typedef __packed struct
+/* ID: 0x0209 Byte: 4 机器人RFID状态 */
+typedef struct __packed
{
uint32_t rfid_status;
} ext_rfid_status_t;
-/* ID: 0x020A Byte: 6 ڻ˿ͻָ */
-typedef __packed struct
+/* ID: 0x020A Byte: 6 飞镖机器人客户端指令数据 */
+typedef struct __packed
{
uint8_t dart_launch_opening_status;
uint8_t dart_attack_target;
@@ -282,36 +283,36 @@ typedef __packed struct
/*
- ݣһͳһݶͷṹ
- IDԼߵ ID ݶΣ
- ݵİܹΪ 128 ֽڣ
- ȥ frame_header,cmd_id,frame_tail Լݶͷṹ 6 ֽڣ
- ʶ͵ݶΪ 113
- 0x0301 İƵΪ 10Hz
-
- ID
- 1Ӣ()
- 2()
- 3/4/5()
- 6()
- 7ڱ()
- 11Ӣ()
- 12()
- 13/14/15()
- 16()
- 17ڱ()
- ͻ ID
- 0x0101 ΪӢ۲ֿͻ( )
- 0x0102 ֿ̲ͻ (( )
- 0x0103/0x0104/0x0105ֿͻ()
- 0x0106вֿͻ(()
- 0x0111Ӣ۲ֿͻ()
- 0x0112ֿ̲ͻ()
- 0x0113/0x0114/0x0115ֿͻ˲()
- 0x0116вֿͻ()
+ 交互数据,包括一个统一的数据段头结构,
+ 包含了内容 ID,发送者以及接受者的 ID 和内容数据段,
+ 整个交互数据的包总共长最大为 128 个字节,
+ 减去 frame_header,cmd_id,frame_tail 以及数据段头结构的 6 个字节,
+ 故而发送的内容数据段最大为 113。
+ 整个交互数据 0x0301 的包上行频率为 10Hz。
+
+ 机器人 ID:
+ 1,英雄(红);
+ 2,工程(红);
+ 3/4/5,步兵(红);
+ 6,空中(红);
+ 7,哨兵(红);
+ 11,英雄(蓝);
+ 12,工程(蓝);
+ 13/14/15,步兵(蓝);
+ 16,空中(蓝);
+ 17,哨兵(蓝)。
+ 客户端 ID:
+ 0x0101 为英雄操作手客户端( 红) ;
+ 0x0102 ,工程操作手客户端 ((红 );
+ 0x0103/0x0104/0x0105,步兵操作手客户端(红);
+ 0x0106,空中操作手客户端((红);
+ 0x0111,英雄操作手客户端(蓝);
+ 0x0112,工程操作手客户端(蓝);
+ 0x0113/0x0114/0x0115,操作手客户端步兵(蓝);
+ 0x0116,空中操作手客户端(蓝)。
*/
-/* ݽϢ0x0301 */
-typedef __packed struct
+/* 交互数据接收信息:0x0301 */
+typedef struct __packed
{
uint16_t data_cmd_id;
uint16_t send_ID;
@@ -319,32 +320,32 @@ typedef __packed struct
} ext_student_interactive_header_data_t;
/*
- ѧ˼ͨ cmd_id 0x0301 ID:0x0200~0x02FF
- ˼ͨţ0x0301
- Ƶʣ 10Hz
+ 学生机器人间通信 cmd_id 0x0301,内容 ID:0x0200~0x02FF
+ 交互数据 机器人间通信:0x0301。
+ 发送频率:上限 10Hz
- ֽƫ С ˵ ע
- 0 2 ݵ ID 0x0200~0x02FF
- ID ѡȡ ID ɲԶ
+ 字节偏移量 大小 说明 备注
+ 0 2 数据的内容 ID 0x0200~0x02FF
+ 可以在以上 ID 段选取,具体 ID 含义由参赛队自定义
- 2 2 ߵ ID ҪУ鷢ߵ ID ȷԣ
+ 2 2 发送者的 ID 需要校验发送者的 ID 正确性,
- 4 2 ߵ ID ҪУߵ ID ȷԣ
- 粻ܷ͵жԻ˵ID
+ 4 2 接收者的 ID 需要校验接收者的 ID 正确性,
+ 例如不能发送到敌对机器人的ID
- 6 n ݶ n ҪС 113
+ 6 n 数据段 n 需要小于 113
*/
-typedef __packed struct
+typedef struct __packed
{
- uint8_t data[100]; //ݶ,nҪС113
+ uint8_t data[100]; //数据段,n需要小于113
} robot_interactive_data_t;
-/* ͻ ͻԶͼΣcmd_id:0x030 */
+/* 客户端 客户端自定义图形:cmd_id:0x030 */
-//ͼ
-typedef __packed struct {
+//图形数据
+typedef struct __packed {
uint8_t graphic_name[3];
uint32_t operate_tpye:3;
uint32_t graphic_tpye:3;
@@ -360,76 +361,76 @@ typedef __packed struct {
uint32_t end_y:11;
} graphic_data_struct_t;
-//ɾͼ data_cmd_id=0x0100
-typedef __packed struct
+//删除图形 data_cmd_id=0x0100
+typedef struct __packed
{
uint8_t operate_tpye;
uint8_t layer;
} ext_client_custom_graphic_delete_t;
-//һͼ data_cmd_id=0x0101
-typedef __packed struct
+//绘制一个图形 data_cmd_id=0x0101
+typedef struct __packed
{
graphic_data_struct_t grapic_data_struct;
} ext_client_custom_graphic_single_t;
-// data_cmd_id=0x0110
-typedef __packed struct {
+//文字数据 data_cmd_id=0x0110
+typedef struct __packed {
graphic_data_struct_t grapic_data_struct;
uint8_t data[30];
} ext_client_custom_character_t;
-//˽Ϣ
-typedef __packed struct
+//机器人交互信息
+typedef struct __packed
{
- xFrameHeader txFrameHeader;//֡ͷ
- uint16_t CmdID;//
- ext_student_interactive_header_data_t dataFrameHeader;//ݶͷṹ
- robot_interactive_data_t interactData;//ݶ
- uint16_t FrameTail;//֡β
+ xFrameHeader txFrameHeader;//帧头
+ uint16_t CmdID;//命令码
+ ext_student_interactive_header_data_t dataFrameHeader;//数据段头结构
+ robot_interactive_data_t interactData;//数据段
+ uint16_t FrameTail;//帧尾
}ext_CommunatianData_t;
-//ͻԶͼϢ
-typedef __packed struct
+//客户端自定义图形信息
+typedef struct __packed
{
- xFrameHeader txFrameHeader;//֡ͷ
- uint16_t CmdID;//
- ext_student_interactive_header_data_t dataFrameHeader;//ݶͷṹ
- ext_client_custom_graphic_single_t graphData;//ݶ
- uint16_t FrameTail;//֡β
+ xFrameHeader txFrameHeader;//帧头
+ uint16_t CmdID;//命令码
+ ext_student_interactive_header_data_t dataFrameHeader;//数据段头结构
+ ext_client_custom_graphic_single_t graphData;//数据段
+ uint16_t FrameTail;//帧尾
}ext_GraphData_t;
-//ͻԶϢ
-typedef __packed struct
+//客户端自定义文字信息
+typedef struct __packed
{
- xFrameHeader txFrameHeader;//֡ͷ
- uint16_t CmdID;//
- ext_student_interactive_header_data_t dataFrameHeader;//ݶͷṹ
- ext_client_custom_character_t textData;//ݶ
- uint16_t FrameTail;//֡β
+ xFrameHeader txFrameHeader;//帧头
+ uint16_t CmdID;//命令码
+ ext_student_interactive_header_data_t dataFrameHeader;//数据段头结构
+ ext_client_custom_character_t textData;//数据段
+ uint16_t FrameTail;//帧尾
}ext_TextData_t;
-//ͻԶUIɾ״
-typedef __packed struct
+//客户端自定义UI删除形状
+typedef struct __packed
{
- xFrameHeader txFrameHeader;//֡ͷ
- uint16_t CmdID;//
- ext_student_interactive_header_data_t dataFrameHeader;//ݶͷṹ
- ext_client_custom_graphic_delete_t deleteData;//ݶ
- uint16_t FrameTail;//֡β
+ xFrameHeader txFrameHeader;//帧头
+ uint16_t CmdID;//命令码
+ ext_student_interactive_header_data_t dataFrameHeader;//数据段头结构
+ ext_client_custom_graphic_delete_t deleteData;//数据段
+ uint16_t FrameTail;//帧尾
}ext_DeleteData_t;
-//ϵͳ֡
+//裁判系统发送数据帧
typedef struct
{
uint8_t data[JUDGE_MAX_FRAME_LENGTH];
uint16_t frameLength;
}JudgeTxFrame;
-/*****************ϵͳݶ**********************/
+/*****************系统数据定义**********************/
typedef struct _judge
{
- xFrameHeader FrameHeader; //֡ͷϢ
+ xFrameHeader FrameHeader; //帧头信息
ext_game_status_t GameState; //0x0001
ext_game_result_t GameResult; //0x0002
ext_game_robot_HP_t GameRobotHP; //0x0003
@@ -450,7 +451,7 @@ typedef struct _judge
}JudgeRecInfo;
/****************************************************/
-//ͼβ
+//图形操作
typedef enum _GraphOperation
{
Operation_Null=0,
@@ -459,7 +460,7 @@ typedef enum _GraphOperation
Operation_Delete
}GraphOperation;
-//ͼ״
+//图形形状
typedef enum _GraphShape
{
Shape_Line=0,
@@ -472,10 +473,10 @@ typedef enum _GraphShape
Shape_Text
}GraphShape;
-//ͼɫ
+//图形颜色
typedef enum _GraphColor
{
- Color_Self=0,//ɫ
+ Color_Self=0,//己方主色
Color_Yellow,
Color_Green,
Color_Orange,
diff --git a/services/rc/rc.c b/services/rc/rc.c
index ace8a9eb4c36a51d0021c32e0da1d8cacf9ac083..6d4190d9b20d2c21396d0050973b1ac96ca7ff1f 100644
--- a/services/rc/rc.c
+++ b/services/rc/rc.c
@@ -1,6 +1,8 @@
#include "config.h"
#include "softbus.h"
#include "cmsis_os.h"
+#include
+#include
#define KEY_NUM 18
//X-MACRO
@@ -24,7 +26,7 @@
MOUSE_KEY(left) \
MOUSE_KEY(right)
-//
+//主键
char* keyType[] = {
#define KEY(x) #x,
#define MOUSE_KEY(x) #x,
@@ -34,66 +36,66 @@ char* keyType[] = {
};
-//ңݽṹ
+//遥控数据结构体
typedef struct {
- //ҡ ȡֵ[-660,660]
+ //摇杆数据 取值[-660,660]
int16_t ch1;
int16_t ch2;
int16_t ch3;
int16_t ch4;
- //Ҳ뿪 1/3/2
+ //左右拨码开关 上1/中3/下2
uint8_t left;
uint8_t right;
- //Ϣ
+ //鼠标信息
struct {
- //ƶٶ
+ //移动速度
int16_t x;
int16_t y;
int16_t z;
- //Ҽ
+ //左右键
uint8_t l;
uint8_t r;
} mouse;
- //Ϣ
+ //键盘信息
union {
- uint16_t key_code;//
+ uint16_t key_code;//按键编码
struct {
#define KEY(x) uint16_t x : 1;
#define MOUSE_KEY(x)
KEY_TPYE
#undef KEY
#undef MOUSE_KEY
- } bit;//λӦļλ
+ } bit;//各个位代表对应的键位
} kb;
- // ȡֵ[-660,660]
+ //拨轮数据 取值[-660,660]
int16_t wheel;
}RC_TypeDef;
-//ṹ壬ڼ/ݼ
+//按键结构体,用于计算键盘/鼠标的按键事件
typedef struct{
- //ҪõIJ
- uint16_t clickDelayTime;//¶ò㵥һ
- uint16_t longPressTime;//¶ò㳤
+ //需要配置的参数
+ uint16_t clickDelayTime;//按下多久才算单击一次
+ uint16_t longPressTime;//按下多久才算长按
- //ʹõIJڶӦЧһ˲Ϊ1
+ //用来使用的参数,仅在对应条件有效的一瞬间为1
uint8_t isClicked;
uint8_t isLongPressed;
uint8_t isUp;
uint8_t isPressing;
- //м
- uint8_t lastState;//1/0Ϊ/ɿ
+ //中间变量
+ uint8_t lastState;//1/0为按下/松开
uint32_t startPressTime;
}Key;
typedef struct
{
- RC_TypeDef rcInfo;//ң
- Key keyList[KEY_NUM];//б(пṵ̈Ҽ)
+ RC_TypeDef rcInfo;//遥控器数据
+ Key keyList[KEY_NUM];//按键列表(包含所有可用键盘按键和鼠标左右键)
uint8_t uartX;
}RC;
-//ڲ
-//ʼжʱ
+//内部函数
+//初始化判定时间
void RC_InitKeys(RC* rc);
void RC_InitKeyJudgeTime(RC* rc, uint32_t key,uint16_t clickDelay,uint16_t longPressDelay);
void RC_PublishData(RC *rc);
@@ -101,9 +103,11 @@ void RC_UpdateKeys(RC* rc);
void RC_ParseData(RC* rc, uint8_t* buff);
void RC_SoftBusCallback(const char* name, SoftBusFrame* frame, void* bindData);
+static RC* GlobalRC; // 调试用
+
void RC_TaskCallback(void const * argument)
{
- //ٽ
+ //进入临界区
portENTER_CRITICAL();
RC rc={0};
rc.uartX = Conf_GetValue((ConfItem*)argument, "uart-x", uint8_t, 0);
@@ -112,6 +116,8 @@ void RC_TaskCallback(void const * argument)
name[5] = rc.uartX + '0';
Bus_RegisterReceiver(&rc, RC_SoftBusCallback, name);
portEXIT_CRITICAL();
+
+ GlobalRC = &rc;
osDelay(2000);
while(1)
@@ -121,14 +127,14 @@ void RC_TaskCallback(void const * argument)
}
}
-//ʼажʱ
+//初始化所有按键的判定时间
void RC_InitKeys(RC* rc)
{
- //ʼȫ(0x3ffff)
+ //初始化全部按键(0x3ffff)
RC_InitKeyJudgeTime(rc,0x3ffff,50,500);
}
-//ʼһжʱ(λIDжʱ䣬жʱ)
+//初始化一个按键的判定时间(键位ID,单击判定时间,长按判定时间)
void RC_InitKeyJudgeTime(RC* rc, uint32_t key,uint16_t clickDelay,uint16_t longPressDelay)
{
for(uint8_t i=0;i<18;i++)
@@ -142,15 +148,15 @@ void RC_InitKeyJudgeTime(RC* rc, uint32_t key,uint16_t clickDelay,uint16_t longP
}
-//ݸrc
+//若有数据更新则发布rc数据
void RC_PublishData(RC *rc)
{
static RC_TypeDef lastData={0};
- if(lastData.ch1 != rc->rcInfo.ch1 || lastData.ch2 != rc->rcInfo.ch2)
+ if(abs(lastData.ch1) > 5 || abs(lastData.ch2) > 5)
Bus_BroadcastSend("/rc/right-stick",{{"x",&rc->rcInfo.ch1},{"y",&rc->rcInfo.ch2}});
- if(lastData.ch3 != rc->rcInfo.ch3 || lastData.ch4 != rc->rcInfo.ch4)
+ if(abs(lastData.ch3) > 5 || abs(lastData.ch4) > 5)
Bus_BroadcastSend("/rc/left-stick",{{"x",&rc->rcInfo.ch3},{"y",&rc->rcInfo.ch4}});
if(lastData.mouse.x != rc->rcInfo.mouse.x || lastData.mouse.y != rc->rcInfo.mouse.y)
@@ -165,31 +171,31 @@ void RC_PublishData(RC *rc)
if(lastData.wheel != rc->rcInfo.wheel)
Bus_BroadcastSend("/rc/wheel",{{"value",&rc->rcInfo.wheel}});
- //°״̬
+ //更新按键状态并发布
RC_UpdateKeys(rc);
lastData =rc->rcInfo;
}
-//°״̬ҪʱãΪ14ms
+//更新按键状态,需要定时调用,建议间隔为14ms
void RC_UpdateKeys(RC* rc)
{
static uint32_t lastUpdateTime;
- uint32_t presentTime=osKernelSysTick();//ȡϵͳʱ
+ uint32_t presentTime=osKernelSysTick();//获取系统时间戳
- //ϼ
+ //检查组合键
char* combineKey="none";
if(rc->rcInfo.kb.bit.Ctrl) combineKey="ctrl";
else if(rc->rcInfo.kb.bit.Shift) combineKey="shift";
for(uint8_t key=0;key<18;key++)
{
- //ȡ״̬
+ //读取按键状态
uint8_t thisState=0;
if(key==4||key==5) continue;
char name[22] = "/rc/key/";
if(key<16)
{
- thisState=(rc->rcInfo.kb.key_code&(0x01<rcInfo.kb.key_code&(0x01<rcInfo.mouse.r;
}
- uint16_t lastPressTime=lastUpdateTime-rc->keyList[key].startPressTime;//ϴθʱµʱ
- uint16_t pressTime=presentTime-rc->keyList[key].startPressTime;//ǰµʱ
+ uint16_t lastPressTime=lastUpdateTime-rc->keyList[key].startPressTime;//上次更新时按下的时间
+ uint16_t pressTime=presentTime-rc->keyList[key].startPressTime;//当前按下的时间
- //״̬ж
- /*******µһ˲********/
+ //按键状态判定
+ /*******按下的一瞬间********/
if(!rc->keyList[key].lastState && thisState)
{
- rc->keyList[key].startPressTime=presentTime;//¼ʱ
+ rc->keyList[key].startPressTime=presentTime;//记录按下时间
rc->keyList[key].isPressing=1;
- //topic
+ //发布topic
memcpy(name+8, "on-down", 8);
Bus_BroadcastSend(name, {
{"key", keyType[key]},
{"combine-key", combineKey}
});
}
- /*******ɿһ˲********/
+ /*******松开的一瞬间********/
else if(rc->keyList[key].lastState && !thisState)
{
rc->keyList[key].isLongPressed=0;
rc->keyList[key].isPressing=0;
- //̧
+ //按键抬起
rc->keyList[key].isUp=1;
- //topic
+ //发布topic
memcpy(name+8, "on-up", 6);
Bus_BroadcastSend(name, {
{"key", keyType[key]},
{"combine-key", combineKey}
});
- //ж
+ //单击判定
if(pressTime>rc->keyList[key].clickDelayTime && pressTimekeyList[key].longPressTime)
{
rc->keyList[key].isClicked=1;
- //topic
+ //发布topic
memcpy(name+8, "on-click", 9);
Bus_BroadcastSend(name, {
{"key", keyType[key]},
@@ -243,22 +249,22 @@ void RC_UpdateKeys(RC* rc)
});
}
}
- /***************/
+ /*******按键持续按下********/
else if(rc->keyList[key].lastState && thisState)
{
- //ִһֱµ¼ص
- //topic
+ //执行一直按下的事件回调
+ //发布topic
memcpy(name+8, "on-pressing", 12);
Bus_BroadcastSend(name, {
{"key", keyType[key]},
{"combine-key", combineKey}
});
- //ж
+ //长按判定
if(lastPressTime<=rc->keyList[key].longPressTime && pressTime>rc->keyList[key].longPressTime)
{
rc->keyList[key].isLongPressed=1;
- //topic
+ //发布topic
memcpy(name+8, "on-long-press", 14);
Bus_BroadcastSend(name, {
{"key", keyType[key]},
@@ -267,7 +273,7 @@ void RC_UpdateKeys(RC* rc)
}
else rc->keyList[key].isLongPressed=0;
}
- /*******ɿ********/
+ /*******按键持续松开********/
else
{
rc->keyList[key].isClicked=0;
@@ -275,10 +281,10 @@ void RC_UpdateKeys(RC* rc)
rc->keyList[key].isUp=0;
}
- rc->keyList[key].lastState=thisState;//¼״̬
+ rc->keyList[key].lastState=thisState;//记录按键状态
}
- lastUpdateTime=presentTime;//¼¼
+ lastUpdateTime=presentTime;//记录更新事件
}
@@ -287,11 +293,12 @@ void RC_SoftBusCallback(const char* name, SoftBusFrame* frame, void* bindData)
RC* rc = (RC*)bindData;
uint8_t* data = (uint8_t*)Bus_GetListValue(frame, 0);
- if(data)
+ uint16_t* len = (uint16_t*)Bus_GetListValue(frame, 1);
+ if(data && len)
RC_ParseData(rc, data);
}
-//
+//解析串口数据
void RC_ParseData(RC* rc, uint8_t* buff)
{
rc->rcInfo.ch1 = (buff[0] | buff[1] << 8) & 0x07FF;
diff --git a/services/shoot/shoot.c b/services/shoot/shoot.c
index 4d32cf334a8fafb445f8d9d32503e55d1de07c97..4916c511615dd53c6944d74faa6b49e34f95d84a 100644
--- a/services/shoot/shoot.c
+++ b/services/shoot/shoot.c
@@ -15,9 +15,9 @@ typedef struct
{
Motor *fricMotors[2],*triggerMotor;
bool fricEnable;
- float fricSpeed; //Ħٶ
- float triggerAngle,targetTrigAngle; //һνǶȼۼƽǶ
- uint16_t intervalTime; //ms
+ float fricSpeed; //摩擦轮速度
+ float triggerAngle,targetTrigAngle; //拨弹一次角度及累计角度
+ uint16_t intervalTime; //连发间隔ms
uint8_t mode;
uint16_t taskInterval;
@@ -35,7 +35,7 @@ void Shoot_StopCallback(const char* name, SoftBusFrame* frame, void* bindData);
void Shooter_TaskCallback(void const * argument)
{
portENTER_CRITICAL();
- float totalAngle; //ΪwarningCбǩһ䲻ǶıʽcaseǡþDZǩ
+ float totalAngle; //为解决warning,C语言中标签的下一条语句不能是定义变量的表达式,而case恰好就是标签
Shooter shooter={0};
Shooter_Init(&shooter, (ConfItem*)argument);
portEXIT_CRITICAL();
@@ -49,29 +49,29 @@ void Shooter_TaskCallback(void const * argument)
osDelay(shooter.taskInterval);
break;
case SHOOTER_MODE_BLOCK:
- totalAngle = shooter.triggerMotor->getData(shooter.triggerMotor, "totalAngle"); //õǶΪǰۼƽǶ
- shooter.targetTrigAngle = totalAngle - shooter.triggerAngle*0.5f; //ת
+ totalAngle = shooter.triggerMotor->getData(shooter.triggerMotor, "totalAngle"); //重置电机角度为当前累计角度
+ shooter.targetTrigAngle = totalAngle - shooter.triggerAngle*0.5f; //反转
shooter.triggerMotor->setTarget(shooter.triggerMotor,shooter.targetTrigAngle);
- osDelay(500); //ȴתָ
+ osDelay(500); //等待电机堵转恢复
shooter.mode = SHOOTER_MODE_IDLE;
break;
- case SHOOTER_MODE_ONCE: //
- if(shooter.fricEnable == false) //Ħδȿ
+ case SHOOTER_MODE_ONCE: //单发
+ if(shooter.fricEnable == false) //若摩擦轮未开启则先开启
{
- Bus_RemoteCall("/shooter/setting",{"fric-enable",IM_PTR(bool,true)});
- osDelay(200); //ȴĦתȶ
+ Bus_RemoteCall("/shooter/setting",{{"fric-enable",{.Bool = true}}});
+ osDelay(200); //等待摩擦轮转速稳定
}
shooter.targetTrigAngle += shooter.triggerAngle;
shooter.triggerMotor->setTarget(shooter.triggerMotor,shooter.targetTrigAngle);
shooter.mode = SHOOTER_MODE_IDLE;
break;
- case SHOOTER_MODE_CONTINUE: //һʱ
- if(shooter.fricEnable == false) //Ħδȿ
+ case SHOOTER_MODE_CONTINUE: //以一定的时间间隔连续发射
+ if(shooter.fricEnable == false) //若摩擦轮未开启则先开启
{
- Bus_RemoteCall("/shooter/setting",{"fric-enable",IM_PTR(bool,true)});
- osDelay(200); //ȴĦתȶ
+ Bus_RemoteCall("/shooter/setting",{{"fric-enable",{.Bool = true}}});
+ osDelay(200); //等待摩擦轮转速稳定
}
- shooter.targetTrigAngle += shooter.triggerAngle; //ӲĿǶ
+ shooter.targetTrigAngle += shooter.triggerAngle; //增加拨弹电机目标角度
shooter.triggerMotor->setTarget(shooter.triggerMotor,shooter.targetTrigAngle);
osDelay(shooter.intervalTime);
break;
@@ -83,17 +83,17 @@ void Shooter_TaskCallback(void const * argument)
void Shooter_Init(Shooter* shooter, ConfItem* dict)
{
- //
+ //任务间隔
shooter->taskInterval = Conf_GetValue(dict, "task-interval", uint16_t, 20);
- //ʼ
+ //初始弹速
shooter->fricSpeed = Conf_GetValue(dict,"fric-speed",float,5450);
- //ֲһת
+ //拨弹轮拨出一发弹丸转角
shooter->triggerAngle = Conf_GetValue(dict,"trigger-angle",float,1/7.0*360);
- //ʼ
+ //发射机构电机初始化
shooter->fricMotors[0] = Motor_Init(Conf_GetPtr(dict, "fric-motor-left", ConfItem));
shooter->fricMotors[1] = Motor_Init(Conf_GetPtr(dict, "fric-motor-right", ConfItem));
shooter->triggerMotor = Motor_Init(Conf_GetPtr(dict, "trigger-motor", ConfItem));
- //÷ģʽ
+ //设置发射机构电机模式
for(uint8_t i = 0; i<2; i++)
{
shooter->fricMotors[i]->changeMode(shooter->fricMotors[i], MOTOR_SPEED_MODE);
@@ -103,26 +103,26 @@ void Shooter_Init(Shooter* shooter, ConfItem* dict)
char* temp = Conf_GetPtr(dict, "name", char);
temp = temp ? temp : "shooter";
uint8_t len = strlen(temp);
- shooter->settingName = pvPortMalloc(len + 9+ 1); //9Ϊ"/ /setting"ijȣ1Ϊ'\0'ij
+ shooter->settingName = pvPortMalloc(len + 9+ 1); //9为"/ /setting"的长度,1为'\0'的长度
sprintf(shooter->settingName, "/%s/setting", temp);
- shooter->changeModeName = pvPortMalloc(len + 6+ 1); //6Ϊ"/ /mode"ijȣ1Ϊ'\0'ij
+ shooter->changeModeName = pvPortMalloc(len + 6+ 1); //6为"/ /mode"的长度,1为'\0'的长度
sprintf(shooter->changeModeName, "/%s/mode", temp);
temp = Conf_GetPtr(dict, "trigger-motor/name", char);
temp = temp ? temp : "trigger-motor";
len = strlen(temp);
- shooter->triggerStallName = pvPortMalloc(len + 7+ 1); //7Ϊ"/ /stall"ijȣ1Ϊ'\0'ij
+ shooter->triggerStallName = pvPortMalloc(len + 7+ 1); //7为"/ /stall"的长度,1为'\0'的长度
sprintf(shooter->triggerStallName, "/%s/stall", temp);
- //עص
+ //注册回调函数
Bus_RegisterRemoteFunc(shooter,Shooter_SettingCallback, shooter->settingName);
Bus_RegisterRemoteFunc(shooter,Shoot_ChangeModeCallback, shooter->changeModeName);
Bus_RegisterReceiver(shooter,Shoot_StopCallback,"/system/stop");
Bus_RegisterReceiver(shooter,Shooter_BlockCallback, shooter->triggerStallName);
}
-//ģʽ
+//射击模式
bool Shooter_SettingCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
Shooter *shooter = (Shooter*)bindData ;
@@ -158,7 +158,7 @@ bool Shoot_ChangeModeCallback(const char* name, SoftBusFrame* frame, void* bindD
if(Bus_IsMapKeyExist(frame,"mode"))
{
char* mode = (char*)Bus_GetMapValue(frame,"mode");
- if(!strcmp(mode,"once") && shooter->mode == SHOOTER_MODE_IDLE) //ʱģʽ
+ if(!strcmp(mode,"once") && shooter->mode == SHOOTER_MODE_IDLE) //空闲时才允许修改模式
{
shooter->mode = SHOOTER_MODE_ONCE;
return true;
@@ -180,13 +180,13 @@ bool Shoot_ChangeModeCallback(const char* name, SoftBusFrame* frame, void* bindD
return false;
}
-//ת
+//堵转
void Shooter_BlockCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
Shooter *shooter = (Shooter*)bindData;
shooter->mode = SHOOTER_MODE_BLOCK;
}
-//ͣ
+//急停
void Shoot_StopCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
Shooter *shooter = (Shooter*)bindData;
diff --git a/softbus/CMakeLists.txt b/softbus/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..732ff6e231cc121f8eda8a9bf805f0a53ce9c8f2
--- /dev/null
+++ b/softbus/CMakeLists.txt
@@ -0,0 +1,7 @@
+
+# 软总线源码列表
+file(GLOB SOFTBUS_SRC *.c)
+set(SOFTBUS_MODULE_SRC ${SOFTBUS_SRC} PARENT_SCOPE)
+
+# 添加包含目录
+set(SOFTBUS_MODULE_INCL ${CMAKE_CURRENT_LIST_DIR} PARENT_SCOPE)
diff --git a/softbus/README.md b/softbus/README.md
index b4abd83ba90273832172fb53dcb2ef62da13974f..e0b86e526f4e91525719917c08e9cbaf7da5e18e 100644
--- a/softbus/README.md
+++ b/softbus/README.md
@@ -184,10 +184,10 @@ float value2 = 1.0f; //要传入的第二个参数
float result1; //用于接收远程函数第一个返回值
uint8_t result2; //用于接收远程函数第二个返回值
Bus_RemoteCall("fun1", {
- {"arg1", &value1},
- {"arg2", &value2},
- {"ret1", &result1},
- {"ret2", &result2}
+ {"arg1", {.U8 = &value1}},
+ {"arg2", {.F32 = &value2}},
+ {"ret1", {&result1}},
+ {"ret2", {&result2}}
}); //调用远程函数fun1
```
diff --git a/softbus/softbus.c b/softbus/softbus.c
index aed779048c6889161e15c126ff8502f3f8597fd2..fe2d6c56907c4f0e6b3374245fb11237aa2a8dc1 100644
--- a/softbus/softbus.c
+++ b/softbus/softbus.c
@@ -15,35 +15,35 @@
typedef struct{
void* bindData;
void* callback;
-}CallbackNode;//صڵ
+}CallbackNode;//回调函数节点
typedef struct{
char* name;
Vector callbackNodes;
-}ReceiverNode;//receiverڵ
+}ReceiverNode;//receiver节点
typedef struct
{
char* name;
CallbackNode callbackNode;
-}RemoteNode;//remoteڵ
+}RemoteNode;//remote节点
typedef struct{
uint32_t hash;
Vector receiverNodes;
Vector remoteNodes;
-}HashNode;//hashڵ
+}HashNode;//hash节点
-int8_t Bus_Init(void);//ʼ,0:ɹ -1:ʧ
-uint32_t SoftBus_Str2Hash_8(const char* str);//8λhashַС20ַʱʹ
-uint32_t SoftBus_Str2Hash_32(const char* str);//32λhashַС20ַʱʹ
-void _Bus_BroadcastSend(const char* name, SoftBusFrame* frame);//Ϣ
-bool _Bus_RemoteCall(const char* name, SoftBusFrame* frame);//
-void Bus_EmptyBroadcastReceiver(const char* name, SoftBusFrame* frame, void* bindData);//ջص
-bool Bus_EmptyRemoteFunction(const char* name, SoftBusFrame* frame, void* bindData);//ջص
+int8_t Bus_Init(void);//初始化软总线,返回0:成功 -1:失败
+uint32_t SoftBus_Str2Hash_8(const char* str);//8位处理的hash函数,在字符串长度小于20个字符时使用
+uint32_t SoftBus_Str2Hash_32(const char* str);//32位处理的hash函数,在字符串长度小于20个字符时使用
+void _Bus_BroadcastSend(const char* name, SoftBusFrame* frame);//发布消息
+bool _Bus_RemoteCall(const char* name, SoftBusFrame* frame);//请求服务
+void Bus_EmptyBroadcastReceiver(const char* name, SoftBusFrame* frame, void* bindData);//空回调函数
+bool Bus_EmptyRemoteFunction(const char* name, SoftBusFrame* frame, void* bindData);//空回调函数
Vector hashList={0};
-//ʼhash
+//初始化hash树
int8_t Bus_Init()
{
return Vector_Init(hashList,HashNode);
@@ -53,38 +53,38 @@ int8_t Bus_RegisterReceiver(void* bindData, SoftBusBroadcastReceiver callback, c
{
if(!name || !callback)
return -2;
- if(hashList.data == NULL)//δʼʼ
+ if(hashList.data == NULL)//如果软总线未初始化则初始化软总线
{
if(Bus_Init())
return -1;
}
- uint32_t hash = SoftBus_Str2Hash(name);//ַhashֵ
- Vector_ForEach(hashList, hashNode, HashNode)//hashڵ
+ uint32_t hash = SoftBus_Str2Hash(name);//计算字符串hash值
+ Vector_ForEach(hashList, hashNode, HashNode)//遍历所有hash节点
{
if(hash == hashNode->hash)
{
- Vector_ForEach(hashNode->receiverNodes, receiverNode, ReceiverNode)//hashڵreceiver
+ Vector_ForEach(hashNode->receiverNodes, receiverNode, ReceiverNode)//遍历该hash节点下所有receiver
{
- if(strcmp(name, receiverNode->name) == 0)//ƥ䵽receiverעص
+ if(strcmp(name, receiverNode->name) == 0)//匹配到已有receiver注册回调函数
{
- if(Vector_GetFront(receiverNode->callbackNodes, CallbackNode)->callback == Bus_EmptyBroadcastReceiver)//receiverпջص
+ if(Vector_GetFront(receiverNode->callbackNodes, CallbackNode)->callback == Bus_EmptyBroadcastReceiver)//如果该receiver下有空回调函数
{
CallbackNode* callbackNode = Vector_GetFront(receiverNode->callbackNodes, CallbackNode);
- callbackNode->bindData = bindData;//°
- callbackNode->callback = callback;//»ص
+ callbackNode->bindData = bindData;//更新绑定数据
+ callbackNode->callback = callback;//更新回调函数
return 0;
}
return Vector_PushBack(receiverNode->callbackNodes, ((CallbackNode){bindData, callback}));
}
}
- Vector callbackNodes = Vector_Create(CallbackNode);//δƥ䵽receiverhashͻڸhashڵ㴦һreceiverڵhashͻ
+ Vector callbackNodes = Vector_Create(CallbackNode);//未匹配到receiver产生hash冲突,在该hash节点处添加一个receiver节点解决hash冲突
Vector_PushBack(callbackNodes, ((CallbackNode){bindData, callback}));
- char* nameCpy = SOFTBUS_MALLOC_PORT(SOFTBUS_STRLEN_PORT(name)+1);//ֹnameǾֲռ䱣浽hash
+ char* nameCpy = SOFTBUS_MALLOC_PORT(SOFTBUS_STRLEN_PORT(name)+1);//防止name是局部变量,分配空间保存到hash树中
SOFTBUS_MEMCPY_PORT(nameCpy, name, SOFTBUS_STRLEN_PORT(name)+1);
return Vector_PushBack(hashNode->receiverNodes,((ReceiverNode){nameCpy, callbackNodes}));
}
}
- Vector callbackNodes = Vector_Create(CallbackNode);//µhashڵ
+ Vector callbackNodes = Vector_Create(CallbackNode);//新的hash节点
Vector_PushBack(callbackNodes, ((CallbackNode){bindData, callback}));
Vector receiverV = Vector_Create(ReceiverNode);
Vector remoteV = Vector_Create(RemoteNode);
@@ -101,7 +101,7 @@ int8_t _Bus_MultiRegisterReceiver(void* bindData, SoftBusBroadcastReceiver callb
return -2;
for (uint16_t i = 0; i < namesNum; i++)
{
- uint8_t retval = Bus_RegisterReceiver(bindData, callback, names[i]); //Ļ
+ uint8_t retval = Bus_RegisterReceiver(bindData, callback, names[i]); //逐个订阅话题
if(retval)
return retval;
}
@@ -132,13 +132,13 @@ void _Bus_BroadcastSend(const char* name, SoftBusFrame* frame)
if(!hashList.data ||!name || !frame)
return;
uint32_t hash = SoftBus_Str2Hash(name);
- Vector_ForEach(hashList, hashNode, HashNode)//hashڵ
+ Vector_ForEach(hashList, hashNode, HashNode)//遍历所有hash节点
{
- if(hash == hashNode->hash)//ƥ䵽hashֵ
+ if(hash == hashNode->hash)//匹配到hash值
{
- Vector_ForEach(hashNode->receiverNodes, receiverNode, ReceiverNode)//hashڵreceiver
+ Vector_ForEach(hashNode->receiverNodes, receiverNode, ReceiverNode)//遍历改hash节点的所有receiver
{
- if(strcmp(name, receiverNode->name) == 0)//ƥ䵽receiver׳receiverлص
+ if(strcmp(name, receiverNode->name) == 0)//匹配到receiver,抛出该receiver所有回调函数
{
Vector_ForEach(receiverNode->callbackNodes, callbackNode, CallbackNode)
{
@@ -152,7 +152,7 @@ void _Bus_BroadcastSend(const char* name, SoftBusFrame* frame)
}
}
-void _Bus_BroadcastSendMap(const char* name, uint16_t itemNum, SoftBusItem* items)
+void _Bus_BroadcastSendMap(const char* name, uint16_t itemNum, SoftBusItemX* items)
{
if(!hashList.data ||!name || !itemNum || !items)
return;
@@ -166,7 +166,7 @@ void _Bus_BroadcastSendList(SoftBusReceiverHandle receiverHandle, uint16_t listN
return;
ReceiverNode* receiverNode = (ReceiverNode*)receiverHandle;
SoftBusFrame frame = {list, listNum};
- Vector_ForEach(receiverNode->callbackNodes, callbackNode, CallbackNode)//׳ÿپлص
+ Vector_ForEach(receiverNode->callbackNodes, callbackNode, CallbackNode)//抛出该快速句柄下所有回调函数
{
(*((SoftBusBroadcastReceiver)callbackNode->callback))(receiverNode->name, &frame, callbackNode->bindData);
}
@@ -176,58 +176,58 @@ SoftBusReceiverHandle Bus_CreateReceiverHandle(const char* name)
{
if(!name)
return NULL;
- uint32_t hash = SoftBus_Str2Hash(name);//ַhashֵ
- Vector_ForEach(hashList, hashNode, HashNode)//hashڵ
+ uint32_t hash = SoftBus_Str2Hash(name);//计算字符串hash值
+ Vector_ForEach(hashList, hashNode, HashNode)//遍历所有hash节点
{
if(hash == hashNode->hash)
{
- Vector_ForEach(hashNode->receiverNodes, receiverNode, ReceiverNode)//hashڵreceiver
+ Vector_ForEach(hashNode->receiverNodes, receiverNode, ReceiverNode)//遍历该hash节点下所有receiver
{
- if(strcmp(name, receiverNode->name) == 0)//ƥ䵽receiverעص
+ if(strcmp(name, receiverNode->name) == 0)//匹配到已有receiver注册回调函数
{
return receiverNode;
}
}
}
}
- Bus_RegisterReceiver(NULL, Bus_EmptyBroadcastReceiver, name);//δƥ䵽receiver,עһջص
- return Bus_CreateReceiverHandle(name);//ݹ
+ Bus_RegisterReceiver(NULL, Bus_EmptyBroadcastReceiver, name);//未匹配到receiver,注册一个空回调函数
+ return Bus_CreateReceiverHandle(name);//递归调用
}
int8_t Bus_RegisterRemoteFunc(void* bindData, SoftBusRemoteFunction callback, const char* name)
{
if(!name || !callback)
return -2;
- if(hashList.data == NULL)//δʼʼ
+ if(hashList.data == NULL)//如果软总线未初始化则初始化软总线
{
if(Bus_Init())
return -1;
}
- uint32_t hash = SoftBus_Str2Hash(name);//ַhashֵ
- Vector_ForEach(hashList, hashNode, HashNode)//hashڵ
+ uint32_t hash = SoftBus_Str2Hash(name);//计算字符串hash值
+ Vector_ForEach(hashList, hashNode, HashNode)//遍历所有hash节点
{
if(hash == hashNode->hash)
{
- Vector_ForEach(hashNode->remoteNodes, remoteNode, RemoteNode)//hashڵremote
+ Vector_ForEach(hashNode->remoteNodes, remoteNode, RemoteNode)//遍历该hash节点下所有remote
{
- if(strcmp(name, remoteNode->name) == 0)//ƥ䵽remoteעص
+ if(strcmp(name, remoteNode->name) == 0)//匹配到已有remote注册回调函数
{
- if(remoteNode->callbackNode.callback == Bus_EmptyRemoteFunction)//remoteΪջص
+ if(remoteNode->callbackNode.callback == Bus_EmptyRemoteFunction)//如果该remote下为空回调函数
{
- remoteNode->callbackNode = ((CallbackNode){bindData, callback});//»ص
+ remoteNode->callbackNode = ((CallbackNode){bindData, callback});//更新回调函数
return 0;
}
- return -3; //÷עһж
+ return -3; //该服务已注册过服务器,不允许一个服务有多个服务器
}
}
- CallbackNode callbackNode = {bindData, callback};//δƥ䵽remotehashͻڸhashڵ㴦һremoteڵhashͻ
+ CallbackNode callbackNode = {bindData, callback};//未匹配到remote产生hash冲突,在该hash节点处添加一个remote节点解决hash冲突
char* remoteCpy = SOFTBUS_MALLOC_PORT(SOFTBUS_STRLEN_PORT(name)+1);
SOFTBUS_MEMCPY_PORT(remoteCpy, name, SOFTBUS_STRLEN_PORT(name)+1);
return Vector_PushBack(hashNode->remoteNodes,((RemoteNode){remoteCpy, callbackNode}));
}
}
- Vector remoteV = Vector_Create(RemoteNode);//µhashڵ
+ Vector remoteV = Vector_Create(RemoteNode);//新的hash节点
char* nameCpy = SOFTBUS_MALLOC_PORT(SOFTBUS_STRLEN_PORT(name)+1);
SOFTBUS_MEMCPY_PORT(nameCpy, name, SOFTBUS_STRLEN_PORT(name)+1);
Vector callbackNodes = Vector_Create(CallbackNode);
@@ -243,13 +243,13 @@ bool _Bus_RemoteCall(const char* name, SoftBusFrame* frame)
if(!hashList.data ||!name || !frame)
return false;
uint32_t hash = SoftBus_Str2Hash(name);
- Vector_ForEach(hashList, hashNode, HashNode)//hashڵ
+ Vector_ForEach(hashList, hashNode, HashNode)//遍历所有hash节点
{
- if(hash == hashNode->hash)//ƥ䵽hashֵ
+ if(hash == hashNode->hash)//匹配到hash值
{
- Vector_ForEach(hashNode->remoteNodes, remoteNode, RemoteNode)//hashڵremote
+ Vector_ForEach(hashNode->remoteNodes, remoteNode, RemoteNode)//遍历改hash节点的所有remote
{
- if(strcmp(name, remoteNode->name) == 0)//ƥ䵽remote׳remoteĻص
+ if(strcmp(name, remoteNode->name) == 0)//匹配到remote,抛出该remote的回调函数
{
CallbackNode callbackNode = remoteNode->callbackNode;
return (*((SoftBusRemoteFunction)callbackNode.callback))(name, frame, callbackNode.bindData);
@@ -261,7 +261,7 @@ bool _Bus_RemoteCall(const char* name, SoftBusFrame* frame)
return false;
}
-bool _Bus_RemoteCallMap(const char* name, uint16_t itemNum, SoftBusItem* items)
+bool _Bus_RemoteCallMap(const char* name, uint16_t itemNum, SoftBusItemX* items)
{
if(!hashList.data ||!name || !itemNum || !items)
return false;
@@ -286,7 +286,7 @@ const SoftBusItem* Bus_GetMapItem(SoftBusFrame* frame, char* key)
for(uint16_t i = 0; i < frame->size; ++i)
{
SoftBusItem* item = (SoftBusItem*)frame->data + i;
- if(strcmp(key, item->key) == 0)//keyֵ֡Ӧֶƥ
+ if(strcmp(key, item->key) == 0)//如果key值与数据帧中相应的字段匹配上则返回它
return item;
}
return NULL;
diff --git a/softbus/softbus.h b/softbus/softbus.h
index 9356cb69ddb283800bc8ce825d15c976076cdda5..8ff6d84b9922f4a320cb7ab63c5df45e08641b6a 100644
--- a/softbus/softbus.h
+++ b/softbus/softbus.h
@@ -7,136 +7,153 @@
typedef struct{
void* data;
uint16_t size;
-}SoftBusFrame;//֡
+}SoftBusFrame;//数据帧
typedef struct{
char* key;
void* data;
-}SoftBusItem;//ֶ
+}SoftBusItem;//数据字段
+
+typedef struct _SoftBusItemX {
+ const char* key;
+ union {
+ void* Ptr;
+ const char* Str;
+ uint32_t U32;
+ uint16_t U16;
+ uint8_t U8;
+ int32_t I32;
+ int16_t I16;
+ int8_t I8;
+ float F32;
+ _Bool Bool;
+ struct _SoftBusItemX* Child;
+ }; // 字长以内的数据均可以直接指定
+} SoftBusItemX;
#ifndef IM_PTR
-#define IM_PTR(type,...) (&(type){__VA_ARGS__}) //ȡĵַ
+#define IM_PTR(type,...) (&(type){__VA_ARGS__}) //取立即数的地址
#endif
-typedef void* SoftBusReceiverHandle;//߿پ
-typedef void (*SoftBusBroadcastReceiver)(const char* name, SoftBusFrame* frame, void* bindData);//㲥صָ
-typedef bool (*SoftBusRemoteFunction)(const char* name, SoftBusFrame* frame, void* bindData);//Զ̺صָ
+typedef void* SoftBusReceiverHandle;//软总线快速句柄
+typedef void (*SoftBusBroadcastReceiver)(const char* name, SoftBusFrame* frame, void* bindData);//广播回调函数指针
+typedef bool (*SoftBusRemoteFunction)(const char* name, SoftBusFrame* frame, void* bindData);//远程函数回调函数指针
-//(ֱӵãӦʹ·defineĽӿ)
+//操作函数声明(不直接调用,应使用下方define定义的接口)
int8_t _Bus_MultiRegisterReceiver(void* bindData, SoftBusBroadcastReceiver callback, uint16_t namesNum, char** names);
-void _Bus_BroadcastSendMap(const char* name, uint16_t itemNum, SoftBusItem* items);
+void _Bus_BroadcastSendMap(const char* name, uint16_t itemNum, SoftBusItemX* items);
void _Bus_BroadcastSendList(SoftBusReceiverHandle receiverHandle, uint16_t listNum, void** list);
-bool _Bus_RemoteCallMap(const char* name, uint16_t itemNum, SoftBusItem* items);
+bool _Bus_RemoteCallMap(const char* name, uint16_t itemNum, SoftBusItemX* items);
uint8_t _Bus_CheckMapKeys(SoftBusFrame* frame, uint16_t keysNum, char** keys);
/*
- @brief ϵһ㲥
- @param callback:㲥ʱĻص
- @param name:㲥
- @retval 0:ɹ -1:ѿռ䲻 -2:Ϊ
- @note صʽӦΪvoid callback(const char* name, SoftBusFrame* frame, void* bindData)
+ @brief 订阅软总线上的一个广播
+ @param callback:广播发布时的回调函数
+ @param name:广播名
+ @retval 0:成功 -1:堆空间不足 -2:参数为空
+ @note 回调函数的形式应为void callback(const char* name, SoftBusFrame* frame, void* bindData)
*/
int8_t Bus_RegisterReceiver(void* bindData, SoftBusBroadcastReceiver callback, const char* name);
/*
- @brief ϵĶ㲥
- @param bindData:
- @param callback:㲥ʱĻص
- @param ...:㲥ַб
- @retval 0:ɹ -1:ѿռ䲻 -2:Ϊ
+ @brief 订阅软总线上的多个广播
+ @param bindData:绑定数据
+ @param callback:广播发布时的回调函数
+ @param ...:广播字符串列表
+ @retval 0:成功 -1:堆空间不足 -2:参数为空
@example Bus_MultiRegisterReceiver(NULL, callback, {"name1", "name2"});
*/
#define Bus_MultiRegisterReceiver(bindData, callback,...) _Bus_MultiRegisterReceiver((bindData),(callback),(sizeof((char*[])__VA_ARGS__)/sizeof(char*)),((char*[])__VA_ARGS__))
/*
- @brief 㲥ӳ֡
- @param name:㲥
- @param ...:ӳ
+ @brief 广播映射表数据帧
+ @param name:广播名
+ @param ...:映射表
@retval void
@example Bus_BroadcastSend("name", {{"key1", data1}, {"key2", data2}});
*/
-#define Bus_BroadcastSend(name,...) _Bus_BroadcastSendMap((name),(sizeof((SoftBusItem[])__VA_ARGS__)/sizeof(SoftBusItem)),((SoftBusItem[])__VA_ARGS__))
+#define Bus_BroadcastSend(name,...) _Bus_BroadcastSendMap((name),(sizeof((SoftBusItemX[])__VA_ARGS__)/sizeof(SoftBusItemX)),((SoftBusItemX[])__VA_ARGS__))
/*
- @brief ͨپ㲥б֡
- @param handle:پ
- @param ...:ָб
+ @brief 通过快速句柄广播列表数据帧
+ @param handle:快速句柄
+ @param ...:数据指针列表
@retval void
@example float value1,value2; Bus_FastBroadcastSend(handle, {&value1, &value2});
*/
#define Bus_FastBroadcastSend(handle,...) _Bus_BroadcastSendList((handle),(sizeof((void*[])__VA_ARGS__)/sizeof(void*)),((void*[])__VA_ARGS__))
/*
- @brief ϵһԶ̺
- @param callback:ӦԶ̺ʱĻص
- @param name:Զ̺
- @retval 0:ɹ -1:ѿռ䲻 -2:Ϊ -3:Զ̺Ѵ
- @note صʽӦΪbool callback(const char* name, SoftBusFrame* frame, void* bindData)
+ @brief 创建软总线上的一个远程函数
+ @param callback:响应远程函数时的回调函数
+ @param name:远程函数名
+ @retval 0:成功 -1:堆空间不足 -2:参数为空 -3:远程函数已存在
+ @note 回调函数的形式应为bool callback(const char* name, SoftBusFrame* frame, void* bindData)
*/
int8_t Bus_RegisterRemoteFunc(void* bindData, SoftBusRemoteFunction callback, const char* name);
/*
- @brief ͨӳ֡Զ̺
- @param name:Զ̺
- @param ...:Զ̺б(ͷֵ)
- @retval true:ɹ false:ʧ
- @example Bus_RemoteCall("name", {{"key1", data1}, {"key2", data2}});
+ @brief 通过映射表数据帧调用远程函数
+ @param name:远程函数名
+ @param ...:远程函数参数列表(包含参数和返回值)
+ @retval true:成功 false:失败
+ @example Bus_RemoteCall("name", {{"key1", {data1}}, {"key2", {data2}}});
*/
-#define Bus_RemoteCall(name,...) _Bus_RemoteCallMap((name),(sizeof((SoftBusItem[])__VA_ARGS__)/sizeof(SoftBusItem)),((SoftBusItem[])__VA_ARGS__))
+#define Bus_RemoteCall(name,...) _Bus_RemoteCallMap((name),(sizeof((SoftBusItemX[])__VA_ARGS__)/sizeof(SoftBusItemX)),((SoftBusItemX[])__VA_ARGS__))
/*
- @brief ӳ֡еֶ
- @param frame:ָ֡
- @param key:ֶε
- @retval ֶָָεconstָ,ѯkeyNULL
- @note ӦԷص֡
+ @brief 查找映射表数据帧中的数据字段
+ @param frame:数据帧的指针
+ @param key:数据字段的名字
+ @retval 指向指定数据字段的const指针,若查询不到key则返回NULL
+ @note 不应对返回的数据帧进行修改
*/
const SoftBusItem* Bus_GetMapItem(SoftBusFrame* frame, char* key);
/*
- @brief жӳ֡Ƿֶָ
- @param frame:ָ֡
- @param key:ֶε
- @retval 0: 1:
+ @brief 判断映射表数据帧中是否存在指定字段
+ @param frame:数据帧的指针
+ @param key:数据字段的名字
+ @retval 0:不存在 1:存在
*/
#define Bus_IsMapKeyExist(frame,key) (Bus_GetMapItem((frame),(key)) != NULL)
/*
- @brief жϸkeyбǷȫӳ֡
- @param frame:ָ֡
- @param ...:Ҫжϵkeyб
- @retval 0:һkey 1:key
+ @brief 判断给定key列表是否全部存在于映射表数据帧中
+ @param frame:数据帧的指针
+ @param ...:要判断的key列表
+ @retval 0:任意一个key不存在 1:所有key都存在
@example if(Bus_CheckMapKeys(frame, {"key1", "key2", "key3"})) { ... }
*/
#define Bus_CheckMapKeys(frame,...) _Bus_CheckMapKeys((frame),(sizeof((char*[])__VA_ARGS__)/sizeof(char*)),((char*[])__VA_ARGS__))
/*
- @brief ȡӳֶָ֡εֵ
- @param frame:ָ֡
- @param key:ֶε
- @retval ֵָ(void*)ָ
- @note ȷkey֡УӦؽӿڽм
- @note Ӧͨصָָ
+ @brief 获取映射表数据帧中指定字段的值
+ @param frame:数据帧的指针
+ @param key:数据字段的名字
+ @retval 指向值的(void*)型指针
+ @note 必须确保传入的key存在于数据帧中,应先用相关接口进行检查
+ @note 不应通过返回的指针修改指向的数据
@example float value = *(float*)Bus_GetMapValue(frame, "key");
*/
#define Bus_GetMapValue(frame,key) (Bus_GetMapItem((frame),(key))->data)
/*
- @brief ͨ㲥ٹ㲥
- @param name:㲥
- @retval Ŀپ
+ @brief 通过广播名创建快速广播句柄
+ @param name:广播名
+ @retval 创建出的快速句柄
@example SoftBusReceiverHandle handle = Bus_CreateReceiverHandle("name");
- @note ӦڳʼʱһΣÿηǰ
+ @note 应仅在程序初始化时创建一次,而不是每次发布前创建
*/
SoftBusReceiverHandle Bus_CreateReceiverHandle(const char* name);
/*
- @brief ȡбָ֡
- @param frame:ָ֡
- @param pos:беλ
- @retval ָݵ(void*)ָ룬NULL
- @note Ӧͨصָָ
- @example float value = *(float*)Bus_GetListValue(frame, 0); //ȡбеһֵ
+ @brief 获取列表数据帧中指定索引的数据
+ @param frame:数据帧的指针
+ @param pos:数据在列表中的位置
+ @retval 指向数据的(void*)型指针,若不存在则返回NULL
+ @note 不应通过返回的指针修改指向的数据
+ @example float value = *(float*)Bus_GetListValue(frame, 0); //获取列表中第一个值
*/
#define Bus_GetListValue(frame,pos) (((pos) < (frame)->size)?((void**)(frame)->data)[(pos)]:NULL)
diff --git a/test/cmsis_os.h b/test/cmsis_os.h
new file mode 100644
index 0000000000000000000000000000000000000000..4942798a8038de75978cc5a5b24ff7899926fb8a
--- /dev/null
+++ b/test/cmsis_os.h
@@ -0,0 +1,6 @@
+
+// 假的CMSIS OS/FreeRTOS API,为测试而生。
+
+#include
+#define pvPortMalloc malloc
+#define vPortFree free
diff --git a/test/main.cpp b/test/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..15220fc0bcb03235c8452bcb609f1bbc1ab16d87
--- /dev/null
+++ b/test/main.cpp
@@ -0,0 +1,9 @@
+
+#include "tests.hpp"
+
+#include
+#include
+
+int main() {
+ TestYamlParser();
+}
diff --git a/test/tests.hpp b/test/tests.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..16c6c4b51d1b0ab51b988977112be96061071578
--- /dev/null
+++ b/test/tests.hpp
@@ -0,0 +1,2 @@
+
+void TestYamlParser();
diff --git a/test/yamlparsertest.cpp b/test/yamlparsertest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5a360b598779934c8cd7875779bdba8486ddfb07
--- /dev/null
+++ b/test/yamlparsertest.cpp
@@ -0,0 +1,85 @@
+
+#include "../conf/yamlparser.h"
+#include
+#include
+
+constexpr const char* yaml_simple =
+R"(
+sys:
+ rotate-pid:
+ p: 1.5
+ i: 0.0
+ d: 0.0
+ max-i: 100.0
+ max-out: 200.0
+
+chassis:
+ task-interval: 2
+ info:
+ wheelbase: 100.0 #这里是注释
+ wheeltrack: 100.0
+ wheel-radius: 76.0
+ offset-x: 0.0
+ offset-y: 0.0
+ #ThisIsAComment: 0
+ move:
+ max-vx: 2000.0
+ max-vy: 2000.0
+
+testcase:
+ minus:
+ int: -65537
+ float: -123.456
+ positive:
+ int: 65536
+ float: 12.3456
+ string:
+ hello: "world"
+)";
+
+template bool CompareYamlValue(UimlYamlNode* node, T value) {
+ return !memcmp(&(node->I32), &value, sizeof(T));
+}
+template <> bool CompareYamlValue(UimlYamlNode* node, const char* value) {
+ return !strcmp(node->Str, value);
+}
+template <> bool CompareYamlValue(UimlYamlNode* node, float value) {
+ return (node->F32 - value <= 1e-6);
+}
+template <> bool CompareYamlValue(UimlYamlNode* node, double value) {
+ return (node->F32 - value <= 1e-6);
+}
+
+template void AssertYamlValue(UimlYamlNode* root, const char* path, T value) {
+ auto node = UimlYamlGetValueByPath(root, path);
+ if (node == NULL) {
+ std::cerr << "FAIL: Requested value of \"" << path << "\" but the item does not exist!\n";
+ return;
+ }
+ if (!CompareYamlValue(node, value)) {
+ std::cerr << "FAIL: Value of \"" << path << "\" expected: " << value << ", got: " << *reinterpret_cast(&(node->I32)) << '\n';
+ }
+}
+
+void TestYamlParser() {
+ UimlYamlNode* root;
+
+ UimlYamlParse(yaml_simple, &root);
+ auto pChassis = UimlYamlGetValue(root->Children, "chassis");
+ auto pInfo = UimlYamlGetValue(pChassis->Children, "info");
+ auto pOffsetX = UimlYamlGetValue(pInfo->Children, "wheel-radius");
+
+ std::cerr << "YAML test didn't crash." << std::endl;
+
+ AssertYamlValue(root, "/chassis/info/wheel-radius", 76.0);
+ AssertYamlValue(root, "/testcase/minus/int", -65537);
+ AssertYamlValue(root, "/testcase/minus/float", -123.456);
+ AssertYamlValue(root, "/testcase/positive/int", 65536);
+ AssertYamlValue(root, "/testcase/positive/float", 12.3456);
+ AssertYamlValue(root, "/testcase/string/hello", "world");
+
+ std::cerr << "chassis.info.wheel-radius: " << pOffsetX->F32 << std::endl;
+
+ std::cerr << "Comment test: " << UimlYamlGetValueByPath(root, "/chassis/#ThisIsAComment") << std::endl;
+
+}
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..382ce57a14cac7685417a17b8f259424b3126ac3
--- /dev/null
+++ b/tools/CMakeLists.txt
@@ -0,0 +1,9 @@
+
+# 递归获取所有源码文件
+file(GLOB_RECURSE TOOLS_SRC *.c)
+
+# 传递源码文件到上一级 CMakeLists 作用域
+set(TOOLS_MODULE_SRC ${TOOLS_SRC} PARENT_SCOPE)
+
+# 添加 include 目录
+set(TOOLS_MODULE_INCL ${CMAKE_CURRENT_LIST_DIR}/include PARENT_SCOPE)
diff --git a/tools/controller/pid.c b/tools/controller/pid.c
deleted file mode 100644
index cc5682e9a31e6616bed1e0091c3781cc15284bb0..0000000000000000000000000000000000000000
--- a/tools/controller/pid.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/****************PID****************/
-
-#include "pid.h"
-
-//ʼpid
-void PID_Init(PID *pid, ConfItem* conf)
-{
- pid->kp=Conf_GetValue(conf, "p", float, 0);
- pid->ki=Conf_GetValue(conf, "i", float, 0);
- pid->kd=Conf_GetValue(conf, "d", float, 0);
- pid->maxIntegral=Conf_GetValue(conf, "max-i", float, 0);
- pid->maxOutput=Conf_GetValue(conf, "max-out", float, 0);
- pid->deadzone=0;
-}
-
-//pid
-void PID_SingleCalc(PID *pid,float reference,float feedback)
-{
- //
- pid->lastError=pid->error;
- if(ABS(reference-feedback) < pid->deadzone)//errorֱ0
- pid->error=0;
- else
- pid->error=reference-feedback;
- //
- pid->output=(pid->error-pid->lastError)*pid->kd;
- //
- pid->output+=pid->error*pid->kp;
- //
- pid->integral+=pid->error*pid->ki;
- LIMIT(pid->integral,-pid->maxIntegral,pid->maxIntegral);//
- pid->output+=pid->integral;
- //
- LIMIT(pid->output,-pid->maxOutput,pid->maxOutput);
-}
-
-//pid
-void PID_CascadeCalc(CascadePID *pid,float angleRef,float angleFdb,float speedFdb)
-{
- PID_SingleCalc(&pid->outer,angleRef,angleFdb);//(ǶȻ)
- PID_SingleCalc(&pid->inner,pid->outer.output,speedFdb);//ڻ(ٶȻ)
- pid->output=pid->inner.output;
-}
-
-//һpidʷ
-void PID_Clear(PID *pid)
-{
- pid->error=0;
- pid->lastError=0;
- pid->integral=0;
- pid->output=0;
-}
-
-//趨pid
-void PID_SetMaxOutput(PID *pid,float maxOut)
-{
- pid->maxOutput=maxOut;
-}
-
-//PID
-void PID_SetDeadzone(PID *pid,float deadzone)
-{
- pid->deadzone=deadzone;
-}
diff --git a/tools/controller/pid.cpp b/tools/controller/pid.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..75d03ebf47fbefcccd098b151750d1d933c0338a
--- /dev/null
+++ b/tools/controller/pid.cpp
@@ -0,0 +1,112 @@
+/****************PID运算****************/
+
+#include "../include/pid.h"
+
+
+//初始化pid参数
+PID::PID(ConfItem* conf) :
+ kp(Conf_GetValue(conf, "p", float, 0)),
+ ki(ki=Conf_GetValue(conf, "i", float, 0)),
+ kd(Conf_GetValue(conf, "d", float, 0)),
+ maxIntegral(Conf_GetValue(conf, "max-i", float, 0)),
+ maxOutput(Conf_GetValue(conf, "max-out", float, 0)),
+ deadzone(0)
+{
+
+}
+
+//单级pid计算
+void PID::SingleCalc(float reference, float feedback)
+{
+ //更新数据
+ lastError = error;
+ if(ABS(reference - feedback) < deadzone)//若误差在死区内则error直接置0
+ error = 0;
+ else
+ error = reference - feedback;
+ //计算微分
+ output = (error - lastError) * kd;
+ //计算比例
+ output += error * kp;
+ //计算积分
+ integral += error * ki;
+ LIMIT(integral, -maxIntegral, maxIntegral);//积分限幅
+ output += integral;
+ //输出限幅
+ LIMIT(output, -maxOutput, maxOutput);
+}
+
+//前馈pid计算
+/*
+当逻辑不复杂,没必要或不想给函数起名的时候,我们会推荐用Lambda表达式来代替函数指针Lambda表达式的结构
+[capture-list] (params) -> ret(optional) { body }
+captures: 捕捉子句,作用是捕捉外部变量
+[],啥都不捕捉,也就是Lambda表达式body中不能出现没在body中声明的变量
+[=],按值捕捉所有变里,也就是lambda表达式前的所有变里,都可以以值传递(拷贝)的方式出现在body中(性能问题,不建议使用)
+[&],按引用捕捉所有变量,也就是Lambda表达式前的所有变量,都可以以引用传递的方式出现在body中(性能问题,不建议使用)
+[&a],按引用捕捉变量a,按值捕捉其他变量
+[&,a],按值捕捉变量a,按引用捕捉其他变量
+[=,a],[&,&a]这样的写法是错误的
+params: 和普通函数一样的参数(设置本地参数)
+ret: 返回值类型,也可以省略,让编译器通过 return 语句自动推导
+body: 函数的具体逻辑
+样例:
+ [] (int a) ->float { return (a * 10);};
+ a * 10可以改成自己所需要的数学模型,然后将lambda表达式整体传入FeedbackCalc函数中,
+*/
+void PID::FeedbackCalc(float reference, float feedback, const std::function& lambda)
+{
+ //更新数据
+ lastError = error;
+ if(ABS(reference - feedback) < deadzone)//若误差在死区内则error直接置0
+ error = 0;
+ else
+ error = reference - feedback;
+ //计算微分
+ output = (error - lastError) * kd;
+ //计算比例
+ output += error * kp;
+ //计算积分
+ integral += error * ki;
+ LIMIT(integral, -maxIntegral, maxIntegral);//积分限幅
+ output += integral;
+ //加入前馈
+ output += lambda(reference);
+ //输出限幅
+ LIMIT(output, -maxOutput, maxOutput);
+}
+
+//串级pid计算
+void CascadePID::CascadeCalc(float angleRef,float angleFdb,float speedFdb)
+{
+ outer.SingleCalc(angleRef, angleFdb);//计算外环(角度环)
+ inner.SingleCalc(outer.output, speedFdb);//计算内环(速度环)
+ output = inner.output;
+}
+
+//清空一个pid的历史数据
+void PID::Clear()
+{
+ error = 0;
+ lastError = 0;
+ integral = 0;
+ output = 0;
+}
+
+//重新设定pid输出限幅
+void PID::SetMaxOutput(float maxOutput)
+{
+ this->maxOutput = maxOutput;
+}
+
+void PID::SetMaxIntegral(float maxIntegral)
+{
+ this->maxIntegral = maxIntegral;
+}
+
+//设置PID死区
+void PID::SetDeadzone(float deadzone)
+{
+ this->deadzone = deadzone;
+}
+
diff --git a/tools/controller/pid.h b/tools/controller/pid.h
deleted file mode 100644
index 7226ec93100e6a3fa4ad0003f22a27689be1b1d7..0000000000000000000000000000000000000000
--- a/tools/controller/pid.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _USER_PID_H_
-#define _USER_PID_H_
-
-#include "config.h"
-
-#ifndef LIMIT
-#define LIMIT(x,min,max) (x)=(((x)<=(min))?(min):(((x)>=(max))?(max):(x)))
-#endif
-
-#ifndef ABS
-#define ABS(x) ((x)>=0?(x):-(x))
-#endif
-
-typedef struct _PID
-{
- float kp,ki,kd;
- float error,lastError;//ϴ
- float integral,maxIntegral;//֡
- float output,maxOutput;//
- float deadzone;//
-}PID;
-
-typedef struct _CascadePID
-{
- PID inner;//ڻ
- PID outer;//
- float output;//inner.output
-}CascadePID;
-
-void PID_Init(PID *pid, ConfItem* conf);
-void PID_SingleCalc(PID *pid,float reference,float feedback);
-void PID_CascadeCalc(CascadePID *pid,float angleRef,float angleFdb,float speedFdb);
-void PID_Clear(PID *pid);
-void PID_SetMaxOutput(PID *pid,float maxOut);
-void PID_SetDeadzone(PID *pid,float deadzone);
-
-#endif
diff --git a/tools/crc/crc16_modbus.c b/tools/crc/crc16_modbus.c
index 9fa160d047ec192be21806c0b8b27db828508886..e43bb250d354b353e87fc9ba896e9e4d24c2d9b1 100644
--- a/tools/crc/crc16_modbus.c
+++ b/tools/crc/crc16_modbus.c
@@ -1,7 +1,7 @@
-#include "crc_modbus.h"
+#include "crc16_modbus.h"
#include
-const uint8_t auchCRCHi[] = /* Table of CRC values for highCorder byte */
+const uint8_t auchCRCHi[] = /* Table of CRC values for high¨Corder byte */
{
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
@@ -21,7 +21,7 @@ const uint8_t auchCRCHi[] = /* Table of CRC values for high
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
-const uint8_t auchCRCLo[] = /* Table of CRC values for lowCorder byte */
+const uint8_t auchCRCLo[] = /* Table of CRC values for low¨Corder byte */
{
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC,
0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8,
@@ -42,7 +42,7 @@ const uint8_t auchCRCLo[] = /* Table of CRC values for low
} ;
/******************************************************************************
- CRC
+ CRC计算
*******************************************************************************/
uint16_t CRC_Calculate(uint8_t *pdata, uint8_t num)
{
diff --git a/tools/first_order_filter/filter.c b/tools/first_order_filter/filter.c
index 48e1ee1cc4e64354569af7acec62f4eb09bb57f1..b84bc43266ef5f262be8425a45b89add38f94f67 100644
--- a/tools/first_order_filter/filter.c
+++ b/tools/first_order_filter/filter.c
@@ -1,18 +1,18 @@
#include "filter.h"
//X-MACRO
-//бÿһʽΪ(,ʼ)
+//子类列表,每一项格式为(类型名,初始化函数名)
#define FILTER_CHILD_LIST \
FILTER_TYPE("kalman",Kalman_Init) \
FILTER_TYPE("mean",Mean_Init) \
FILTER_TYPE("low-pass",LowPass_Init)
-//ʼ
+//声明子类初始化函数
#define FILTER_TYPE(name,initFunc) extern Filter* initFunc(ConfItem*);
FILTER_CHILD_LIST
#undef FILTER_TYPE
-//ڲ
+//内部函数声明
void Filter_InitDefault(Filter* filter);
float Filter_Cala(Filter *filter, float data);
@@ -21,7 +21,7 @@ Filter* Filter_Init(ConfItem* dict)
char* filterType = Conf_GetPtr(dict, "type", char);
Filter *filter = NULL;
- //жĸ
+ //判断属于哪个子类
#define FILTER_TYPE(name,initFunc) \
if(!strcmp(filterType, name)) \
filter = initFunc(dict);
@@ -30,7 +30,7 @@ Filter* Filter_Init(ConfItem* dict)
if(!filter)
filter = FILTER_MALLOC_PORT(sizeof(Filter));
- //δķΪպ
+ //将子类未定义的方法设置为空函数
Filter_InitDefault(filter);
return filter;
@@ -42,5 +42,5 @@ void Filter_InitDefault(Filter* filter)
filter->cala = Filter_Cala;
}
-//麯
+//纯虚函数
float Filter_Cala(Filter *filter, float data) {return 0;}
diff --git a/tools/first_order_filter/kalman.c b/tools/first_order_filter/kalman.c
index a27306a5cb6a92820dd65885a0e7ca061b547d55..cd757a710bddd9ac5977889698d220440c40cb3b 100644
--- a/tools/first_order_filter/kalman.c
+++ b/tools/first_order_filter/kalman.c
@@ -1,17 +1,17 @@
#include "filter.h"
-//һ˲ṹ
+//一阶卡尔曼滤波结构体
typedef struct
{
Filter filter;
- float xLast; //һʱ̵Ž X(k|k-1)
- float xPre; //ǰʱ̵Ԥ X(k|k-1)
- float xNow; //ǰʱ̵Ž X(k|k)
- float pPre; //ǰʱԤЭ P(k|k-1)
- float pNow; //ǰʱŽЭ P(k|k)
- float pLast; //һʱŽЭ P(k-1|k-1)
- float kg; //kalman
+ float xLast; //上一时刻的最优结果 X(k|k-1)
+ float xPre; //当前时刻的预测结果 X(k|k-1)
+ float xNow; //当前时刻的最优结果 X(k|k)
+ float pPre; //当前时刻预测结果的协方差 P(k|k-1)
+ float pNow; //当前时刻最优结果的协方差 P(k|k)
+ float pLast; //上一时刻最优结果的协方差 P(k-1|k-1)
+ float kg; //kalman增益
float Q;
float R;
}KalmanFilter;
@@ -21,13 +21,13 @@ Filter* Kalman_Init(ConfItem* dict);
float Kalman_Cala(Filter* filter, float data);
/**
- * @brief ʼһ˲
- * @param kalman: ˲
- * @param T_Q:ϵͳЭ
- * @param T_R:Э
+ * @brief 初始化一个卡尔曼滤波器
+ * @param kalman: 滤波器
+ * @param T_Q:系统噪声协方差
+ * @param T_R:测量噪声协方差
* @retval None
- * @attention R̶QԽԽβֵQֻòֵ
- * ֮QԽСԽģԤֵQΪֻģԤ
+ * @attention R固定,Q越大,代表越信任侧量值,Q无穷代表只用测量值
+ * 反之,Q越小代表越信任模型预测值,Q为零则是只用模型预测
*/
Filter* Kalman_Init(ConfItem* dict)
{
@@ -45,14 +45,14 @@ Filter* Kalman_Init(ConfItem* dict)
/**
- * @brief ˲
- * @param kalman: ˲
- * @param data:˲
- * @retval ˲
- * @attention Z(k)ϵͳ,ֵ X(k|k)ǿ˲ֵ,
- * A=1 B=0 H=1 I=1 W(K) V(k)Ǹ˹,ڲֵ,Բù
- * ǿ5Ĺʽ
- * һH'Ϊ,Ϊתþ
+ * @brief 卡尔曼滤波器
+ * @param kalman: 滤波器
+ * @param data:待滤波数据
+ * @retval 滤波后的数据
+ * @attention Z(k)是系统输入,即测量值 X(k|k)是卡尔曼滤波后的值,即最终输出
+ * A=1 B=0 H=1 I=1 W(K) V(k)是高斯白噪声,叠加在测量值上了,可以不用管
+ * 以下是卡尔曼的5个核心公式
+ * 一阶H'即为它本身,否则为转置矩阵
*/
float Kalman_Cala(Filter* filter, float data)
{
@@ -63,7 +63,7 @@ float Kalman_Cala(Filter* filter, float data)
kalman->kg = kalman->pPre / (kalman->pPre + kalman->R); //kg(k) = p(k|k-1)*H'/(H*p(k|k-1)*H'+R)
kalman->xNow = kalman->xPre + kalman->kg * (data - kalman->xPre); //x(k|k) = X(k|k-1)+kg(k)*(Z(k)-H*X(k|k-1))
kalman->pNow = (1 - kalman->kg) * kalman->pPre; //p(k|k) = (I-kg(k)*H)*P(k|k-1)
- kalman->pLast = kalman->pNow; //״̬
- kalman->xLast = kalman->xNow; //״̬
- return kalman->xNow; //Ԥx(k|k)
+ kalman->pLast = kalman->pNow; //状态更新
+ kalman->xLast = kalman->xNow; //状态更新
+ return kalman->xNow; //输出预测结果x(k|k)
}
diff --git a/tools/first_order_filter/low_pass.c b/tools/first_order_filter/low_pass.c
index f079edfebaa5d8f5fb3edb1d648cc746fc1aecd0..6500c04d6a6e696c0d6a1e43cfca6a2e31333a24 100644
--- a/tools/first_order_filter/low_pass.c
+++ b/tools/first_order_filter/low_pass.c
@@ -1,5 +1,5 @@
#include "filter.h"
-//ͨ˲ṹ
+//低通滤波结构体
typedef struct
{
Filter filter;
diff --git a/tools/first_order_filter/mean.c b/tools/first_order_filter/mean.c
index 4dc379f926dcbd19bde2d4ca1602f20b73e83e06..980e70e61ff6eb04ea34f5aa140cedc84d95e056 100644
--- a/tools/first_order_filter/mean.c
+++ b/tools/first_order_filter/mean.c
@@ -1,6 +1,6 @@
#include "filter.h"
-//ֵ˲ṹ
+//均值滤波结构体
typedef struct
{
Filter filter;
@@ -14,10 +14,10 @@ typedef struct
float Mean_Cala(Filter* filter, float data);
/**
- * @brief ʼһֵ˲
- * @param ˲ṹ
- * @param Ҫ˲ṹ
- * @param ˲С˲ڲڴ洢ݵĴС
+ * @brief 初始化一个均值滤波器
+ * @param 滤波器结构体
+ * @param 需要关联到滤波器结构体的数组
+ * @param 滤波器缓存区大小(滤波器内部用于存储数据的数组的大小)
* @retval None
*/
Filter* Mean_Init(ConfItem* dict)
@@ -36,9 +36,9 @@ Filter* Mean_Init(ConfItem* dict)
}
/**
- * @brief ֵ˲
- * @param ˲ṹ壬Ҫ˲
- * @retval ˲
+ * @brief 均值滤波函数
+ * @param 滤波器结构体,需要滤波的数据
+ * @retval 滤波输出量
* @attention None
*/
float Mean_Cala(Filter* filter, float data)
diff --git a/tools/hasher/hasher.c b/tools/hasher/hasher.c
new file mode 100644
index 0000000000000000000000000000000000000000..d3c315f643fad6463bbc29fe2c633742cb5fddab
--- /dev/null
+++ b/tools/hasher/hasher.c
@@ -0,0 +1,25 @@
+
+#include "hasher.h"
+#include
+
+uint32_t Hasher_UIML32(const uint8_t *data, size_t length)
+{
+ uint32_t h = 0;
+ uint16_t strLength = length, alignedLen = strLength / sizeof(uint32_t);
+ for(uint16_t i = 0; i < alignedLen; ++i)
+ h = (h << 5) - h + ((uint32_t*)data)[i];
+ for(uint16_t i = alignedLen << 2; i < strLength; ++i)
+ h = (h << 5) - h + data[i];
+ return h;
+}
+
+uint32_t Hasher_FNV1A(const uint8_t *data, size_t length)
+{
+ uint32_t prime = 16777619U;
+ uint32_t ret = 2166136261U;
+ for (size_t i = 0; i < length; i++) {
+ ret ^= (uint32_t)(data[i]);
+ ret *= prime;
+ }
+ return ret;
+}
diff --git a/tools/crc/crc16_modbus.h b/tools/include/crc16_modbus.h
similarity index 100%
rename from tools/crc/crc16_modbus.h
rename to tools/include/crc16_modbus.h
diff --git a/tools/crc/crc_dji.h b/tools/include/crc_dji.h
similarity index 100%
rename from tools/crc/crc_dji.h
rename to tools/include/crc_dji.h
diff --git a/tools/first_order_filter/filter.h b/tools/include/filter.h
similarity index 94%
rename from tools/first_order_filter/filter.h
rename to tools/include/filter.h
index 0f7c347a8ffe49559de31ac47d28808ffc115704..d4cd489effd105a3289e3fa4b79b637658a8859c 100644
--- a/tools/first_order_filter/filter.h
+++ b/tools/include/filter.h
@@ -3,6 +3,7 @@
#include "config.h"
#include "cmsis_os.h"
+#include
#define FILTER_MALLOC_PORT(len) pvPortMalloc(len)
#define FILTER_FREE_PORT(ptr) vPortFree(ptr)
diff --git a/tools/include/hasher.h b/tools/include/hasher.h
new file mode 100644
index 0000000000000000000000000000000000000000..4d9502f82c5a65982537198183865dad6a62bf0a
--- /dev/null
+++ b/tools/include/hasher.h
@@ -0,0 +1,13 @@
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+uint32_t Hasher_UIML32(const uint8_t* data, size_t length);
+uint32_t Hasher_FNV1A(const uint8_t* data, size_t length);
+
+#ifdef __cplusplus
+} // extern "C" {
+#endif
diff --git a/tools/motor/motor.h b/tools/include/motor.h
similarity index 85%
rename from tools/motor/motor.h
rename to tools/include/motor.h
index 9eb7d17a1314334eb8fa2bc048453d1f52b232e2..8abf0162ca24fa4fccd351c17bd48ba00c25432b 100644
--- a/tools/motor/motor.h
+++ b/tools/include/motor.h
@@ -2,10 +2,13 @@
#define _MOTOR_H_
#include "config.h"
#include "cmsis_os.h"
+#include
+#include
+#include
#define MOTOR_MALLOC_PORT(len) pvPortMalloc(len)
#define MOTOR_FREE_PORT(ptr) vPortFree(ptr)
-//ģʽ
+//模式
typedef enum
{
MOTOR_TORQUE_MODE,
@@ -13,7 +16,7 @@ typedef enum
MOTOR_ANGLE_MODE,
MOTOR_STOP_MODE
}MotorCtrlMode;
-//࣬ķ
+//父类,包含所有子类的方法
typedef struct _Motor
{
void (*changeMode)(struct _Motor* motor, MotorCtrlMode mode);
diff --git a/tools/universal_queue/my_queue.h b/tools/include/my_queue.h
similarity index 69%
rename from tools/universal_queue/my_queue.h
rename to tools/include/my_queue.h
index 7686497ce976fb151a5889cd5c5fce51b6bd686a..a30027f50a685e885a7d04995bc11fe018a68451 100644
--- a/tools/universal_queue/my_queue.h
+++ b/tools/include/my_queue.h
@@ -5,21 +5,21 @@
#define EMPTY_QUEUE {NULL,0,0,0,NULL,0}
-/*************ݽṹ**************/
-//нṹ
+/*************数据结构**************/
+//队列结构体
typedef struct _Queue
{
- //
- void **data;//ָֻ룬Ҫͬʱָ븽ӱ
+ //队列数据
+ void **data;//只保存指针,若要同时保存指向的数据请附加保存区
uint16_t maxSize;
uint16_t front,rear;
uint8_t initialized;
- //ݱ(ѡ)
+ //数据保存区(可选用)
void *buffer;
- uint8_t bufElemSize;//ÿԪصĴС
+ uint8_t bufElemSize;//每个元素的大小
}Queue;
-/**************ӿں***************/
+/**************接口函数***************/
void Queue_Init(Queue *queue,uint16_t maxSize);
void Queue_AttachBuffer(Queue *queue,void *buffer,uint8_t elemSize);
void Queue_Destroy(Queue *queue);
diff --git a/tools/include/pid.h b/tools/include/pid.h
new file mode 100644
index 0000000000000000000000000000000000000000..53a2355a9dc30d48562e95cdeba08c8560711e1d
--- /dev/null
+++ b/tools/include/pid.h
@@ -0,0 +1,45 @@
+#ifndef _USER_PID_H_
+#define _USER_PID_H_
+
+#include "../../conf/config.h"
+
+#include
+
+#ifndef LIMIT
+#define LIMIT(x,min,max) (x)=(((x)<=(min))?(min):(((x)>=(max))?(max):(x)))
+#endif
+
+#ifndef ABS
+#define ABS(x) ((x)>=0?(x):-(x))
+#endif
+
+class PID
+{
+public:
+ float kp,ki,kd;
+ float error,lastError;//误差、上次误差
+ float integral,maxIntegral;//积分、积分限幅
+ float output,maxOutput;//输出、输出限幅
+ float deadzone;//死区
+
+ PID(ConfItem* conf);
+ void SingleCalc(float reference,float feedback);
+ void FeedbackCalc(float reference, float feedback, const std::function& lambda);
+ void Clear();
+ void SetMaxOutput(float maxOutput);
+ void SetMaxIntegral(float maxIntegral);
+ void SetDeadzone(float deadzone);
+};
+
+class CascadePID
+{
+public:
+ PID inner;//内环
+ PID outer;//外环
+ float output;//串级输出,等于inner.output
+
+ void CascadeCalc(float angleRef,float angleFdb,float speedFdb);
+};
+
+
+#endif
diff --git a/tools/slope/slope.h b/tools/include/slope.h
similarity index 67%
rename from tools/slope/slope.h
rename to tools/include/slope.h
index 5971eb2359f680fa0ae66014ebc865cac27b2ecc..5b1ff31e29b48e704fb274cef9ed8bace0e7cc52 100644
--- a/tools/slope/slope.h
+++ b/tools/include/slope.h
@@ -5,12 +5,12 @@
#define ABS(x) ((x)>=0?(x):-(x))
#endif
-//б½ṹ
+//斜坡结构体
typedef struct{
- float target; //Ŀֵ
- float step; //ֵ
- float value; //ǰֵ
- float deadzone; //ֵСڸֵ
+ float target; //目标值
+ float step; //步进值
+ float value; //当前值
+ float deadzone; //死区,若差值小于该值则不进行增减
}Slope;
void Slope_Init(Slope *slope,float step,float deadzone);
diff --git a/tools/universal_vector/vector.h b/tools/include/vector.h
similarity index 40%
rename from tools/universal_vector/vector.h
rename to tools/include/vector.h
index 6541324afc8b26155d2d36a6ad8f1ec228b7aa43..f317081b21a2101d2850f9fefa6735f883d29e78 100644
--- a/tools/universal_vector/vector.h
+++ b/tools/include/vector.h
@@ -1,18 +1,18 @@
-/* CԵͨͶ̬ģ飬C++еSTLģvector */
+/* 用于C语言的通用类型动态数组模块,类似于C++中的STL模板库vector */
#ifndef _VECTOR_H_
#define _VECTOR_H_
#include
-//Vectorݽṹ
+//Vector数据结构体
typedef struct{
uint8_t *data;
uint8_t elementSize;
uint32_t size,capacity;
}Vector;
-//(ֱӵãӦʹ·defineĽӿ)
+//操作函数声明(不直接调用,应使用下方define定义的接口)
int _Vector_Init(Vector *vector,int _elementSize);
Vector _Vector_Create(int _elementSize);
void _Vector_Destroy(Vector *vector);
@@ -23,154 +23,154 @@ int _Vector_SetValue(Vector *vector, uint32_t index, void *element);
int _Vector_TrimCapacity(Vector *vector);
/*
- @brief ʼһָ͵Vector
- @param vector:ҪʼVector
- type:VectorнŵԪ
- @retval 0:ɹ -1:ʧ
+ @brief 初始化一个指定类型的Vector
+ @param vector:需要初始化的Vector对象
+ type:该Vector中将会存放的元素类型
+ @retval 0:成功 -1:失败
*/
#define Vector_Init(vector,type) (_Vector_Init(&(vector),sizeof(type)))
/*
- @brief һָ͵Vector
- @param type:VectorнŵԪ
- @retval ѳʼõVector (ڴʧdata=NULL)
+ @brief 创建一个指定类型的Vector
+ @param type:该Vector中将会存放的元素类型
+ @retval 已初始化好的Vector对象 (若内存分配失败则其中data=NULL)
*/
#define Vector_Create(type) (_Vector_Create(sizeof(type)))
/*
- @brief һVector
- @param vector:ҪٵVector
+ @brief 销毁一个Vector
+ @param vector:需要销毁的Vector
@retval void
*/
#define Vector_Destroy(vector) (_Vector_Destroy(&(vector)))
/*
- @brief ȡѲԪ
- @param vector:ĿVector
- @retval vectorеԪ
+ @brief 获取已插入的元素数量
+ @param vector:目标Vector对象
+ @retval 该vector中的元素数量
*/
#define Vector_Size(vector) ((vector).size)
/*
- @brief ȡǰѷ
- @param vector:ĿVector
- @retval ΪvectorĿռܴ洢Ԫ
+ @brief 获取当前已分配的容量
+ @param vector:目标Vector对象
+ @retval 已为该vector分配的空间所能存储的元素数量
*/
#define Vector_Capacity(vector) ((vector).capacity)
/*
- @brief ɾ
- @param vector:ĿVector
- @retval 0:ɹ -1:ʧ
+ @brief 删除空余容量
+ @param vector:目标Vector对象
+ @retval 0:成功 -1:失败
*/
#define Vector_TrimCapacity(vector) (_Vector_TrimCapacity(&(vector)))
/*
- @brief VectorתΪԪ
- @param vector:Ŀvector
- type:Ԫ
- @retval type*͵ָ룬ֱַָΪʹ
+ @brief 将Vector转为元素数组
+ @param vector:目标vector对象
+ type:元素类型
+ @retval type*类型的指针,指向数据首地址,可直接作为数组名使用
@example int num = Vector_ToArray(vector,int)[0];
*/
#define Vector_ToArray(vector,type) ((type*)((vector).data))
/*
- @brief ȡָ±괦Ԫصָ
- @param vector:Ŀvector
- index:ָ±
- type:Ԫ
- @retval ָָ±괦Ԫص(type*)ָ룬±겻NULL
+ @brief 获取指定下标处元素的指针
+ @param vector:目标vector对象
+ index:指定的下标
+ type:元素类型
+ @retval 指向指定下标处元素的(type*)型指针,若下标不存在则返回NULL
*/
#define Vector_GetByIndex(vector,index,type) ((type*)_Vector_GetByIndex(&(vector),(index)))
/*
- @brief ȡԪָ
- @param vector:Ŀvector
- type:Ԫ
- @retval ָԪص(type*)ָ룬NULL
+ @brief 获取首元素指针
+ @param vector:目标vector对象
+ type:元素类型
+ @retval 指向首元素的(type*)型指针,若不存在则返回NULL
*/
#define Vector_GetFront(vector,type) Vector_GetByIndex(vector,0,type)
/*
- @brief ȡβԪָ
- @param vector:Ŀvector
- type:Ԫ
- @retval ָβԪص(type*)ָ룬NULL
+ @brief 获取尾元素指针
+ @param vector:目标vector对象
+ type:元素类型
+ @retval 指向尾元素的(type*)型指针,若不存在则返回NULL
*/
#define Vector_GetBack(vector,type) Vector_GetByIndex(vector,(vector).size-1,type)
/*
- @brief ָ±ֵ
- @param vector:Ŀvector
- index:ָ±
- val:Ҫĵֵ
- @retval 0:ɹ -1:ʧ
- @notice ϣvalӦʹ紫100Ӧд"(int){100}"
+ @brief 修改指定下标的值
+ @param vector:目标vector对象
+ index:指定的下标
+ val:需要修改的新值
+ @retval 0:成功 -1:失败
+ @notice 若希望在val处传入立即数则应使用字面量,如传入100应写"(int){100}"
*/
#define Vector_SetValue(vector,index,val) (_Vector_SetValue(&(vector),(index),&(val)))
/*
- @brief ɾָ±Ԫ
- @param vector:Ҫvector
- index:ָ±
- @retval 0:ɹ -1:ʧ
+ @brief 删除指定下标的元素
+ @param vector:要操作的vector对象
+ index:指定的下标
+ @retval 0:成功 -1:失败
*/
#define Vector_Remove(vector,index) (_Vector_Remove(&(vector),(index)))
/*
- @brief ɾβԪ
- @param vector:Ҫvector
- @retval 0:ɹ -1:ʧ
+ @brief 删除尾元素
+ @param vector:要操作的vector对象
+ @retval 0:成功 -1:失败
*/
#define Vector_PopBack(vector) Vector_Remove(vector,(vector).size-1)
/*
- @brief ɾԪ
- @param vector:Ҫvector
- @retval 0:ɹ -1:ʧ
+ @brief 删除首元素
+ @param vector:要操作的vector对象
+ @retval 0:成功 -1:失败
*/
#define Vector_PopFront(vector) Vector_Remove(vector,0)
/*
- @brief ɾԪ
- @param vector:Ҫvector
+ @brief 删除所有元素
+ @param vector:要操作的vector对象
@retval 0
*/
#define Vector_Clear(vector) ((vector).size=0)
/*
- @brief ָ±괦Ԫأ±괦ԭԪؼԪƶ
- @param vector:Ŀvector
- index:ָ±
- val:Ҫֵ
- @retval 0:ɹ -1:ʧ
- @notice ϣvalӦʹ紫100Ӧд"(int){100}"
+ @brief 在指定下标处插入元素,该下标处原有元素及其后续元素向后移动
+ @param vector:目标vector对象
+ index:指定的下标
+ val:需要插入的值
+ @retval 0:成功 -1:失败
+ @notice 若希望在val处传入立即数则应使用字面量,如传入100应写"(int){100}"
*/
#define Vector_Insert(vector,index,val) (_Vector_Insert(&(vector),(index),&(val)))
/*
- @brief βԪ
- @param vector:Ŀvector
- val:Ҫֵ
- @retval 0:ɹ -1:ʧ
- @notice ϣvalӦʹ紫100Ӧд"(int){100}"
+ @brief 在尾部插入元素
+ @param vector:目标vector对象
+ val:需要插入的值
+ @retval 0:成功 -1:失败
+ @notice 若希望在val处传入立即数则应使用字面量,如传入100应写"(int){100}"
*/
#define Vector_PushBack(vector,val) Vector_Insert(vector,(vector).size,(val))
/*
- @brief ͷԪ
- @param vector:Ŀvector
- val:Ҫֵ
- @retval 0:ɹ -1:ʧ
- @notice ϣvalӦʹ紫100Ӧд"(int){100}"
+ @brief 在头部插入元素
+ @param vector:目标vector对象
+ val:需要插入的值
+ @retval 0:成功 -1:失败
+ @notice 若希望在val处传入立即数则应使用字面量,如传入100应写"(int){100}"
*/
#define Vector_PushFront(vector,val) Vector_Insert(vector,0,(val))
/*
- @brief 䣬еfor
- @param vector:Ŀvector
- iter:ʱıָԪص(type*)ָ
- type:Ԫص
+ @brief 遍历迭代语句,替代遍历过程中的for语句
+ @param vector:目标vector对象
+ iter:遍历时迭代器的变量名,是指向所遍历到的元素的(type*)型指针
+ type:元素的类型
@example Vector_ForEach(vector,ptr,int) { printf("%d",*ptr); }
*/
#define Vector_ForEach(vector,iter,type) for(type *iter=(type*)(vector).data; iter<((type*)(vector).data+(vector).size); iter++)
diff --git a/tools/motor/motor.c b/tools/motor/motor.c
index 23a94fff80158a8b7760e79a16e512303072d8f3..bcb26ed97372690bae33926cb619daa3740c3582 100644
--- a/tools/motor/motor.c
+++ b/tools/motor/motor.c
@@ -1,7 +1,7 @@
#include "motor.h"
//X-MACRO
-//бÿһʽΪ(,ʼ)
+//子类列表,每一项格式为(类型名,初始化函数名)
#define MOTOR_CHILD_LIST \
MOTOR_TYPE("M3508",M3508_Init) \
MOTOR_TYPE("M2006",M2006_Init) \
@@ -9,7 +9,7 @@
MOTOR_TYPE("Servo",Servo_Init) \
MOTOR_TYPE("DcMotor",DcMotor_Init)
-//ڲ
+//内部函数声明
void Motor_SetTarget(Motor* motor, float targetValue);
void Motor_ChangeCtrler(Motor* motor, MotorCtrlMode ctrlerType);
void Motor_InitTotalAngle(Motor* motor, float angle);
@@ -17,7 +17,7 @@ float Motor_GetData(Motor* motor, const char* data);
void Motor_Stop(Motor* motor);
void Motor_InitDefault(Motor* motor);
-//ʼ
+//声明子类初始化函数
#define MOTOR_TYPE(name,initFunc) __weak Motor* initFunc(ConfItem* dict) {return NULL;}
MOTOR_CHILD_LIST
#undef MOTOR_TYPE
@@ -27,7 +27,7 @@ Motor* Motor_Init(ConfItem* dict)
char* motorType = Conf_GetPtr(dict, "type", char);
Motor *motor = NULL;
- //жĸ
+ //判断属于哪个子类
#define MOTOR_TYPE(name,initFunc) \
if(!strcmp(motorType, name)) \
motor = initFunc(dict);
@@ -36,7 +36,7 @@ Motor* Motor_Init(ConfItem* dict)
if(!motor)
motor = MOTOR_MALLOC_PORT(sizeof(Motor));
- //δķΪպ
+ //将子类未定义的方法设置为空函数
Motor_InitDefault(motor);
return motor;
@@ -56,7 +56,7 @@ void Motor_InitDefault(Motor* motor)
motor->stop = Motor_Stop;
}
-//麯
+//纯虚函数
void Motor_SetTarget(Motor* motor, float targetValue) { }
void Motor_ChangeCtrler(Motor* motor, MotorCtrlMode mode) { }
diff --git a/tools/motor/motor_can/m2006.c b/tools/motor/motor_can/m2006.c
index 795ad470af7a87f486a3a2390871119d2f57f941..d14b67b76e30ac7e22ef88cbc9b5838760a63eb9 100644
--- a/tools/motor/motor_can/m2006.c
+++ b/tools/motor/motor_can/m2006.c
@@ -3,37 +3,37 @@
#include "pid.h"
#include "config.h"
-//ֵֵǶȵĻ
-#define M2006_DGR2CODE(dgr,rdcr) ((int32_t)((dgr)*22.7528f*(rdcr))) //ٱ*8191/360
+//各种电机编码值与角度的换算
+#define M2006_DGR2CODE(dgr,rdcr) ((int32_t)((dgr)*22.7528f*(rdcr))) //减速比*8191/360
#define M2006_CODE2DGR(code,rdcr) ((float)((code)/(22.7528f*(rdcr))))
typedef struct _M2006
{
- Motor motor;
-
- float reductionRatio;
- struct
- {
- uint16_t sendID,recvID;
- uint8_t canX;
- uint8_t bufIndex;
- }canInfo;
- MotorCtrlMode mode;
-
- int16_t angle,speed,torque;
-
- int16_t lastAngle;//¼һεõĽǶ
-
- int32_t totalAngle;//ۼתıֵ
-
- float targetValue;//Ŀֵ(Ťؾ/ٶ/Ƕ(λ))
-
- uint16_t stallTime;//תʱ
-
- PID speedPID;//ٶpid()
- CascadePID anglePID;//Ƕpid
-
- char* stallName;
+ Motor motor;
+
+ float reductionRatio;
+ struct
+ {
+ uint16_t sendID,recvID;
+ uint8_t canX;
+ uint8_t bufIndex;
+ }canInfo;
+ MotorCtrlMode mode;
+
+ int16_t angle,speed,torque;
+
+ int16_t lastAngle;//记录上一次得到的角度
+
+ int32_t totalAngle;//累计转过的编码器值
+
+ float targetValue;//目标值(输出轴扭矩矩/速度/角度(单位度))
+
+ uint16_t stallTime;//堵转时间
+
+ PID speedPID;//速度pid(单级)
+ CascadePID anglePID;//角度pid,串级
+
+ char* stallName;
}M2006;
Motor* M2006_Init(ConfItem* dict);
@@ -50,198 +50,197 @@ void M2006_PIDInit(M2006* m2006, ConfItem* dict);
void M2006_StatAngle(M2006* m2006);
void M2006_CtrlerCalc(M2006* m2006, float reference);
-//ʱص
+//软件定时器回调函数
void M2006_TimerCallback(void const *argument)
{
- M2006* m2006 = pvTimerGetTimerID((TimerHandle_t)argument);
- M2006_StatAngle(m2006);
- M2006_CtrlerCalc(m2006, m2006->targetValue);
- m2006->stallTime = (m2006->speed == 0 && abs(m2006->torque) > 500) ? m2006->stallTime + 2 : 0;
- if (m2006->stallTime > 500)
- {
- Bus_BroadcastSend(m2006->stallName, {{""}});
- m2006->stallTime = 0;
- }
+ M2006* m2006 = pvTimerGetTimerID((TimerHandle_t)argument);
+ M2006_StatAngle(m2006);
+ M2006_CtrlerCalc(m2006, m2006->targetValue);
+ m2006->stallTime = (m2006->speed == 0 && abs(m2006->torque) > 500) ? m2006->stallTime + 2 : 0;
+ if (m2006->stallTime > 500)
+ {
+ Bus_BroadcastSend(m2006->stallName, {{""}});
+ m2006->stallTime = 0;
+ }
}
Motor* M2006_Init(ConfItem* dict)
{
- //ڴռ
- M2006* m2006 = MOTOR_MALLOC_PORT(sizeof(M2006));
- memset(m2006,0,sizeof(M2006));
- //̬
- m2006->motor.setTarget = M2006_SetTarget;
- m2006->motor.changeMode = M2006_ChangeMode;
- m2006->motor.initTotalAngle = M2006_InitTotalAngle;
- m2006->motor.getData = M2006_GetData;
- m2006->motor.stop = M2006_Stop;
- //ٱ
- m2006->reductionRatio = Conf_GetValue(dict, "reduction-ratio", float, 36);//δõٱȲʹԭװĬϼٱ
- //ʼcanϢ
- uint16_t id = Conf_GetValue(dict, "id", uint16_t, 0);
- m2006->canInfo.recvID = id + 0x200;
- m2006->canInfo.sendID = (id <= 4) ? 0x200 : 0x1FF;
- m2006->canInfo.bufIndex = ((id - 1)%4) * 2;
- m2006->canInfo.canX = Conf_GetValue(dict, "can-x", uint8_t, 0);
- //õĬģʽΪŤģʽ
- m2006->mode = MOTOR_TORQUE_MODE;
- //ʼpid
- M2006_PIDInit(m2006, dict);
- //canϢ
- char name[] = "/can_/recv";
- name[4] = m2006->canInfo.canX + '0';
- Bus_RegisterReceiver(m2006, M2006_SoftBusCallback, name);
-
- char* motorName = Conf_GetPtr(dict, "name", char);
- motorName = motorName ? motorName : "motor";
- uint8_t len = strlen(motorName);
- m2006->stallName = MOTOR_MALLOC_PORT(len + 7+ 1); //7Ϊ"/ /stall"ijȣ1Ϊ'\0'ij
- sprintf(m2006->stallName, "/%s/stall", motorName);
- //ʱ
- osTimerDef(M2006, M2006_TimerCallback);
- osTimerStart(osTimerCreate(osTimer(M2006), osTimerPeriodic, m2006), 2);
-
- return (Motor*)m2006;
+ //分配子类内存空间
+ M2006* m2006 = MOTOR_MALLOC_PORT(sizeof(M2006));
+ memset(m2006,0,sizeof(M2006));
+ //子类多态
+ m2006->motor.setTarget = M2006_SetTarget;
+ m2006->motor.changeMode = M2006_ChangeMode;
+ m2006->motor.initTotalAngle = M2006_InitTotalAngle;
+ m2006->motor.getData = M2006_GetData;
+ m2006->motor.stop = M2006_Stop;
+ //电机减速比
+ m2006->reductionRatio = Conf_GetValue(dict, "reduction-ratio", float, 36);//如果未配置电机减速比参数,则使用原装电机默认减速比
+ //初始化电机绑定can信息
+ uint16_t id = Conf_GetValue(dict, "id", uint16_t, 0);
+ m2006->canInfo.recvID = id + 0x200;
+ m2006->canInfo.sendID = (id <= 4) ? 0x200 : 0x1FF;
+ m2006->canInfo.bufIndex = ((id - 1)%4) * 2;
+ m2006->canInfo.canX = Conf_GetValue(dict, "can-x", uint8_t, 0);
+ //设置电机默认模式为扭矩模式
+ m2006->mode = MOTOR_TORQUE_MODE;
+ //初始化电机pid
+ M2006_PIDInit(m2006, dict);
+ //订阅can信息
+ char name[] = "/can_/recv";
+ name[4] = m2006->canInfo.canX + '0';
+ Bus_RegisterReceiver(m2006, M2006_SoftBusCallback, name);
+
+ char* motorName = Conf_GetPtr(dict, "name", char);
+ motorName = motorName ? motorName : "motor";
+ uint8_t len = strlen(motorName);
+ m2006->stallName = MOTOR_MALLOC_PORT(len + 7+ 1); //7为"/ /stall"的长度,1为'\0'的长度
+ sprintf(m2006->stallName, "/%s/stall", motorName);
+ //开启软件定时器
+ osTimerDef(M2006, M2006_TimerCallback);
+ osTimerStart(osTimerCreate(osTimer(M2006), osTimerPeriodic, m2006), 2);
+
+ return (Motor*)m2006;
}
-//ʼpid
+//初始化pid
void M2006_PIDInit(M2006* m2006, ConfItem* dict)
{
- PID_Init(&m2006->speedPID, Conf_GetPtr(dict, "speed-pid", ConfItem));
- PID_Init(&m2006->anglePID.inner, Conf_GetPtr(dict, "angle-pid/inner", ConfItem));
- PID_Init(&m2006->anglePID.outer, Conf_GetPtr(dict, "angle-pid/outer", ConfItem));
- PID_SetMaxOutput(&m2006->anglePID.outer, m2006->anglePID.outer.maxOutput*m2006->reductionRatio);//ٶŴת
+ PID_Init(&m2006->speedPID, Conf_GetPtr(dict, "speed-pid", ConfItem));
+ PID_Init(&m2006->anglePID.inner, Conf_GetPtr(dict, "angle-pid/inner", ConfItem));
+ PID_Init(&m2006->anglePID.outer, Conf_GetPtr(dict, "angle-pid/outer", ConfItem));
+ PID_SetMaxOutput(&m2006->anglePID.outer, m2006->anglePID.outer.maxOutput*m2006->reductionRatio);//将输出轴速度限幅放大到转子上
}
-//ص
+//软总线回调函数
void M2006_SoftBusCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
- M2006* m2006 = (M2006*)bindData;
-
- uint16_t id = *(uint16_t*)Bus_GetListValue(frame, 0);
- if(id != m2006->canInfo.recvID)
- return;
-
- uint8_t* data = (uint8_t*)Bus_GetListValue(frame, 1);
- if(data)
- M2006_Update(m2006, data);
+ M2006* m2006 = (M2006*)bindData;
+
+ uint16_t id = *(uint16_t*)Bus_GetListValue(frame, 0);
+ if(id != m2006->canInfo.recvID)
+ return;
+
+ uint8_t* data = (uint8_t*)Bus_GetListValue(frame, 1);
+ if(data)
+ M2006_Update(m2006, data);
}
-//ʼͳƵۼƽǶ
+//开始统计电机累计角度
void M2006_InitTotalAngle(Motor *motor, float startAngle)
{
- M2006* m2006 = (M2006*)motor;
-
- m2006->totalAngle= M2006_DGR2CODE(startAngle, m2006->reductionRatio);
- m2006->lastAngle=m2006->angle;
+ M2006* m2006 = (M2006*)motor;
+
+ m2006->totalAngle= M2006_DGR2CODE(startAngle, m2006->reductionRatio);
+ m2006->lastAngle=m2006->angle;
}
-//ͳƵۼתȦ
+//统计电机累计转过的圈数
void M2006_StatAngle(M2006* m2006)
{
- int32_t dAngle=0;
- if(m2006->angle-m2006->lastAngle<-4000)
- dAngle=m2006->angle+(8191-m2006->lastAngle);
- else if(m2006->angle-m2006->lastAngle>4000)
- dAngle=-m2006->lastAngle-(8191-m2006->angle);
- else
- dAngle=m2006->angle-m2006->lastAngle;
- //Ƕ
- m2006->totalAngle+=dAngle;
- //¼Ƕ
- m2006->lastAngle=m2006->angle;
+ int32_t dAngle=0;
+ if(m2006->angle-m2006->lastAngle<-4000)
+ dAngle=m2006->angle+(8191-m2006->lastAngle);
+ else if(m2006->angle-m2006->lastAngle>4000)
+ dAngle=-m2006->lastAngle-(8191-m2006->angle);
+ else
+ dAngle=m2006->angle-m2006->lastAngle;
+ //将角度增量加入计数器
+ m2006->totalAngle+=dAngle;
+ //记录角度
+ m2006->lastAngle=m2006->angle;
}
-//ģʽ
+//控制器根据模式计算输出
void M2006_CtrlerCalc(M2006* m2006, float reference)
{
- int16_t output=0;
- uint8_t buffer[2]={0};
- if(m2006->mode == MOTOR_SPEED_MODE)
- {
- PID_SingleCalc(&m2006->speedPID, reference, m2006->speed);
- output = m2006->speedPID.output;
- }
- else if(m2006->mode == MOTOR_ANGLE_MODE)
- {
- PID_CascadeCalc(&m2006->anglePID, reference, m2006->totalAngle, m2006->speed);
- output = m2006->anglePID.output;
- }
- else if(m2006->mode == MOTOR_TORQUE_MODE)
- {
- output = (int16_t)reference;
- }
- buffer[0] = (output>>8)&0xff;
- buffer[1] = (output)&0xff;
- //canϢ
- Bus_RemoteCall("/can/set-buf",{
- {"can-x", &m2006->canInfo.canX},
- {"id", &m2006->canInfo.sendID},
- {"pos", &m2006->canInfo.bufIndex},
- {"len", &(uint8_t){2}},
- {"data", buffer}
- });
+ int16_t output=0;
+ uint8_t buffer[2]={0};
+ if(m2006->mode == MOTOR_SPEED_MODE)
+ {
+ PID_SingleCalc(&m2006->speedPID, reference, m2006->speed);
+ output = m2006->speedPID.output;
+ }
+ else if(m2006->mode == MOTOR_ANGLE_MODE)
+ {
+ PID_CascadeCalc(&m2006->anglePID, reference, m2006->totalAngle, m2006->speed);
+ output = m2006->anglePID.output;
+ }
+ else if(m2006->mode == MOTOR_TORQUE_MODE)
+ {
+ output = (int16_t)reference;
+ }
+ buffer[0] = (output>>8)&0xff;
+ buffer[1] = (output)&0xff;
+ //发布can信息
+ Bus_RemoteCall("/can/set-buf",{{"can-x", {.U8 = m2006->canInfo.canX}},
+ {"id", {.U16 = m2006->canInfo.sendID}},
+ {"pos", {.U8 = m2006->canInfo.bufIndex}},
+ {"len", {.U8 = 2}},
+ {"data", {buffer}}
+ });
}
-//õֵ
+//设置电机期望值
void M2006_SetTarget(Motor* motor, float targetValue)
{
- M2006* m2006 = (M2006*)motor;
- if(m2006->mode == MOTOR_ANGLE_MODE)
- {
- m2006->targetValue = M2006_DGR2CODE(targetValue, m2006->reductionRatio);
- }
- else if(m2006->mode == MOTOR_SPEED_MODE)
- {
- m2006->targetValue = targetValue*m2006->reductionRatio;
- }
- else
- {
- m2006->targetValue = targetValue;
- }
+ M2006* m2006 = (M2006*)motor;
+ if(m2006->mode == MOTOR_ANGLE_MODE)
+ {
+ m2006->targetValue = M2006_DGR2CODE(targetValue, m2006->reductionRatio);
+ }
+ else if(m2006->mode == MOTOR_SPEED_MODE)
+ {
+ m2006->targetValue = targetValue*m2006->reductionRatio;
+ }
+ else
+ {
+ m2006->targetValue = targetValue;
+ }
}
-//лģʽ
+//切换电机模式
void M2006_ChangeMode(Motor* motor, MotorCtrlMode mode)
{
- M2006* m2006 = (M2006*)motor;
- if(m2006->mode == MOTOR_STOP_MODE) //ͣģʽ²лģʽ
- return;
-
- if(m2006->mode == MOTOR_SPEED_MODE)
- {
- PID_Clear(&m2006->speedPID);
- }
- else if(m2006->mode == MOTOR_ANGLE_MODE)
- {
- PID_Clear(&m2006->anglePID.inner);
- PID_Clear(&m2006->anglePID.outer);
- }
- m2006->mode = mode;
+ M2006* m2006 = (M2006*)motor;
+ if(m2006->mode == MOTOR_STOP_MODE) //急停模式下不允许切换模式
+ return;
+
+ if(m2006->mode == MOTOR_SPEED_MODE)
+ {
+ PID_Clear(&m2006->speedPID);
+ }
+ else if(m2006->mode == MOTOR_ANGLE_MODE)
+ {
+ PID_Clear(&m2006->anglePID.inner);
+ PID_Clear(&m2006->anglePID.outer);
+ }
+ m2006->mode = mode;
}
-//ȡ
+//获取电机数据
float M2006_GetData(Motor* motor, const char* data)
{
- M2006* m2006 = (M2006*)motor;
- if(!strcmp(data, "angle"))
- {
- return M2006_CODE2DGR(m2006->angle, 1);
- }
- else if(!strcmp(data, "totalAngle"))
- {
- return M2006_CODE2DGR(m2006->totalAngle, m2006->reductionRatio);
- }
- return 0;
+ M2006* m2006 = (M2006*)motor;
+ if(!strcmp(data, "angle"))
+ {
+ return M2006_CODE2DGR(m2006->angle, 1);
+ }
+ else if(!strcmp(data, "totalAngle"))
+ {
+ return M2006_CODE2DGR(m2006->totalAngle, m2006->reductionRatio);
+ }
+ return 0;
}
-//ͣ
+//电机急停函数
void M2006_Stop(Motor* motor)
{
- M2006* m2006 = (M2006*)motor;
- m2006->targetValue = 0;
- m2006->mode = MOTOR_STOP_MODE;
+ M2006* m2006 = (M2006*)motor;
+ m2006->targetValue = 0;
+ m2006->mode = MOTOR_STOP_MODE;
}
-//µ(ܽ˲)
+//更新电机数据(可能进行滤波)
void M2006_Update(M2006* m2006,uint8_t* data)
{
- m2006->angle = (data[0]<<8 | data[1]);
- m2006->speed = (data[2]<<8 | data[3]);
- m2006->torque = (data[4]<<8 | data[5]);
+ m2006->angle = (data[0]<<8 | data[1]);
+ m2006->speed = (data[2]<<8 | data[3]);
+ m2006->torque = (data[4]<<8 | data[5]);
}
diff --git a/tools/motor/motor_can/m3508.c b/tools/motor/motor_can/m3508.c
index b8a841c596f79d7497e106caedefb8b64d151403..a167b06511e624ec0027ae91acd12036666cb6ca 100644
--- a/tools/motor/motor_can/m3508.c
+++ b/tools/motor/motor_can/m3508.c
@@ -3,8 +3,8 @@
#include "pid.h"
#include "config.h"
-//ֵֵǶȵĻ
-#define M3508_DGR2CODE(dgr,rdcr) ((int32_t)((dgr)*22.7528f*(rdcr))) //ٱ*8191/360
+//各种电机编码值与角度的换算
+#define M3508_DGR2CODE(dgr,rdcr) ((int32_t)((dgr)*22.7528f*(rdcr))) //减速比*8191/360
#define M3508_CODE2DGR(code,rdcr) ((float)((code)/(22.7528f*(rdcr))))
typedef struct _M3508
@@ -22,16 +22,16 @@ typedef struct _M3508
int16_t angle,speed,torque;
- int16_t lastAngle;//¼һεõĽǶ
+ int16_t lastAngle;//记录上一次得到的角度
- int32_t totalAngle;//ۼתıֵ
+ int32_t totalAngle;//累计转过的编码器值
- float targetValue;//Ŀֵ(Ťؾ/ٶ/Ƕ(λ))
+ float targetValue;//目标值(输出轴扭矩矩/速度/角度(单位度))
- uint16_t stallTime;//תʱ
+ uint16_t stallTime;//堵转时间
- PID speedPID;//ٶpid()
- CascadePID anglePID;//Ƕpid
+ PID speedPID;//速度pid(单级)
+ CascadePID anglePID;//角度pid,串级
char* stallName;
}M3508;
@@ -50,7 +50,7 @@ void M3508_PIDInit(M3508* m3508, ConfItem* dict);
void M3508_StatAngle(M3508* m3508);
void M3508_CtrlerCalc(M3508* m3508, float reference);
-//ʱص
+//软件定时器回调函数
void M3508_TimerCallback(void const *argument)
{
M3508* m3508 = pvTimerGetTimerID((TimerHandle_t)argument);
@@ -66,28 +66,28 @@ void M3508_TimerCallback(void const *argument)
Motor* M3508_Init(ConfItem* dict)
{
- //ڴռ
+ //分配子类内存空间
M3508* m3508 = MOTOR_MALLOC_PORT(sizeof(M3508));
memset(m3508,0,sizeof(M3508));
- //̬
+ //子类多态
m3508->motor.setTarget = M3508_SetTarget;
m3508->motor.changeMode = M3508_ChangeMode;
m3508->motor.initTotalAngle = M3508_InitTotalAngle;
m3508->motor.getData = M3508_GetData;
m3508->motor.stop = M3508_Stop;
- //ٱ
- m3508->reductionRatio = Conf_GetValue(dict, "reduction-ratio", float, 19.2f);//δõٱȲʹԭװĬϼٱ
- //ʼcanϢ
+ //电机减速比
+ m3508->reductionRatio = Conf_GetValue(dict, "reduction-ratio", float, 19.2f);//如果未配置电机减速比参数,则使用原装电机默认减速比
+ //初始化电机绑定can信息
uint16_t id = Conf_GetValue(dict, "id", uint16_t, 0);
m3508->canInfo.recvID = id + 0x200;
m3508->canInfo.sendID = (id <= 4) ? 0x200 : 0x1FF;
m3508->canInfo.bufIndex = ((id - 1)%4) * 2;
m3508->canInfo.canX = Conf_GetValue(dict, "can-x", uint8_t, 0);
- //õĬģʽΪŤģʽ
+ //设置电机默认模式为扭矩模式
m3508->mode = MOTOR_TORQUE_MODE;
- //ʼpid
+ //初始化电机pid
M3508_PIDInit(m3508, dict);
- //canϢ
+ //订阅can信息
char name[] = "/can_/recv";
name[4] = m3508->canInfo.canX + '0';
Bus_RegisterReceiver(m3508, M3508_SoftBusCallback, name);
@@ -95,23 +95,23 @@ Motor* M3508_Init(ConfItem* dict)
char* motorName = Conf_GetPtr(dict, "name", char);
motorName = motorName ? motorName : "motor";
uint8_t len = strlen(motorName);
- m3508->stallName = MOTOR_MALLOC_PORT(len + 7+ 1); //7Ϊ"/ /stall"ijȣ1Ϊ'\0'ij
+ m3508->stallName = MOTOR_MALLOC_PORT(len + 7+ 1); //7为"/ /stall"的长度,1为'\0'的长度
sprintf(m3508->stallName, "/%s/stall", motorName);
- //ʱ
+ //开启软件定时器
osTimerDef(M3508, M3508_TimerCallback);
osTimerStart(osTimerCreate(osTimer(M3508), osTimerPeriodic, m3508), 2);
return (Motor*)m3508;
}
-//ʼpid
+//初始化pid
void M3508_PIDInit(M3508* m3508, ConfItem* dict)
{
PID_Init(&m3508->speedPID, Conf_GetPtr(dict, "speed-pid", ConfItem));
PID_Init(&m3508->anglePID.inner, Conf_GetPtr(dict, "angle-pid/inner", ConfItem));
PID_Init(&m3508->anglePID.outer, Conf_GetPtr(dict, "angle-pid/outer", ConfItem));
- PID_SetMaxOutput(&m3508->anglePID.outer, m3508->anglePID.outer.maxOutput*m3508->reductionRatio);//ٶŴת
+ PID_SetMaxOutput(&m3508->anglePID.outer, m3508->anglePID.outer.maxOutput*m3508->reductionRatio);//将输出轴速度限幅放大到转子上
}
-//ص
+//软总线回调函数
void M3508_SoftBusCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
M3508* m3508 = (M3508*)bindData;
@@ -125,7 +125,7 @@ void M3508_SoftBusCallback(const char* name, SoftBusFrame* frame, void* bindData
M3508_Update(m3508, data);
}
-//ͣص
+//电机急停回调函数
void M3508_StopCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
M3508* m3508 = (M3508*)bindData;
@@ -133,7 +133,7 @@ void M3508_StopCallback(const char* name, SoftBusFrame* frame, void* bindData)
m3508->mode = MOTOR_STOP_MODE;
}
-//ʼͳƵۼƽǶ
+//开始统计电机累计角度
void M3508_InitTotalAngle(Motor *motor, float startAngle)
{
M3508* m3508 = (M3508*)motor;
@@ -142,7 +142,7 @@ void M3508_InitTotalAngle(Motor *motor, float startAngle)
m3508->lastAngle=m3508->angle;
}
-//ͳƵۼתȦ
+//统计电机累计转过的圈数
void M3508_StatAngle(M3508* m3508)
{
int32_t dAngle=0;
@@ -152,12 +152,12 @@ void M3508_StatAngle(M3508* m3508)
dAngle=-m3508->lastAngle-(8191-m3508->angle);
else
dAngle=m3508->angle-m3508->lastAngle;
- //Ƕ
+ //将角度增量加入计数器
m3508->totalAngle+=dAngle;
- //¼Ƕ
+ //记录角度
m3508->lastAngle=m3508->angle;
}
-//ģʽ
+//控制器根据模式计算输出
void M3508_CtrlerCalc(M3508* m3508, float reference)
{
int16_t output=0;
@@ -178,15 +178,14 @@ void M3508_CtrlerCalc(M3508* m3508, float reference)
}
buffer[0] = (output>>8)&0xff;
buffer[1] = (output)&0xff;
- Bus_RemoteCall("/can/set-buf",{
- {"can-x", &m3508->canInfo.canX},
- {"id", &m3508->canInfo.sendID},
- {"pos", &m3508->canInfo.bufIndex},
- {"len", &(uint8_t){2}},
- {"data", buffer}
+ Bus_RemoteCall("/can/set-buf",{{"can-x", {.U8 = m3508->canInfo.canX}},
+ {"id", {.U16 = m3508->canInfo.sendID}},
+ {"pos", {.U8 = m3508->canInfo.bufIndex}},
+ {"len", {.U8 = 2}},
+ {"data", {buffer}}
});
}
-//õֵ
+//设置电机期望值
void M3508_SetTarget(Motor* motor, float targetValue)
{
M3508* m3508 = (M3508*)motor;
@@ -203,11 +202,11 @@ void M3508_SetTarget(Motor* motor, float targetValue)
m3508->targetValue = targetValue;
}
}
-//лģʽ
+//切换电机模式
void M3508_ChangeMode(Motor* motor, MotorCtrlMode mode)
{
M3508* m3508 = (M3508*)motor;
- if(m3508->mode == MOTOR_STOP_MODE) //ͣģʽ²лģʽ
+ if(m3508->mode == MOTOR_STOP_MODE) //急停模式下不允许切换模式
return;
if(m3508->mode == MOTOR_SPEED_MODE)
@@ -222,7 +221,7 @@ void M3508_ChangeMode(Motor* motor, MotorCtrlMode mode)
m3508->mode = mode;
}
-//ȡ
+//获取电机数据
float M3508_GetData(Motor* motor, const char* data)
{
M3508* m3508 = (M3508*)motor;
@@ -238,7 +237,7 @@ float M3508_GetData(Motor* motor, const char* data)
return 0;
}
-//ͣ
+//电机急停函数
void M3508_Stop(Motor* motor)
{
M3508* m3508 = (M3508*)motor;
@@ -246,7 +245,7 @@ void M3508_Stop(Motor* motor)
m3508->mode = MOTOR_STOP_MODE;
}
-//µ(ܽ˲)
+//更新电机数据(可能进行滤波)
void M3508_Update(M3508* m3508,uint8_t* data)
{
m3508->angle = (data[0]<<8 | data[1]);
diff --git a/tools/motor/motor_can/m6020.c b/tools/motor/motor_can/m6020.c
index 880be2221c5bf2c3d37e2216258ecd9abce93ded..4944327f86bc8f9a44b027f14c3f006ac3189700 100644
--- a/tools/motor/motor_can/m6020.c
+++ b/tools/motor/motor_can/m6020.c
@@ -3,33 +3,33 @@
#include "pid.h"
#include "config.h"
-//ֵֵǶȵĻ
-#define M6020_DGR2CODE(dgr,rdcr) ((int32_t)((dgr)*22.7528f*(rdcr))) //ٱ*8191/360
+//各种电机编码值与角度的换算
+#define M6020_DGR2CODE(dgr,rdcr) ((int32_t)((dgr)*22.7528f*(rdcr))) //减速比*8191/360
#define M6020_CODE2DGR(code,rdcr) ((float)((code)/(22.7528f*(rdcr))))
typedef struct _M6020
{
- Motor motor;
-
- float reductionRatio;
- struct
- {
- uint16_t sendID,recvID;
- uint8_t canX;
- uint8_t bufIndex;
- }canInfo;
- MotorCtrlMode mode;
-
- int16_t angle,speed;
-
- int16_t lastAngle;//¼һεõĽǶ
-
- int32_t totalAngle;//ۼתıֵ
-
- float targetValue;//Ŀֵ(Ťؾ/ٶ/Ƕ(λ))
-
- PID speedPID;//ٶpid()
- CascadePID anglePID;//Ƕpid
+ Motor motor;
+
+ float reductionRatio;
+ struct
+ {
+ uint16_t sendID,recvID;
+ uint8_t canX;
+ uint8_t bufIndex;
+ }canInfo;
+ MotorCtrlMode mode;
+
+ int16_t angle,speed;
+
+ int16_t lastAngle;//记录上一次得到的角度
+
+ int32_t totalAngle;//累计转过的编码器值
+
+ float targetValue;//目标值(输出轴扭矩矩/速度/角度(单位度))
+
+ PID speedPID;//速度pid(单级)
+ CascadePID anglePID;//角度pid,串级
}M6020;
Motor* M6020_Init(ConfItem* dict);
@@ -46,193 +46,191 @@ void M6020_PIDInit(M6020* m6020, ConfItem* dict);
void M6020_StatAngle(M6020* m6020);
void M6020_CtrlerCalc(M6020* m6020, float reference);
-//ʱص
+//软件定时器回调函数
void M6020_TimerCallback(void const *argument)
{
- M6020* m6020 = pvTimerGetTimerID((TimerHandle_t)argument);
- M6020_StatAngle(m6020);
- M6020_CtrlerCalc(m6020, m6020->targetValue);
+ M6020* m6020 = pvTimerGetTimerID((TimerHandle_t)argument);
+ M6020_StatAngle(m6020);
+ M6020_CtrlerCalc(m6020, m6020->targetValue);
}
Motor* M6020_Init(ConfItem* dict)
{
- //ڴռ
- M6020* m6020 = MOTOR_MALLOC_PORT(sizeof(M6020));
- memset(m6020,0,sizeof(M6020));
- //̬
- m6020->motor.setTarget = M6020_SetTarget;
- m6020->motor.changeMode = M6020_ChangeMode;
- m6020->motor.initTotalAngle = M6020_InitTotalAngle;
- m6020->motor.getData = M6020_GetData;
- m6020->motor.stop = M6020_Stop;
- //ٱ
- m6020->reductionRatio = Conf_GetValue(dict, "reduction-ratio", float, 1);//δõٱȲʹԭװĬϼٱ
- //ʼcanϢ
- uint16_t id = Conf_GetValue(dict, "id", uint16_t, 0);
- m6020->canInfo.recvID = id + 0x204;
- m6020->canInfo.sendID = (id <= 4) ? 0x1FF : 0x2FF;
- m6020->canInfo.bufIndex = ((id - 1)%4) * 2;
- m6020->canInfo.canX = Conf_GetValue(dict, "can-x", uint8_t, 0);
- //õĬģʽΪŤģʽ
- m6020->mode = MOTOR_TORQUE_MODE;
- //ʼpid
- M6020_PIDInit(m6020, dict);
- //canϢ
- char name[] = "/can_/recv";
- name[4] = m6020->canInfo.canX + '0';
- Bus_RegisterReceiver(m6020, M6020_SoftBusCallback, name);
- //ʱ
- osTimerDef(M6020, M6020_TimerCallback);
- osTimerStart(osTimerCreate(osTimer(M6020), osTimerPeriodic, m6020), 2);
-
- return (Motor*)m6020;
+ //分配子类内存空间
+ M6020* m6020 = MOTOR_MALLOC_PORT(sizeof(M6020));
+ memset(m6020,0,sizeof(M6020));
+ //子类多态
+ m6020->motor.setTarget = M6020_SetTarget;
+ m6020->motor.changeMode = M6020_ChangeMode;
+ m6020->motor.initTotalAngle = M6020_InitTotalAngle;
+ m6020->motor.getData = M6020_GetData;
+ m6020->motor.stop = M6020_Stop;
+ //电机减速比
+ m6020->reductionRatio = Conf_GetValue(dict, "reduction-ratio", float, 1);//如果未配置电机减速比参数,则使用原装电机默认减速比
+ //初始化电机绑定can信息
+ uint16_t id = Conf_GetValue(dict, "id", uint16_t, 0);
+ m6020->canInfo.recvID = id + 0x204;
+ m6020->canInfo.sendID = (id <= 4) ? 0x1FF : 0x2FF;
+ m6020->canInfo.bufIndex = ((id - 1)%4) * 2;
+ m6020->canInfo.canX = Conf_GetValue(dict, "can-x", uint8_t, 0);
+ //设置电机默认模式为扭矩模式
+ m6020->mode = MOTOR_TORQUE_MODE;
+ //初始化电机pid
+ M6020_PIDInit(m6020, dict);
+ //订阅can信息
+ char name[] = "/can_/recv";
+ name[4] = m6020->canInfo.canX + '0';
+ Bus_RegisterReceiver(m6020, M6020_SoftBusCallback, name);
+ //开启软件定时器
+ osTimerDef(M6020, M6020_TimerCallback);
+ osTimerStart(osTimerCreate(osTimer(M6020), osTimerPeriodic, m6020), 2);
+
+ return (Motor*)m6020;
}
-//ʼpid
+//初始化pid
void M6020_PIDInit(M6020* m6020, ConfItem* dict)
{
- PID_Init(&m6020->speedPID, Conf_GetPtr(dict, "speed-pid", ConfItem));
- PID_Init(&m6020->anglePID.inner, Conf_GetPtr(dict, "angle-pid/inner", ConfItem));
- PID_Init(&m6020->anglePID.outer, Conf_GetPtr(dict, "angle-pid/outer", ConfItem));
- PID_SetMaxOutput(&m6020->anglePID.outer, m6020->anglePID.outer.maxOutput*m6020->reductionRatio);//ٶŴת
+ PID_Init(&m6020->speedPID, Conf_GetPtr(dict, "speed-pid", ConfItem));
+ PID_Init(&m6020->anglePID.inner, Conf_GetPtr(dict, "angle-pid/inner", ConfItem));
+ PID_Init(&m6020->anglePID.outer, Conf_GetPtr(dict, "angle-pid/outer", ConfItem));
+ PID_SetMaxOutput(&m6020->anglePID.outer, m6020->anglePID.outer.maxOutput*m6020->reductionRatio);//将输出轴速度限幅放大到转子上
}
-//ص
+//软总线回调函数
void M6020_SoftBusCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
- M6020* m6020 = (M6020*)bindData;
-
- uint16_t id = *(uint16_t*)Bus_GetListValue(frame, 0);
- if(id != m6020->canInfo.recvID)
- return;
-
- uint8_t* data = (uint8_t*)Bus_GetListValue(frame, 1);
- if(data)
- M6020_Update(m6020, data);
+ M6020* m6020 = (M6020*)bindData;
+
+ uint16_t id = *(uint16_t*)Bus_GetListValue(frame, 0);
+ if(id != m6020->canInfo.recvID)
+ return;
+
+ uint8_t* data = (uint8_t*)Bus_GetListValue(frame, 1);
+ if(data)
+ M6020_Update(m6020, data);
}
-//ͣص
+//电机急停回调函数
void M6020_StopCallback(const char* name, SoftBusFrame* frame, void* bindData)
{
- M6020* m6020 = (M6020*)bindData;
- m6020->targetValue = 0;
- m6020->mode = MOTOR_STOP_MODE;
+ M6020* m6020 = (M6020*)bindData;
+ m6020->targetValue = 0;
+ m6020->mode = MOTOR_STOP_MODE;
}
-//ʼͳƵۼƽǶ
+//开始统计电机累计角度
void M6020_InitTotalAngle(Motor *motor, float startAngle)
{
- M6020* m6020 = (M6020*)motor;
-
- m6020->totalAngle=M6020_DGR2CODE(startAngle, m6020->reductionRatio);
- m6020->lastAngle=m6020->angle;
+ M6020* m6020 = (M6020*)motor;
+
+ m6020->totalAngle=M6020_DGR2CODE(startAngle, m6020->reductionRatio);
+ m6020->lastAngle=m6020->angle;
}
-//ͳƵۼתȦ
+//统计电机累计转过的圈数
void M6020_StatAngle(M6020* m6020)
{
- int32_t dAngle=0;
- if(m6020->angle-m6020->lastAngle<-4000)
- dAngle=m6020->angle+(8191-m6020->lastAngle);
- else if(m6020->angle-m6020->lastAngle>4000)
- dAngle=-m6020->lastAngle-(8191-m6020->angle);
- else
- dAngle=m6020->angle-m6020->lastAngle;
- //Ƕ
- m6020->totalAngle+=dAngle;
- //¼Ƕ
- m6020->lastAngle=m6020->angle;
+ int32_t dAngle=0;
+ if(m6020->angle-m6020->lastAngle<-4000)
+ dAngle=m6020->angle+(8191-m6020->lastAngle);
+ else if(m6020->angle-m6020->lastAngle>4000)
+ dAngle=-m6020->lastAngle-(8191-m6020->angle);
+ else
+ dAngle=m6020->angle-m6020->lastAngle;
+ //将角度增量加入计数器
+ m6020->totalAngle+=dAngle;
+ //记录角度
+ m6020->lastAngle=m6020->angle;
}
-//ģʽ
+//控制器根据模式计算输出
void M6020_CtrlerCalc(M6020* m6020, float reference)
{
- int16_t output=0;
- uint8_t buffer[2]={0};
- if(m6020->mode == MOTOR_SPEED_MODE)
- {
- PID_SingleCalc(&m6020->speedPID, reference, m6020->speed);
- output = m6020->speedPID.output;
- }
- else if(m6020->mode == MOTOR_ANGLE_MODE)
- {
- PID_CascadeCalc(&m6020->anglePID, reference, m6020->totalAngle, m6020->speed);
- output = m6020->anglePID.output;
- }
- else if(m6020->mode == MOTOR_TORQUE_MODE)
- {
- output = (int16_t)reference;
- }
- buffer[0] = (output>>8)&0xff;
- buffer[1] = (output)&0xff;
- Bus_RemoteCall("/can/set-buf",{
- {"can-x", &m6020->canInfo.canX},
- {"id", &m6020->canInfo.sendID},
- {"pos", &m6020->canInfo.bufIndex},
- {"len", &(uint8_t){2}},
- {"data", buffer}
- });
+ int16_t output=0;
+ uint8_t buffer[2]={0};
+ if(m6020->mode == MOTOR_SPEED_MODE)
+ {
+ PID_SingleCalc(&m6020->speedPID, reference, m6020->speed);
+ output = m6020->speedPID.output;
+ }
+ else if(m6020->mode == MOTOR_ANGLE_MODE)
+ {
+ PID_CascadeCalc(&m6020->anglePID, reference, m6020->totalAngle, m6020->speed);
+ output = m6020->anglePID.output;
+ }
+ else if(m6020->mode == MOTOR_TORQUE_MODE)
+ {
+ output = (int16_t)reference;
+ }
+ buffer[0] = (output>>8)&0xff;
+ buffer[1] = (output)&0xff;
+ Bus_RemoteCall("/can/set-buf",{{"can-x", {.U8 = m6020->canInfo.canX}},
+ {"id", {.U16 = m6020->canInfo.sendID}},
+ {"pos", {.U8 = m6020->canInfo.bufIndex}},
+ {"len", {.U8 = 2}},
+ {"data", {buffer}}});
}
-//õֵ
+//设置电机期望值
void M6020_SetTarget(Motor* motor, float targetValue)
{
- M6020* m6020 = (M6020*)motor;
- if(m6020->mode == MOTOR_ANGLE_MODE)
- {
- m6020->targetValue = M6020_DGR2CODE(targetValue, m6020->reductionRatio);
- }
- else if(m6020->mode == MOTOR_SPEED_MODE)
- {
- m6020->targetValue = targetValue*m6020->reductionRatio;
- }
- else
- {
- m6020->targetValue = targetValue;
- }
+ M6020* m6020 = (M6020*)motor;
+ if(m6020->mode == MOTOR_ANGLE_MODE)
+ {
+ m6020->targetValue = M6020_DGR2CODE(targetValue, m6020->reductionRatio);
+ }
+ else if(m6020->mode == MOTOR_SPEED_MODE)
+ {
+ m6020->targetValue = targetValue*m6020->reductionRatio;
+ }
+ else
+ {
+ m6020->targetValue = targetValue;
+ }
}
-//лģʽ
+//切换电机模式
void M6020_ChangeMode(Motor* motor, MotorCtrlMode mode)
{
- M6020* m6020 = (M6020*)motor;
- if(m6020->mode == MOTOR_STOP_MODE) //ͣģʽ²лģʽ
- return;
-
- if(m6020->mode == MOTOR_SPEED_MODE)
- {
- PID_Clear(&m6020->speedPID);
- }
- else if(m6020->mode == MOTOR_ANGLE_MODE)
- {
- PID_Clear(&m6020->anglePID.inner);
- PID_Clear(&m6020->anglePID.outer);
- }
- m6020->mode = mode;
+ M6020* m6020 = (M6020*)motor;
+ if(m6020->mode == MOTOR_STOP_MODE) //急停模式下不允许切换模式
+ return;
+
+ if(m6020->mode == MOTOR_SPEED_MODE)
+ {
+ PID_Clear(&m6020->speedPID);
+ }
+ else if(m6020->mode == MOTOR_ANGLE_MODE)
+ {
+ PID_Clear(&m6020->anglePID.inner);
+ PID_Clear(&m6020->anglePID.outer);
+ }
+ m6020->mode = mode;
}
-//ȡ
+//获取电机数据
float M6020_GetData(Motor* motor, const char* data)
{
- M6020* m6020 = (M6020*)motor;
-
- if(!strcmp(data, "angle"))
- {
- return M6020_CODE2DGR(m6020->angle, 1);
- }
- else if(!strcmp(data, "totalAngle"))
- {
- return M6020_CODE2DGR(m6020->totalAngle, m6020->reductionRatio);
- }
- return 0;
+ M6020* m6020 = (M6020*)motor;
+
+ if(!strcmp(data, "angle"))
+ {
+ return M6020_CODE2DGR(m6020->angle, 1);
+ }
+ else if(!strcmp(data, "totalAngle"))
+ {
+ return M6020_CODE2DGR(m6020->totalAngle, m6020->reductionRatio);
+ }
+ return 0;
}
-//ͣ
+//电机急停函数
void M6020_Stop(Motor* motor)
{
- M6020* m6020 = (M6020*)motor;
- m6020->targetValue = 0;
- m6020->mode = MOTOR_STOP_MODE;
+ M6020* m6020 = (M6020*)motor;
+ m6020->targetValue = 0;
+ m6020->mode = MOTOR_STOP_MODE;
}
-//µ(ܽ˲)
+//更新电机数据(可能进行滤波)
void M6020_Update(M6020* m6020,uint8_t* data)
{
- m6020->angle = (data[0]<<8 | data[1]);
- m6020->speed = (data[2]<<8 | data[3]);
+ m6020->angle = (data[0]<<8 | data[1]);
+ m6020->speed = (data[2]<<8 | data[3]);
}
diff --git a/tools/motor/motor_pwm/dc_motor.c b/tools/motor/motor_pwm/dc_motor.c
index d715ef8ad85142fe7d7be3e15b29e69d3b11bfce..9b5d9b00d0a0a04078b1549ecba9ea1acadab011 100644
--- a/tools/motor/motor_pwm/dc_motor.c
+++ b/tools/motor/motor_pwm/dc_motor.c
@@ -4,8 +4,8 @@
#include "pid.h"
#include
-//ֵֵǶȵĻ
-#define DCMOTOR_DGR2CODE(dgr,rdcr,encode) ((int32_t)((dgr)*encode/360.0f*(rdcr))) //ٱ*һȦֵ/360
+//各种电机编码值与角度的换算
+#define DCMOTOR_DGR2CODE(dgr,rdcr,encode) ((int32_t)((dgr)*encode/360.0f*(rdcr))) //减速比*编码器一圈值/360
#define DCMOTOR_CODE2DGR(code,rdcr,encode) ((float)((code)/(encode/360.0f*(rdcr))))
typedef struct
@@ -23,16 +23,16 @@ typedef struct _DCmotor
MotorCtrlMode mode;
- uint32_t angle,lastAngle;//¼һεõĽǶ
+ uint32_t angle,lastAngle;//记录上一次得到的角度
int16_t speed;
- int32_t totalAngle;//ۼתıֵ
+ int32_t totalAngle;//累计转过的编码器值
- float targetValue;//Ŀֵ(/ٶ/Ƕ(λ))
+ float targetValue;//目标值(输出轴/速度/角度(单位度))
- PID speedPID;//ٶpid()
- CascadePID anglePID;//Ƕpid
+ PID speedPID;//速度pid(单级)
+ CascadePID anglePID;//角度pid,串级
}DcMotor;
@@ -45,7 +45,7 @@ void DcMotor_ChangeMode(Motor* motor, MotorCtrlMode mode);
void DcMotor_StatAngle(DcMotor* dcMotor);
void DcMotor_CtrlerCalc(DcMotor* dcMotor, float reference);
-//ʱص
+//软件定时器回调函数
void DcMotor_TimerCallback(void const *argument)
{
DcMotor* dcMotor = pvTimerGetTimerID((TimerHandle_t)argument);
@@ -55,40 +55,40 @@ void DcMotor_TimerCallback(void const *argument)
Motor* DcMotor_Init(ConfItem* dict)
{
- //ڴռ
+ //分配子类内存空间
DcMotor* dcMotor = MOTOR_MALLOC_PORT(sizeof(DcMotor));
memset(dcMotor,0,sizeof(DcMotor));
- //̬
+ //子类多态
dcMotor->motor.setTarget = DcMotor_SetTarget;
dcMotor->motor.changeMode = DcMotor_ChangeMode;
dcMotor->motor.initTotalAngle = DcMotor_InitTotalAngle;
- //ٱ
- dcMotor->reductionRatio = Conf_GetValue(dict, "reduction-ratio", float, 19.0f);//ٱȲ
- dcMotor->circleEncode = Conf_GetValue(dict, "max-encode", float, 48.0f); //ƵתһȦֵ
- //ʼtimϢ
+ //电机减速比
+ dcMotor->reductionRatio = Conf_GetValue(dict, "reduction-ratio", float, 19.0f);//电机减速比参数
+ dcMotor->circleEncode = Conf_GetValue(dict, "max-encode", float, 48.0f); //倍频后编码器转一圈的最大值
+ //初始化电机绑定tim信息
DcMotor_TimInit(dcMotor, dict);
- //õĬģʽΪٶģʽ
+ //设置电机默认模式为速度模式
dcMotor->mode = MOTOR_TORQUE_MODE;
- //ʼpid
+ //初始化电机pid
DcMotor_PIDInit(dcMotor, dict);
- //ʱ
+ //开启软件定时器
osTimerDef(DCMOTOR, DcMotor_TimerCallback);
osTimerStart(osTimerCreate(osTimer(DCMOTOR), osTimerPeriodic,dcMotor), 2);
return (Motor*)dcMotor;
}
-//ʼpid
+//初始化pid
void DcMotor_PIDInit(DcMotor* dcMotor, ConfItem* dict)
{
PID_Init(&dcMotor->speedPID, Conf_GetPtr(dict, "speed-pid", ConfItem));
PID_Init(&dcMotor->anglePID.inner, Conf_GetPtr(dict, "angle-pid/inner", ConfItem));
PID_Init(&dcMotor->anglePID.outer, Conf_GetPtr(dict, "angle-pid/outer", ConfItem));
- PID_SetMaxOutput(&dcMotor->anglePID.outer, dcMotor->anglePID.outer.maxOutput*dcMotor->reductionRatio);//ٶŴת
+ PID_SetMaxOutput(&dcMotor->anglePID.outer, dcMotor->anglePID.outer.maxOutput*dcMotor->reductionRatio);//将输出轴速度限幅放大到转子上
}
-//ʼtim
+//初始化tim
void DcMotor_TimInit(DcMotor* dcMotor, ConfItem* dict)
{
dcMotor->posRotateTim.timX = Conf_GetValue(dict,"pos-rotate-tim/tim-x",uint8_t,0);
@@ -98,7 +98,7 @@ void DcMotor_TimInit(DcMotor* dcMotor, ConfItem* dict)
dcMotor->encodeTim.channelX = Conf_GetValue(dict,"encode-tim/tim-x",uint8_t,0);
}
-//ʼͳƵۼƽǶ
+//开始统计电机累计角度
void DcMotor_InitTotalAngle(Motor *motor, float startAngle)
{
DcMotor* dcMotor = (DcMotor*)motor;
@@ -107,13 +107,15 @@ void DcMotor_InitTotalAngle(Motor *motor, float startAngle)
dcMotor->lastAngle=dcMotor->angle;
}
-//ͳƵۼתȦ
+//统计电机累计转过的圈数
void DcMotor_StatAngle(DcMotor* dcMotor)
{
int32_t dAngle=0;
uint32_t autoReload=0;
- Bus_RemoteCall("/tim/encode",{{"tim-x",&dcMotor->encodeTim.timX},{"count",&dcMotor->angle},{"auto-reload",&autoReload}});
+ Bus_RemoteCall("/tim/encode",{{"tim-x", {.U8 = dcMotor->encodeTim.timX}},
+ {"count", {.U32 = dcMotor->angle}},
+ {"auto-reload", {.U32 = autoReload}}});
if(dcMotor->angle - dcMotor->lastAngle < -(autoReload/2.0f))
dAngle = dcMotor->angle+(autoReload-dcMotor->lastAngle);
@@ -121,15 +123,15 @@ void DcMotor_StatAngle(DcMotor* dcMotor)
dAngle = -dcMotor->lastAngle - (autoReload - dcMotor->angle);
else
dAngle = dcMotor->angle - dcMotor->lastAngle;
- //Ƕ
+ //将角度增量加入计数器
dcMotor->totalAngle += dAngle;
- //ٶ
+ //计算速度
dcMotor->speed = (float)dAngle/(dcMotor->circleEncode*dcMotor->reductionRatio)*500*60;//rpm
- //¼Ƕ
+ //记录角度
dcMotor->lastAngle=dcMotor->angle;
}
-//ģʽ
+//控制器根据模式计算输出
void DcMotor_CtrlerCalc(DcMotor* dcMotor, float reference)
{
float output=0;
@@ -150,19 +152,27 @@ void DcMotor_CtrlerCalc(DcMotor* dcMotor, float reference)
if(output>0)
{
- Bus_RemoteCall("/tim/pwm/set-duty",{{"tim-x",&dcMotor->posRotateTim.timX},{"channel-x",&dcMotor->posRotateTim.channelX},{"duty",&output}});
- Bus_RemoteCall("/tim/pwm/set-duty",{{"tim-x",&dcMotor->posRotateTim.timX},{"channel-x",&dcMotor->negRotateTim.channelX},{"duty",IM_PTR(float, 0)}});
+ Bus_RemoteCall("/tim/pwm/set-duty", {{"tim-x", {.U8 = dcMotor->posRotateTim.timX}},
+ {"channel-x", {.U8 = dcMotor->posRotateTim.channelX}},
+ {"duty", {.F32 = output}}});
+ Bus_RemoteCall("/tim/pwm/set-duty", {{"tim-x", {.U8 = dcMotor->posRotateTim.timX}},
+ {"channel-x", {.U8 = dcMotor->negRotateTim.channelX}},
+ {"duty", {.F32 = 0.0f}}});
}
else
{
output = ABS(output);
- Bus_RemoteCall("/tim/pwm/set-duty",{{"tim-x",&dcMotor->posRotateTim.timX},{"channel-x",&dcMotor->posRotateTim.channelX},{"duty",IM_PTR(float, 0)}});
- Bus_RemoteCall("/tim/pwm/set-duty",{{"tim-x",&dcMotor->posRotateTim.timX},{"channel-x",&dcMotor->negRotateTim.channelX},{"duty",&output}});
+ Bus_RemoteCall("/tim/pwm/set-duty", {{"tim-x", {.U8 = dcMotor->posRotateTim.timX}},
+ {"channel-x", {.U8 = dcMotor->posRotateTim.channelX}},
+ {"duty", {.F32 = 0.0f}}});
+ Bus_RemoteCall("/tim/pwm/set-duty", {{"tim-x", {.U8 = dcMotor->posRotateTim.timX}},
+ {"channel-x", {.U8 = dcMotor->negRotateTim.channelX}},
+ {"duty", {.F32 = output}}});
}
}
-//õֵ
+//设置电机期望值
void DcMotor_SetTarget(Motor* motor, float targetValue)
{
DcMotor* dcMotor = (DcMotor*)motor;
@@ -180,7 +190,7 @@ void DcMotor_SetTarget(Motor* motor, float targetValue)
}
}
-//лģʽ
+//切换电机模式
void DcMotor_ChangeMode(Motor* motor, MotorCtrlMode mode)
{
DcMotor* dcMotor = (DcMotor*)motor;
diff --git a/tools/motor/motor_pwm/servo.c b/tools/motor/motor_pwm/servo.c
index 835a3cd9dea00cabb6fcabaad1967fe885e80ff2..5069d9c63d6e39c2075b37964e449dc1bf8ef151 100644
--- a/tools/motor/motor_pwm/servo.c
+++ b/tools/motor/motor_pwm/servo.c
@@ -10,7 +10,7 @@ typedef struct _Servo
uint8_t timX;
uint8_t channelX;
}timInfo;
- float targetAngle;//ĿǶ(λ)
+ float targetAngle;//目标角度(单位度)
float maxAngle;
float maxDuty,minDuty;
}Servo;
@@ -21,12 +21,12 @@ void Servo_SetTarget(Motor* motor,float targetValue);
Motor* Servo_Init(ConfItem* dict)
{
- //ڴռ
+ //分配子类内存空间
Servo* servo = MOTOR_MALLOC_PORT(sizeof(Servo));
memset(servo,0,sizeof(Servo));
- //̬
+ //子类多态
servo->motor.setTarget = Servo_SetTarget;
- //ʼTIMϢ
+ //初始化电机绑定TIM信息
servo->timInfo.timX = Conf_GetValue(dict,"tim-x",uint8_t,0);
servo->timInfo.channelX = Conf_GetValue(dict,"channel-x",uint8_t,0);
servo->maxAngle = Conf_GetValue(dict,"max-angle",float,180);
@@ -36,13 +36,15 @@ Motor* Servo_Init(ConfItem* dict)
return (Motor*)servo;
}
-//öǶ
+//设置舵机角度
void Servo_SetTarget(Motor* motor,float targetValue)
{
Servo* servo=(Servo*) motor;
- servo->targetAngle = targetValue; //ʵ;debug
+ servo->targetAngle = targetValue; //无实际用途,可用于debug
float pwmDuty = servo->targetAngle / servo->maxAngle * (servo->maxDuty - servo->minDuty) + servo->minDuty;
- Bus_RemoteCall("/tim/pwm/set-duty", {{"tim-x", &servo->timInfo.timX}, {"channel-x", &servo->timInfo.channelX}, {"duty", &pwmDuty}});
+ Bus_RemoteCall("/tim/pwm/set-duty", {{"tim-x", {.U8 = servo->timInfo.timX}},
+ {"channel-x", {.U8 = servo->timInfo.channelX}},
+ {"duty", {.F32 = pwmDuty}}});
}
diff --git a/tools/slope/slope.c b/tools/slope/slope.c
index 6b9641f9b01fcc37d9e37c0745826fd29ec791d1..b1a5b346cef30a167431b2f029b8d1e2bc2416ec 100644
--- a/tools/slope/slope.c
+++ b/tools/slope/slope.c
@@ -1,6 +1,6 @@
#include "slope.h"
-//ʼб²
+//初始化斜坡参数
void Slope_Init(Slope *slope,float step,float deadzone)
{
slope->target=0;
@@ -9,27 +9,27 @@ void Slope_Init(Slope *slope,float step,float deadzone)
slope->deadzone=deadzone;
}
-//趨бĿ
+//设定斜坡目标
void Slope_SetTarget(Slope *slope,float target)
{
slope->target=target;
}
-//趨б²
+//设定斜坡步长
void Slope_SetStep(Slope *slope,float step)
{
slope->step=step;
}
-//һбֵslope->valueظֵ
+//计算下一个斜坡值,更新slope->value并返回该值
float Slope_NextVal(Slope *slope)
{
- float error=slope->value-slope->target;//ǰֵĿֵIJֵ
+ float error=slope->value-slope->target;//当前值与目标值的差值
- if(ABS(error)deadzone)//ǰֵ仯
+ if(ABS(error)deadzone)//若误差在死区内则当前值不发生变化
return slope->value;
- if(ABS(error)step)//㲽ǰֱֵΪĿֵ
+ if(ABS(error)step)//若误差不足步长则当前值直接设为目标值
slope->value=slope->target;
else if(error<0)
slope->value+=slope->step;
@@ -38,7 +38,7 @@ float Slope_NextVal(Slope *slope)
return slope->value;
}
-//ȡбµǰֵ
+//获取斜坡当前值
float Slope_GetVal(Slope *slope)
{
return slope->value;
diff --git a/tools/universal_queue/my_queue.c b/tools/universal_queue/my_queue.c
index 5c61bbc05d5a2b0ac0c20b6097a9fef8d5591cd7..ecdfb54daed43113d6d709609188bfbca428456d 100644
--- a/tools/universal_queue/my_queue.c
+++ b/tools/universal_queue/my_queue.c
@@ -1,10 +1,10 @@
-/****************ͨѭ*****************/
+/****************通用循环队列*****************/
#include "my_queue.h"
#include
#include
-//ʼ
+//初始化队列
void Queue_Init(Queue *queue,uint16_t maxSize)
{
queue->data=malloc(maxSize*sizeof(void*));
@@ -13,8 +13,8 @@ void Queue_Init(Queue *queue,uint16_t maxSize)
queue->maxSize=maxSize;
}
-//һݱ(ʱὫݸƵӦλ)
-//עⱣССڶгȣԽ
+//附加上一个数据保存区(入队时会将数据复制到保存区对应位置)
+//注意保存区大小不得小于队列长度,否则会越界
void Queue_AttachBuffer(Queue *queue,void *buffer,uint8_t elemSize)
{
if(!queue->initialized) return;
@@ -22,7 +22,7 @@ void Queue_AttachBuffer(Queue *queue,void *buffer,uint8_t elemSize)
queue->bufElemSize=elemSize;
}
-//һ
+//销毁一个队列
void Queue_Destroy(Queue *queue)
{
if(!queue->initialized) return;
@@ -30,28 +30,28 @@ void Queue_Destroy(Queue *queue)
memset(queue,0,sizeof(Queue));
}
-//ȡг
+//获取队列长度
uint16_t Queue_Size(Queue *queue)
{
if(!queue->initialized) return 0;
return (queue->rear+queue->maxSize-queue->front)%queue->maxSize;
}
-//ǷΪ
+//队列是否为满
uint8_t Queue_IsFull(Queue *queue)
{
if(!queue->initialized) return 1;
return (queue->front==(queue->rear+1)%queue->maxSize)?1:0;
}
-//ǷΪ
+//队列是否为空
uint8_t Queue_IsEmpty(Queue *queue)
{
if(!queue->initialized) return 1;
return (queue->front==queue->rear)?1:0;
}
-//ȡָλõԪ(ͷԪλΪ0)
+//获取队列指定位置的元素(队头元素位置为0)
void* Queue_GetElement(Queue *queue,uint16_t position)
{
if(!queue->initialized) return NULL;
@@ -61,7 +61,7 @@ void* Queue_GetElement(Queue *queue,uint16_t position)
return queue->data[(queue->front+position)%queue->maxSize];
}
-//ȡͷԪ()
+//获取队头元素(但不出队)
void* Queue_Top(Queue *queue)
{
if(!queue->initialized) return NULL;
@@ -71,7 +71,7 @@ void* Queue_Top(Queue *queue)
return queue->data[queue->front];
}
-//
+//出队
void* Queue_Dequeue(Queue *queue)
{
if(!queue->initialized) return NULL;
@@ -83,19 +83,19 @@ void* Queue_Dequeue(Queue *queue)
return res;
}
-//
+//入队
void Queue_Enqueue(Queue *queue,void* data)
{
if(!queue->initialized) return;
if(Queue_IsFull(queue)) return;
- //ָΪ˵δӱԭʼָ
+ //如果缓冲区指针为空说明未附加保存区,入队原始指针
if(queue->buffer == NULL)
{
queue->data[queue->rear]=data;
}
- else//˱ݸƹӱָ
+ else//若加了保存区则将数据复制过来并入队保存区的指针
{
memcpy((uint8_t*)(queue->buffer) + (queue->rear)*(queue->bufElemSize),
data,
diff --git a/tools/universal_vector/vector.c b/tools/universal_vector/vector.c
index 3cea1b097fedbfb6bbfaa0854e88d49b69c82778..85366701840f8f4ba9221bde39a3dfb6605d8d26 100644
--- a/tools/universal_vector/vector.c
+++ b/tools/universal_vector/vector.c
@@ -1,14 +1,14 @@
#include "vector.h"
-//ñ⺯ڴͨĺ궨ֲ
-#include
+//引用标准库函数用于内存操作,可通过修改宏定义进行移植
+#include
#include
#include "cmsis_os.h"
#define VECTOR_MALLOC_PORT(len) pvPortMalloc(len)
#define VECTOR_FREE_PORT(ptr) vPortFree(ptr)
#define VECTOR_MEMCPY_PORT(dst,src,len) memcpy(dst,src,len)
-//ʼ, ɹ0ʧܷ-1
+//初始化, 成功返回0失败返回-1
int _Vector_Init(Vector *vector, int _elementSize)
{
vector->elementSize=_elementSize;
@@ -20,7 +20,7 @@ int _Vector_Init(Vector *vector, int _elementSize)
return 0;
}
-//ʼһvector
+//创建并初始化一个vector
Vector _Vector_Create(int _elementSize)
{
Vector vector;
@@ -28,19 +28,19 @@ Vector _Vector_Create(int _elementSize)
return vector;
}
-//һvector
+//销毁一个vector
void _Vector_Destroy(Vector *vector)
{
if(vector->data)
VECTOR_FREE_PORT(vector->data);
}
-//Ԫ, ɹ0ʧܷ-1
+//插入元素, 成功返回0失败返回-1
int _Vector_Insert(Vector *vector, uint32_t index, void *element)
{
if(!vector->data || index > vector->size)
return -1;
- if(vector->size+1 > vector->capacity) //ʣռ䲻㣬·ռ䲢
+ if(vector->size+1 > vector->capacity) //若剩余空间不足,重新分配两倍空间并拷贝数据
{
uint8_t *newBuf=VECTOR_MALLOC_PORT(vector->capacity * 2 * vector->elementSize);
if(!newBuf)
@@ -50,57 +50,57 @@ int _Vector_Insert(Vector *vector, uint32_t index, void *element)
VECTOR_FREE_PORT(vector->data);
vector->data=newBuf;
}
- if(vector->size > 0 && index <= vector->size-1) //ݺ
+ if(vector->size > 0 && index <= vector->size-1) //将插入点后的数据后移
{
for(int32_t pos=vector->size-1; pos>=(int32_t)index; pos--)
VECTOR_MEMCPY_PORT(vector->data + (pos+1) * vector->elementSize, vector->data + pos * vector->elementSize, vector->elementSize);
}
- VECTOR_MEMCPY_PORT(vector->data + index * vector->elementSize, element, vector->elementSize); //ûֵ
+ VECTOR_MEMCPY_PORT(vector->data + index * vector->elementSize, element, vector->elementSize); //拷贝用户传入的值
vector->size++;
return 0;
}
-//ɾԪ, ɹ0ʧܷ-1
+//删除元素, 成功返回0失败返回-1
int _Vector_Remove(Vector *vector, uint32_t index)
{
if(!vector->data || vector->size==0 || index >= vector->size)
return -1;
- for(uint32_t pos=index; pos<(vector->size-1); pos++) //ɾǰ
+ for(uint32_t pos=index; pos<(vector->size-1); pos++) //将删除点后的数据前移
VECTOR_MEMCPY_PORT(vector->data + pos * vector->elementSize, vector->data + (pos+1) * vector->elementSize, vector->elementSize);
vector->size--;
return 0;
}
-//ȡָλϵԪָ, ʧܷNULL
+//获取指定位置上的元素指针, 若失败返回NULL
void *_Vector_GetByIndex(Vector *vector, uint32_t index)
{
if(index >= vector->size)
return NULL;
- return vector->data + index * vector->elementSize; //ƫƣصַ
+ return vector->data + index * vector->elementSize; //计算偏移,返回地址
}
-//ָλϵԪ, ɹ0ʧܷ-1
+//修改指定位置上的元素, 成功返回0失败返回-1
int _Vector_SetValue(Vector *vector, uint32_t index, void *element)
{
if(index >= vector->size || !vector->data)
return -1;
- VECTOR_MEMCPY_PORT(vector->data + index * vector->elementSize, element, vector->elementSize); //ûֵĿַ
+ VECTOR_MEMCPY_PORT(vector->data + index * vector->elementSize, element, vector->elementSize); //拷贝用户传入的值到目标地址
return 0;
}
-//ɾĿռ, ɹ0ʧܷ-1
+//删除多余的空间, 成功返回0失败返回-1
int _Vector_TrimCapacity(Vector *vector)
{
if(!vector->data)
return -1;
if(vector->capacity <= vector->size)
return 0;
- int newCapacity=(vector->size ? vector->size : 1); //¿ռС
- uint8_t *newBuf=VECTOR_MALLOC_PORT(newCapacity * vector->elementSize); //¿ռ
+ int newCapacity=(vector->size ? vector->size : 1); //计算新空间大小
+ uint8_t *newBuf=VECTOR_MALLOC_PORT(newCapacity * vector->elementSize); //分配新空间
if(!newBuf)
return -1;
if(vector->size)
- VECTOR_MEMCPY_PORT(newBuf, vector->data, vector->size * vector->elementSize); //ԭ
+ VECTOR_MEMCPY_PORT(newBuf, vector->data, vector->size * vector->elementSize); //拷贝原有数据
VECTOR_FREE_PORT(vector->data);
vector->data=newBuf;
vector->capacity=newCapacity;