add tutorial

This commit is contained in:
NeoZng 2022-11-12 18:03:18 +08:00
parent 0fb67070b8
commit 82a55d7eca
27 changed files with 341 additions and 114 deletions

27
.vscode/launch.json vendored
View File

@ -1,24 +1,25 @@
{
"version": "0.2.0",
"configurations": [
{
{ // 使dap-link(线)
"name": "Debug-dap",
"cwd": "${workspaceRoot}",
"executable": "${workspaceRoot}\\build\\basic_framework.elf",
"executable": "${workspaceRoot}\\build\\basic_framework.elf", //
"request": "launch",
"type": "cortex-debug",
"device":"STM32F407IG", //使J-link GDB ServerGBD ServerSVD https://www.segger.com/downloads/supported-devices.php
"svdFile": ".\\STM32F407.svd", //svd https://github.com/posborne/cmsis-svd
"servertype": "openocd", //使GDB Server
"configFiles":[
".\\openocd.cfg",
"device": "STM32F407IG", //使J-link GDB Server;GBD ServerSVD https://www.segger.com/downloads/supported-devices.php
"svdFile": ".\\STM32F407.svd", //svd https://github.com/posborne/cmsis-svd
// C使svd
"servertype": "openocd", //使GDB Server
"configFiles": [
".\\openocd.cfg", // ,
],
// path to your gcc-arm-none-eabi/bin
// path to your gcc-arm-none-eabi/bin,cortex-debug,
"armToolchainPath": "D:\\gcc-arm-none-eabi\\bin",
// path to your gcc-arm-none-eabi/arm-none-eabi-gdb.exe
"gdbPath": "D:\\gcc-arm-none-eabi\\bin\\arm-none-eabi-gdb.exe"
// path to your gcc-arm-none-eabi/arm-none-eabi-gdb.exe,cortex-debug,
"gdbPath": "D:\\gcc-arm-none-eabi\\bin\\arm-none-eabi-gdb.exe"
},
{
{ // 使j-link
"name": "Debug-jlink",
"cwd": "${workspaceFolder}",
"executable": "${workspaceRoot}\\build\\basic_framework.elf",
@ -29,8 +30,10 @@
"showDevDebugOutput": "none",
"servertype": "jlink",
"interface": "swd",
//cortex-debug,
"armToolchainPath": "D:\\gcc-arm-none-eabi\\bin",
"gdbPath": "D:\\gcc-arm-none-eabi\\bin\\arm-none-eabi-gdb.exe"
//cortex-debug,
"gdbPath": "D:\\gcc-arm-none-eabi\\bin\\arm-none-eabi-gdb.exe"
}
]
}

View File

@ -105,6 +105,7 @@ bsp/bsp_can.c \
bsp/bsp_buzzer.c \
bsp/bsp_usart.c \
bsp/bsp_log.c \
bsp/bsp_init.c \
\ \
modules/algorithm/controller.c \
modules/algorithm/kalman_filter.c \
@ -117,6 +118,7 @@ modules/master_machine/master_process.c \
modules/motor/dji_motor.c \
modules/motor/HT04.c \
modules/motor/LK9025.c \
modules/mode/step_motor.c \
modules/motor/motor_task.c \
modules/referee/referee.c \
modules/referee/referee_UI.c \
@ -125,7 +127,8 @@ modules/remote/remote_control.c \
modules/super_cap/super_cap.c \
modules/master_machine/seasky_protocol.c \
modules/algorithm/crc8.c \
modules/algorithm/crc16.c
modules/algorithm/crc16.c \
modules/can_comm/can_comm.c
# ASM sources

View File

@ -100,10 +100,11 @@ Module层主要存放的是类型定义和实例指针数组在该层没有
## 文件树
板级支持包的每个组件,每个moduel,每个app都有对应的说明文档.
```shell
ROOT:.
│ .gitignore # git版本管理忽略文件
│ .mxproject # CubeMX项目文件
│ .mxproject # CubeMX项目文件
│ basic_framework.ioc # CubeMX初始化配置文件
│ Makefile # 编译管理文件,为make命令的目标
│ openocd.cfg # 用于OpenOCD调试使用的配置文件
@ -111,39 +112,50 @@ ROOT:.
│ startup_stm32f407xx.s # F407汇编启动文件
│ STM32F407.svd # F407外设地址映射文件,用于调试
│ STM32F407IGHx_FLASH.ld # F407IGH(C板使用的MCU)的文件目标FLASH地址,用于烧录和调试
│ VSCode+Ozone使用方法.md # 开发环境配置
|
├─.vscode
│ launch.json # 用于VSCode插件CORTEX-DEBUG调试的配置文件
├─application # 应用层,包括底盘控制,云台控制和发射控制
│ chassis.c
│ chassis.h
│ chassis.md
│ gimbal.c
│ gimbal.h
│ gimbal.md
│ shoot.c
│ shoot.h
│ shoot.md
├─bsp # 板级支持包,提供对硬件的封装,将接口暴露给module层
│ bsp.md
│ bsp_buzzer.c
│ bsp_buzzer.h
│ bsp_can.c
│ bsp_can.h
│ bsp_can.md
│ bsp_dwt.c
│ bsp_dwt.h
│ bsp_init.c
│ bsp_init.h
│ bsp_led.c
│ bsp_led.h
│ bsp_log.c
│ bsp_log.h
│ bsp_log.md
│ bsp_temperature.c
│ bsp_temperature.h
│ bsp_usart.c
│ bsp_usart.h
│ bsp_usart.md
│ struct_typedef.h
├─HAL_N_Middlewares # HAL库对寄存器操作的封装,以及FreeRTOS等中间件
|
└─modules # 模块层,使用BSP提供的接口构建对应的功能模块,将模块实例提供给应用层
├─algorithm # 算法
│ algorithm.md
│ controller.c # 控制器
│ controller.h
│ crc16.c # 循环冗余校验
@ -159,6 +171,11 @@ ROOT:.
│ user_lib.c # 多个模块都会使用到的函数
│ user_lib.h
├─can_comm # 双板CAN通信组件
│ can_comm.c
│ can_comm.h
│ can_comm.md
|
├─imu # 考虑到使用SPI的设备较少,这里没有对SPI提供bsp支持,直接于此实现
│ BMI088driver.c
│ BMI088driver.h
@ -173,10 +190,12 @@ ROOT:.
│ led_task.h
├─master_machine # 和上位机(视觉PC)通信的模块
│ master_process.c
│ master_process.c
│ master_process.h
│ seasky_protocol.c # 视觉通信协议
│ master_process.md
│ seasky_protocol.c
│ seasky_protocol.h
│ 湖南大学RoboMaster电控组通信协议.md
├─motor # 电机模块
│ dji_motor.c # DJI智能电机
@ -193,7 +212,8 @@ ROOT:.
│ referee.c # 接收裁判系统信息
│ referee.h
│ referee_UI.c # UI绘制(发送)
│ referee_communication.c # 多机通信
|
├─remote # 遥控器模块
│ remote_control.c
│ remote_control.h

View File

@ -1,2 +1,199 @@
# VSCode+Ozone使用方法
# VSCode+Ozone开发STM32的方法
<center><b><font face="楷体">neozng1@hnu.edu.cn</font></b></center>
[TOC]
## 前言
了解过嵌入式开发的你一定接触过Keil这款20世纪风格UI的IDE伴随很多人度过了学习单片机的岁月。然而由于其缺少代码补全、高亮和静态检查的支持以及为人诟病的一系列逆天的设置、极慢的编译速度特别是在开发HAL库时很多开发者开始转向其他IDE。
IAR、CubeIDE等都是广为使用的“其他”IDE但是他们也有各自的缺点不能让笔者满意。作为IDE界的艺术家JetBrains推出的Clion也在相当程度上完善了对嵌入式开发的支持。不过在体验过多款IDE后还是**VSCode**这款高度定制化的编辑器最让人满意。
而Ozone则是SEGGER(做jilnk的)推出的调试应用支持变量实时更新变量曲线可视化SEGGER RTT日志DBG虚拟串口等功能大大扩展了调试的功能。很多人习惯使用串口进行可视化调试如vofa串口调试助手等。然而通过这些方式进行调试都是对内核有**侵入性**的会占有内核资源并且导致定时器的时间错乱。由于DBG有单独连接到FLASH和CPU寄存器的高速总线类似于DMA可以在不影响程序正常运行的情况下以极高的频率直接获取变量值。
下面将从工具链介绍、环境配置以及调试工作流三个方面介绍以VSCode为编辑器Ozone为调试接口的开发环境。
开发的大致流程为:
~~~mermaid
graph LR
CubeMX进行初始化 --> VSCode编写代/进行编译/简单调试 --> Ozone变量可视化调试+log
~~~
## 前置知识
1. 计算机速成课:[Crash Course Computer Science](https://www.bilibili.com/video/av21376839/?vd_source=ddae2b7332590050afe28928f52f0bda)
2. 从零到一打造一台计算机:
[编程前你最好了解的基本硬件和计算机基础知识(模拟电路)](https://www.bilibili.com/video/BV1774114798/?spm_id_from=333.788.recommend_more_video.11&vd_source=ddae2b7332590050afe28928f52f0bda)
[编程前你最好了解的基本硬件和计算机基础知识(数字电路)](https://www.bilibili.com/video/BV1Hi4y1t7zY/?spm_id_from=333.788.recommend_more_video.0)
[从0到1设计一台计算机](https://www.bilibili.com/video/BV1wi4y157D3/?spm_id_from=333.788.recommend_more_video.0&vd_source=ddae2b7332590050afe28928f52f0bda)
3. C语言基础[程序设计入门——C语言](https://www.icourse163.org/course/ZJU-199001?from=searchPage&outVendor=zw_mooc_pcssjg_)
***务必学完以上课程再开始本教程的学习。***
## 预备知识
1. 软件安装(队伍NAS和资料硬盘内提供了所有必要的依赖,安装包和插件)
2. C语言从源代码到.bin和.hex等机器代码的编译和链接过程
3. C语言的内存模型
4. C语言标准动态链接库和静态编译的区别一些编译器的常用选项
5. STM32F4系列的DBG外设工作原理
### 编译全过程
C语言代码由固定的词汇关键字按照固定的格式语法组织起来简单直观程序员容易识别和理解但是CPU只能识别二进制形式的指令并且这些指令是和硬件相关的感兴趣的同学可以搜索**指令集**相关内容。这就需要一个工具将C语言代码转换成CPU能够识别的二进制指令对于我们的x86平台windows下的程序就是.exe后缀的文件对于单片机一般来说是.bin或.hex等格式的文件调试文件包括axf和elf
能够完成这个转化过程的工具是一个特殊的软件,叫做**编译器Compiler**。常见的编译器包括开源的GNU GCCwindows下微软开发的visual C++以及apple主导的llvm/clang。编译器能够识别代码中的关键字、表达式以及各种特定的格式并将他们转换成特定的符号也就是**汇编语言**(再次注意汇编语言是平台特定的),这个过程称为**编译Compile**。
对于单个.c文件从C语言开始到单片机可识别的.bin文件一般要经历以下几步
![img](https://pic3.zhimg.com/80/v2-2797ea99d0d38eb9996993bb0ad77ab2_720w.webp)
首先是编译**预处理**Preprocessing这一步会展开宏并删除注释将多余的空格去除。预处理之后会生成.i文件。
然后,开始**编译**Compilation的工作。编译器会将源代码进行语法分析、词法分析、语义分析等根据编译设置进行性能优化然后生成汇编代码.s文件。汇编代码仍然是以助记符的形式记录的文本比如将某个地址的数据加载到CPU寄存器等还需要进一步翻译成二进制代码。
下一步就是进行**汇编**Assemble编译器会根据汇编助记符和机器代码的查找表将所有符号进行替换生成.o .obj等文件。但请注意这些文件并不能直接使用烧录我们在编写代码的时候都会包含一些**库**,因此编译结果应当有多个.o文件。我们还需要一种方法将这些目标文件缝合在一起使得在遇到函数调用的时候程序可以正确地跳转到对应的地方执行。
最后一步就由链接器Linker也称LD完成称为**链接**Linking。比如你编写了一个motor.c文件和.h文件并在main.c中包含了motor.h使用了后者提供的`MotorControl()`函数。那么,链接器会根据编译器生成.obj文件时留下的函数入口地址将main.o里的调用映射到生成的motor.o中。链接完成后就生成了单片机可以识别的可执行文件通过支持的串口或下载器烧录便可以运行。
> 另外,上图可以看到左侧的**静态库**,包括`.lib .a`比如我们在STM32中使用的DSP运算库就是这种文件。他在本质上和.o文件相同只要你在你编写的源文件中包含了这些库的头文件链接器就可以根据映射关系找到头文件中声明的函数在库文件的地址。直接提供库而不是.c文件就可以防止源代码泄露因此一些不开源的程序会提供函数调用的头文件和接口具体实现的库你也可以编写自己的库感兴趣自行搜索
链接之后,实际上还要进行不同代码片段的重组、地址重映射,详细的内容请参看:[C/C++语言编译链接过程](https://zhuanlan.zhihu.com/p/88255667)这篇教程还提供了以GCC为例的代码编译示例。
### C语言内存模型
<img src="C:\Users\Neo\AppData\Roaming\Typora\typora-user-images\image-20221112160213066.png" alt="image-20221112160213066" style="zoom:80%;" />
以上是C语言常见的内存模型即C语言的代码块以及运行时使用的内存包括函数、变量等的组织方式。
> 有些平台的图与此相反,栈在最下面(内存低地址),其他区域都倒置,不影响我们理解
**代码段**即我们编写的代码,也就是前面说的编译和链接之后最终生成的可执行文件占据的空间。一些常量,包括字符串和使用`const`关键字修饰的变量被放在常量存储区。`static`修饰的静态变量(包括函数静态变量和文件静态变量)以及全局变量放在常量区上面一点的全局区(也称静态区)。
然后就是最重要的**堆**和**栈**。在一个代码块内定义的变量会被放在栈区,一旦离开作用域(出了它被定义的`{}`的区域),就会立刻被销毁。在调用函数或进入一个用户自定义的`{}`块都会在栈上开辟一块新的空间空间的大小和内存分配由操作系统或C库自动管理。**一般来说,直接通过变量访问栈内存,速度最快**(对于单片机)。而堆则是存储程序员自行分配的变量的地方,即使用`malloc(),realloc() ,new`等方法获取的空间,都被分配在这里。
> 在CubeMX初始化的时候Project mananger标签页下有一个Linker Setting的选项这里是设置最小堆内存和栈内存的地方。如果你的程序里写了大规模的数组或使用`malloc()`等分配了大量的空间可能出现栈溢出或堆挤占栈空间的情况。需要根据MCU的资源大小设置合适的stack size和heap size。
### C language标准和编译器
不同的C语言标准一般以年份作代号支持的语法特性和关键字不同拥有的功能也不同。一般来说语言标准都是向前兼容的在更新之后仍然会保存前代的基本功能支持legacy support。不过为了程序能够正常运行我们还需要一些硬件或平台支持的组件。比如`malloc()`这个函数在linux平台和windows平台上的具体实现就相去甚远跟单片机更是差了不止一点。前两者一般和对应的操作系统有关后者在裸机上则是直接通过硬件或ST公司提供的硬件抽象层代码实现。
然而不同编译器提供的代码实现也不尽相同比如使用clang和gcc这两种c语言编译器他们对于一些标准库也称C库包括stdiostdlibstring等在内的实现的函数的实现就不太一样。再如`__packed`是arm-cc提供的一个字节不对齐关键字在一些其他编译器中就不支持这种实现。
以前大家常用的KEIL使用的是ARM提供的arm-cc工具链非常蛋疼甚至不支持uint8_t=0b00001111这种二进制定义法而该教程选用的是开源的**Arm GNU Toolchain**。在非目标机且和目标机平台不同的平台上进行开发被成为**跨平台开发**,进行的编译也被成为**交叉编译**(在一个平台上生成另一个平台上的 可执行代码)。
> 工具链包含了编译器链接器以及调试器等开发常用组件。我们使用的Arm GNU toolchain中编译器是`arm-none-eabi-gcc.exe`,链接器是`arm-none-eabi-ld.exe`,调试器则是`arm-none-eabi-gdb.exe`。通过跨平台调试器和j-link/st-link/dap-link我们就可以在自己的电脑上对异构平台即单片机的运行进行调试了。
### Debug外设工作原理
![image-20221112145717063](C:\Users\Neo\AppData\Roaming\Typora\typora-user-images\image-20221112145717063.png)
DBG支持模块红框标注部分也可以看作一个外设通过一条专用的AHB-AP总线和调试接口相连Jtag或swd并且有与**数据**和**外设**总线直接相连的桥接器。它还同时连接了中断嵌套管理器因此同样可以捕获中断并进行debug和ITM、DWT、FPB这些调试支持模块。因此DBG可以直接获取内存或片上外设内的数据而不需要占用CPU的资源并将这些数据通过专用外设总线发送给调试器进而在上位机中读取。
FPB是flash patch breakpoint闪存指令断点的缩写用于提供代码断点插入的支持当CPU的指令寄存器读取到某一条指令时FPB会监测到它的动作并通知TPIU暂停CPU进行现场保护。
DWT是data watch trace数据观察与追踪单元的缩写用于比较debug变量的大小并追踪变量值的变化。当你设定了比较断点规则当某个数据大于/小于某个值时暂停程序或将变量加入watch进行查看DWT就会开始工作。DWT还提供了一个额外的计时器即所有可见的TIM资源之外的另一个硬件计时器因为调试其他硬件定时器的计时由于时钟变化可能定时不准而DWT定时器是始终正常运行的。它用于给自身和其他调试器模块产生的信息打上时间戳。我们的bsp中也封装了dwt计时器你可以使用它来计时。
ITM是instrument trace macrocell指令追踪宏单元的缩写它用于提供非阻塞式的日志发送支持相当于大家常用的串口调试SEGGER RTT就可以利用这个模块向上位机发送日志和信息。
以上三个模块都需要通过TPIUtrace port interface unit和外部调试器j-link等进行连接TPIU会将三个模块发来的数据进行封装并通过DWT记录时间发送给上位机。
## 环境配置
- 安装STM32CubeMX并安装F4支持包和DSP库支持包-
- 安装VSCode并安装C/C++Cortex-DebugCortex-Debug: Device Support Pack - STM32F4Better C++ SyntaxIntelliCodeMakfile ToolsC/C++ Snippets插件
![image-20221112172157533](C:\Users\Neo\AppData\Roaming\Typora\typora-user-images\image-20221112172157533.png)
![image-20221112172208749](C:\Users\Neo\AppData\Roaming\Typora\typora-user-images\image-20221112172208749.png)
![image-20221112172221756](C:\Users\Neo\AppData\Roaming\Typora\typora-user-images\image-20221112172221756.png)
![image-20221112172239386](C:\Users\Neo\AppData\Roaming\Typora\typora-user-images\image-20221112172239386.png)
![image-20221112172254809](C:\Users\Neo\AppData\Roaming\Typora\typora-user-images\image-20221112172254809.png)
- 安装MinGW等待界面如下
![image-20221112172051589](C:\Users\Neo\AppData\Roaming\Typora\typora-user-images\image-20221112172051589.png)
安装好后打开MinGW后将所有的支持包勾选然后安装
![image-20221112172348408](C:\Users\Neo\AppData\Roaming\Typora\typora-user-images\image-20221112172348408.png)
![image-20221112172420037](C:\Users\Neo\AppData\Roaming\Typora\typora-user-images\image-20221112172420037.png)
安装完以后将MinGW的bin文件夹添加到环境变量中的path下按下菜单键搜索**编辑系统环境变量**打开之后:
![image-20221112172716320](C:\Users\Neo\AppData\Roaming\Typora\typora-user-images\image-20221112172716320.png)
验证安装:
打开命令行win+Rcmd回车输入`gcc -v`,如果没有报错,并输出了一堆路径和参数说明安装成功。
- 配置gcc-arm-none-eabi环境变量
同上将工具链的bin添加到PATH
![image-20221112172858593](C:\Users\Neo\AppData\Roaming\Typora\typora-user-images\image-20221112172858593.png)
<center>安装路径可能不一样,这里要使用你自己的路径而不是直接抄</center>
验证安装:
打开命令行,输入`arm-none-eabi-gcc -v`,如果没有报错,并输出了一堆路径和参数说明安装成功。
> 添加到环境变量PATH的意思是当一些程序需要某些依赖或者要打开某些程序时系统会自动前往PATH下寻找对应项。**一般需要重启使环境变量生效。**
- **将OpenOCD解压到一个文件夹里**稍后需要在VSCode中设置这个路径。
- CubeMX生成代码的时候工具链选择makefile
![image-20221112173534670](C:\Users\Neo\AppData\Roaming\Typora\typora-user-images\image-20221112173534670.png)
生成的目录结构如下:
![image-20221112174211802](C:\Users\Neo\AppData\Roaming\Typora\typora-user-images\image-20221112174211802.png)
Makefile就是我们要使用的构建规则文件。
## VSCode编译和调试配置
### 编译
用VSCode打开创建的项目文件夹**Makefile Tools插件会询问你是否帮助配置intellisense选择是。**
### 简单调试
> 在VSCode中调试不能像Keil一样查看变量动态变化但是支持以外的所有操作如查看外设和反汇编代码设置断点触发方式等。
用于调试的配置参考这篇博客:[Cortex-debug 调试器使用介绍](https://blog.csdn.net/qq_40833810/article/details/106713462)
你需要配置**arm gnu工具链的路径****OpenOCD的路径**使得GDB调试器可以找到OpenOCD并调用它从而连接硬件调试器如j-link等该工作区文件夹的**launch.json文件**用于启动vscode的调试任务
如果教程看不懂,请看`.vscode`下的`launch.json`,照葫芦画瓢。
根目录下已经提供了C板所需的.svd和使用无线调试器时所用的openocd.cfg配置文件。
然后选择run and debug标签页在选项中选择你配置好的选项开始调试。
![image-20221112180103750](C:\Users\Neo\AppData\Roaming\Typora\typora-user-images\image-20221112180103750.png)

0
application/chassis.md Normal file
View File

0
application/gimbal.md Normal file
View File

0
application/shoot.md Normal file
View File

0
bsp/bsp.md Normal file
View File

0
bsp/bsp_init.c Normal file
View File

0
bsp/bsp_init.h Normal file
View File

View File

@ -0,0 +1,32 @@
# algorithms
<p align='right'>neozng1@hnu.edu.cn</p>
> TODO:
>
> 1. 实现麦轮和全向轮的速度解算
> 2. 实现LQR
> 3. 实现一些通用的滤波器,如指数平均,窗平均,低通等
> 4. 实现系统辨识
## 总览和使用
module层的algorithm提供了一些供其他模块以及app的应用层使用的算法包括
1. PID控制器`controller.h`
2. crc8 crc16循环冗余校验
3. 卡尔曼滤波器`kalman_filter.h`,可以通过用户自定义函数配置为扩展卡尔曼滤波
4. `LQR.h`,线性二次型调节器
5. `QuaterninoEKF.h`,用于`ins_task`的四元数姿态解算和扩展卡尔曼滤波融合
6. `user_lib.h`,一些通用的函数,包括限幅、数据类型转换、角度弧度转换、快速符号判断以及优化开方等功能。多个模块都会使用的、不好区分的函数可以放置于此
## 代码结构
.c 为算法的实现,.h为算法对外接口的头文件
在编写应用的时候,你基本不会使用这里的函数,或是修改其实现。
若发现bug或需要增加功能联系组长讨论。

View File

@ -2,7 +2,8 @@
******************************************************************************
* @file user_lib.c
* @author Wang Hongxi
* @version V1.0.0
* @author modified by neozng
* @version 0.2 beta
* @date 2021/2/18
* @brief
******************************************************************************
@ -24,7 +25,7 @@
uint8_t GlobalDebugMode = 7;
//快速开方
// 快速开方
float Sqrt(float x)
{
float y;
@ -51,29 +52,7 @@ float Sqrt(float x)
return y;
}
/**
* @brief /s
* @author RM
* @param[in]
* @param[in]
* @retval
*/
float ramp_calc(ramp_function_source_t *ramp_source_type, float input)
{
ramp_source_type->input = input;
ramp_source_type->out += ramp_source_type->input * ramp_source_type->frame_period;
if (ramp_source_type->out > ramp_source_type->max_value)
{
ramp_source_type->out = ramp_source_type->max_value;
}
else if (ramp_source_type->out < ramp_source_type->min_value)
{
ramp_source_type->out = ramp_source_type->min_value;
}
return ramp_source_type->out;
}
//绝对值限制
// 绝对值限制
float abs_limit(float num, float Limit)
{
if (num > Limit)
@ -87,7 +66,7 @@ float abs_limit(float num, float Limit)
return num;
}
//判断符号位
// 判断符号位
float sign(float value)
{
if (value >= 0.0f)
@ -100,7 +79,7 @@ float sign(float value)
}
}
//浮点死区
// 浮点死区
float float_deadband(float Value, float minValue, float maxValue)
{
if (Value < maxValue && Value > minValue)
@ -120,7 +99,7 @@ int16_t int16_deadline(int16_t Value, int16_t minValue, int16_t maxValue)
return Value;
}
//限幅函数
// 限幅函数
float float_constrain(float Value, float minValue, float maxValue)
{
if (Value < minValue)
@ -131,7 +110,7 @@ float float_constrain(float Value, float minValue, float maxValue)
return Value;
}
//限幅函数
// 限幅函数
int16_t int16_constrain(int16_t Value, int16_t minValue, int16_t maxValue)
{
if (Value < minValue)
@ -142,7 +121,7 @@ int16_t int16_constrain(int16_t Value, int16_t minValue, int16_t maxValue)
return Value;
}
//循环限幅函数
// 循环限幅函数
float loop_float_constrain(float Input, float minValue, float maxValue)
{
if (maxValue < minValue)
@ -169,9 +148,9 @@ float loop_float_constrain(float Input, float minValue, float maxValue)
return Input;
}
//弧度格式化为-PI~PI
// 弧度格式化为-PI~PI
//角度格式化为-180~180
// 角度格式化为-180~180
float theta_format(float Ang)
{
return loop_float_constrain(Ang, -180.0f, 180.0f);

View File

@ -87,39 +87,9 @@ extern uint8_t GlobalDebugMode;
#define VAL_MIN(a, b) ((a) < (b) ? (a) : (b))
#define VAL_MAX(a, b) ((a) > (b) ? (a) : (b))
typedef struct
{
float input; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float out; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float min_value; //<2F>޷<EFBFBD><DEB7><EFBFBD>Сֵ
float max_value; //<2F>޷<EFBFBD><DEB7><EFBFBD><EFBFBD>ֵ
float frame_period; //ʱ<><CAB1><EFBFBD><EFBFBD>
} ramp_function_source_t;
typedef struct
{
uint16_t Order;
uint32_t Count;
float *x;
float *y;
float k;
float b;
float StandardDeviation;
float t[4];
} Ordinary_Least_Squares_t;
//<2F><><EFBFBD>ٿ<EFBFBD><D9BF><EFBFBD>
float Sqrt(float x);
//б<><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>
void ramp_init(ramp_function_source_t *ramp_source_type, float frame_period, float max, float min);
//б<><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float ramp_calc(ramp_function_source_t *ramp_source_type, float input);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float abs_limit(float num, float Limit);
//<2F>жϷ<D0B6><CFB7><EFBFBD>λ

View File

View File

View File

@ -0,0 +1,3 @@
can_comm
双板CAN通信

6
modules/led_light/led.md Normal file
View File

@ -0,0 +1,6 @@
# led_task
<p align='right'>neozng1@hnu.edu.cn</p>
> TODO:
> 1. 预计添加不同错误标志,将错误类型和灯的闪烁频率或颜色等对应起来,方便调试

View File

@ -12,11 +12,14 @@
/* use usart1 as vision communication*/
static Vision_Recv_s recv_data;
// @todo:由于后续需要进行IMU-Cam的硬件触发采集控制,因此可能需要将发送设置为定时任务,或由IMU采集完成产生的中断唤醒的任务,
// 使得时间戳对齐. 因此,在send_data中设定其他的标志位数据,让ins_task填充姿态值.
// static Vision_Send_s send_data;
static usart_instance vision_usart_instance;
/**
* @brief ,bsp_usart.c中被usart rx callback调用
* @todo 1.,get_protocol_info的第四个参数增加一个float buffer
* @todo 1.,get_protocol_info的第四个参数增加一个float类型buffer
* 2.
*/
static void DecodeVision()
@ -38,8 +41,10 @@ Vision_Recv_s* VisionInit(UART_HandleTypeDef *handle)
/**
* @brief
* @todo 1.,get_protocol_info的第四个参数增加一个float buffer
* @todo 1.,get_protocol_send_data的第6个参数增加一个float buffer
* 2.
* 3.IMU-Cam的硬件触发采集控制,
* IMU采集完成产生的中断唤醒的任务,使.
*
* @param send
*/
@ -53,3 +58,9 @@ void VisionSend(Vision_Send_s *send)
get_protocol_send_data(0x02, flag_register, &send->yaw, 3, send_buff, &tx_len);
USARTSend(&vision_usart_instance, send_buff, tx_len);
}
Vision_Recv_s* VisionGetcmd()
{
return &recv_data;
}

View File

@ -22,4 +22,11 @@ Vision_Recv_s *VisionInit(UART_HandleTypeDef *handle);
*/
void VisionSend(Vision_Send_s *send);
/**
* @brief
*
* @return Vision_Recv_s*
*/
Vision_Recv_s* VisionGetcmd();
#endif // !MASTER_PROCESS_H

View File

@ -6,7 +6,7 @@
#define PROTOCOL_CMD_ID 0XA5
#define OFFSET_BYTE 8 //出数据段外,其他部分所占字节数
#define OFFSET_BYTE 8 // 出数据段外,其他部分所占字节数
typedef enum
{
@ -77,7 +77,7 @@ typedef struct
float pitch;
float roll;
// uint32_t time_stamp;
// uint32_t time_stamp; // @todo 用于和相机的时间戳对齐
} Vision_Send_s;
typedef struct
@ -86,23 +86,23 @@ typedef struct
{
uint8_t sof;
uint16_t data_length;
uint8_t crc_check; //帧头CRC校验
} header; //数据帧头
uint16_t cmd_id; //数据ID
uint16_t frame_tail; //帧尾CRC校验
uint8_t crc_check; // 帧头CRC校验
} header; // 数据帧头
uint16_t cmd_id; // 数据ID
uint16_t frame_tail; // 帧尾CRC校验
} protocol_rm_struct;
/*更新发送数据帧,并计算发送数据帧长度*/
void get_protocol_send_data(uint16_t send_id, //信号id
void get_protocol_send_data(uint16_t send_id, // 信号id
uint16_t flags_register, // 16位寄存器
float *tx_data, //待发送的float数据
float *tx_data, // 待发送的float数据
uint8_t float_length, // float的数据长度
uint8_t *tx_buf, //待发送的数据帧
uint16_t *tx_buf_len); //待发送的数据帧长度
uint8_t *tx_buf, // 待发送的数据帧
uint16_t *tx_buf_len); // 待发送的数据帧长度
/*接收数据处理*/
uint16_t get_protocol_info(uint8_t *rx_buf, //接收到的原始数据
uint16_t *flags_register, //接收数据的16位寄存器地址
float *rx_data); //接收的float数据存储地址
uint16_t get_protocol_info(uint8_t *rx_buf, // 接收到的原始数据
uint16_t *flags_register, // 接收数据的16位寄存器地址
float *rx_data); // 接收的float数据存储地址
#endif

View File

@ -2,13 +2,11 @@
* @file dji_motor.h
* @author neozng
* @brief DJI智能电机头文件
* @version 0.1
* @version 0.2
* @date 2022-11-01
*
* @todo 1. 使
2. `DJIMotorInit()`,
`dji_motor_init_config_s`,使,
3. M2006和M3508增加开环的零位校准函数
2. M2006和M3508增加开环的零位校准函数
* @copyright Copyright (c) 2022 HNU YueLu EC all rights reserved
*
@ -28,13 +26,13 @@
/* DJI电机CAN反馈信息*/
typedef struct
{
uint16_t ecd;
uint16_t ecd; // 0-8192
uint16_t last_ecd;
int16_t speed_rpm;
int16_t given_current;
int16_t speed_rpm; // rounds per minute
int16_t given_current; // 实际电流
uint8_t temperate;
int16_t total_round;
int32_t total_angle;
int16_t total_round; // 总圈数,注意方向
int32_t total_angle; // 总角度,注意方向
} dji_motor_measure;
/**
@ -66,19 +64,18 @@ typedef struct
/**
* @brief DJI智能电机,,application初始化的时候调用此函数
* initStructure然后传入此函数.
* recommend: type xxxinitStructure = {
* .member1=xx,
* .member2=xx,
* ....};
* recommend: type xxxinitStructure = {.member1=xx,
* .member2=xx,
* ....};
* 线(6),,(500Hz),
* DJIMotorControl().
*
* @attention M3508和M2006的反馈报文都是0x200+id,GM6020的反馈是0x204+id,id不要冲突.
* ,IDcrash_Handler(),debug来判断是否出现冲突.
*
*
* @param config ,,PID参数设置,CAN设置
*
* @return dji_motor_instance*
*
* @return dji_motor_instance*
*/
dji_motor_instance *DJIMotorInit(Motor_Init_Config_s config);

View File

@ -5,8 +5,7 @@
> TODO:
>
> 1. 给不同的电机设置不同的低通滤波器惯性系数而不是统一使用宏
> 2. 当前电机初始化函数`DJIMotorInit()`稍显凌乱,应设置一个`dji_motor_init_config_s`结构体用于电机初始化,使得风格统一,提高可读性
> 3. 为M2006和M3508增加开环的零位校准函数
> 2. 为M2006和M3508增加开环的零位校准函数

View File

View File

View File

0
modules/remote/remote.md Normal file
View File

View File