无刷电机小车开发记录01——制作RTT内GD32E503器件的BSP

前情提要


最近计划开始做一个无刷电机的小车玩玩,不用网上的现有方案,一切从零开始自己做方案。硬件方案打算用GD32E503和EG2134栅极驱动IC等一系列国产器件去做,这样就面临一个问题,不太好用Arduino跑SimpleFOC快速出原型。所以软件方案想基于RTT开发,这样只需移植一些硬件驱动和FOC以及卡尔曼滤波等算法,其它的很多功能还是可以用RThread组件实现的,总不能所有轮子都自己造😅,毕竟玩这个小车的目的也只是想深入玩玩这些控制算法。这个小车的整个开发周期可能会很长,至少是以年为度量单位的,第一是因为工作比较忙,只能用一些零散时间搞,第二是因为计划用到什么学什么,有意思的地方都深入的研究研究,不以速成为目的。整个开发过程也都记录一下,图文形式的记录可能会在RTThread论坛进行记录,视频形式的记录就发布在B站上,希望有兴趣的小伙伴也可以一起玩一玩哈。


前期工作


前段时间,大概花了一周的时间已经把第一版测试用的硬件电路和机械结构设计完毕,如下是硬件电路的3D视图。

如下是三轮小车形态的车底盘3D渲染图:


下图是平衡车形态的车底盘3D渲染图:

下图为二阶平衡车形态的车底盘3D渲染图:

目前第一版的硬件测试电路已焊接完毕,第一版测试小车也完成了组装,下图是刚组装起来的平衡车形态的无刷电机小车,就计划先拿它开刀了,其它形态后面再慢慢玩。小车还算小巧,等测试通过后计划再做一版集成度更高更小巧的玩玩。


千里之行始于创建BSP


一切就绪,准备开始撸程序了,那遇到的第一个问题就是目前RTThread的BSP内并没有我想用的这款GD32E503的处理器(用这款处理器是想玩一玩它的三角函数加速器,有硬件计算电路,就不用查询法去计算三角函数了,感觉跑FOC会舒服很多)。所以第一步就是要学习一下添加自己的BSP了。


下载GD32E503固件库和RTT源码包


做BSP的第一步,自然是下载RTThread源码和GD32E503的固件库了。目前RTThread的稳定发行版应该是4.1.0,但我这里只是玩玩,对稳定度要求不高,果断去码云上下载了最新的master版本,目前的版本是5.0.1:

1/* RT-Thread version information */
2#define RT_VERSION_MAJOR                5               /**< Major version number (X.x.x) */
3#define RT_VERSION_MINOR                0               /**< Minor version number (x.X.x) */
4#define RT_VERSION_PATCH                1               /**< Patch version number (x.x.X) */

GD32E503的固件库包含在开发板Demo资料里,最新版本是V1.2.2:


添加GD32E503器件到MDK


GD32E50x的AddOn资源包,目前最新版本是1.3.3,如果还没有安装MDK需要先安装一下MDK,这里不做过多表述,然后再安装AddOn资源包内的两个”.pack”文件(也可以只安装E50x版本的):

如下图所示,MDK内的DeviceDatabase内能找到GD32E50x系列的器件列表,证明资源包安装成功。


添加libraries


拷贝固件库到BSP的libraries目录内

解压RTT源码包和固件库压缩包,先拷贝固件库的”GD32E50x_Firmware_Library”文件夹到RTT源码包的”bsp/gd32/arm/libraries/“路径下:

修改libraries目录内的配置文件

这里可以看到libraries目录下还有两个配置文件“Kconfig”和“.ignore_format.yml”,Kconfig文件后面用menuconfig或RTthreadStudio IDE去配置肯定会用到,另外一个文件暂时不知道什么用途,但不妨一起修改了,Kconfig文件修改如下(文档末尾添加GD32E5的配置信息):

1config SOC_FAMILY_GD32
2    bool
3config SOC_SERIES_GD32F1
4    bool
5    select ARCH_ARM_CORTEX_M3
6    select SOC_FAMILY_GD32
7config SOC_SERIES_GD32F2
8    bool
9    select ARCH_ARM_CORTEX_M3
10    select SOC_FAMILY_GD32
11config SOC_SERIES_GD32F3
12    bool
13    select ARCH_ARM_CORTEX_M4
14    select SOC_FAMILY_GD32
15config SOC_SERIES_GD32F4
16    bool
17    select ARCH_ARM_CORTEX_M4
18    select SOC_FAMILY_GD32
19config SOC_SERIES_GD32E5    #add by cjl
20    bool
21    select ARCH_ARM_CORTEX_M33
22    select SOC_FAMILY_GD32

“.yml”文件把GD32E50x的固件库路径名添加到数组末尾:

1dir_path:
2- GD32F10x_Firmware_Library
3- GD32F20x_Firmware_Library
4- GD32F30x_Firmware_Library
5- GD32F4xx_Firmware_Library
6- GD32E50x_Firmware_Library

给固件库添加SConscript构建配置文件

从其它固件库文件内(我用的F4xx)拷贝一份”SConscript”文件到新加入的固件库路径内:

1import rtconfig
2from building import *
3# get current directory
4cwd = GetCurrentDir()
5# The set of source files associated with this SConscript file.
6src = Split('''
7CMSIS/GD/GD32E50x/Source/system_gd32e50x.c
8GD32E50x_standard_peripheral/Source/gd32e50x_gpio.c
9GD32E50x_standard_peripheral/Source/gd32e50x_rcu.c
10GD32E50x_standard_peripheral/Source/gd32e50x_exti.c
11GD32E50x_standard_peripheral/Source/gd32e50x_misc.c
12'''
)
13# remove: GD32E50x_standard_peripheral/Source/gd32e50x_syscfg.c
14if GetDepend(['RT_USING_SERIAL']):
15    src += ['GD32E50x_standard_peripheral/Source/gd32e50x_usart.c']
16if GetDepend(['RT_USING_I2C']):
17    src += ['GD32E50x_standard_peripheral/Source/gd32e50x_i2c.c']
18if GetDepend(['RT_USING_SPI']):
19    src += ['GD32E50x_standard_peripheral/Source/gd32e50x_spi.c']
20if GetDepend(['RT_USING_CAN']):
21    src += ['GD32E50x_standard_peripheral/Source/gd32e50x_can.c']
22if GetDepend(['BSP_USING_ETH']):
23    src += ['GD32E50x_standard_peripheral/Source/gd32e50x_enet.c']
24if GetDepend(['RT_USING_ADC']):
25    src += ['GD32E50x_standard_peripheral/Source/gd32e50x_adc.c']
26if GetDepend(['RT_USING_DAC']):
27    src += ['GD32E50x_standard_peripheral/Source/gd32e50x_dac.c']
28if GetDepend(['RT_USING_RTC']):
29    src += ['GD32E50x_standard_peripheral/Source/gd32e50x_rtc.c']
30    src += ['GD32E50x_standard_peripheral/Source/gd32e50x_pmu.c']
31if GetDepend(['RT_USING_WDT']):
32    src += ['GD32E50x_standard_peripheral/Source/gd32e50x_wwdgt.c']
33    src += ['GD32E50x_standard_peripheral/Source/gd32e50x_fwdgt.c']
34if GetDepend(['RT_USING_SDIO']):
35    src += ['GD32E50x_standard_peripheral/Source/gd32e50x_sdio.c']
36    src += ['GD32E50x_standard_peripheral/Source/gd32e50x_dma.c']
37path = [
38    cwd + '/CMSIS/GD/GD32E50x/Include',
39    cwd + '/CMSIS',
40    cwd + '/GD32E50x_standard_peripheral/Include',]
41CPPDEFINES = ['USE_STDPERIPH_DRIVER']
42group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES)
43Return('group')

创建BSP


拷贝BSP模板

任意拷贝一份BSP文件夹(我同样也是用的407)重命名为E503:

修改board.h头文件

其中主要需要修改的内容都在board路径下。先看board.h文件,我这里没有做外部SDRAM,所以注释掉相关定义,我板子实际焊的是GD32E503RCT6,所以SRAM大小改为96KB,再把相关头文件名修改一下:

1#ifndef __BOARD_H__
2#define __BOARD_H__
3#include "gd32e50x.h"
4#include "drv_usart.h"
5#include "drv_gpio.h"
6#include "gd32e50x_exti.h"
7//#define EXT_SDRAM_BEGIN    (0xC0000000U) /* the begining address of external SDRAM */
8//#define EXT_SDRAM_END      (EXT_SDRAM_BEGIN + (32U * 1024 * 1024)) /* the end address of external SDRAM */
9//  Internal SRAM memory size[Kbytes] <8-64>
10//  Default: 64
11#ifdef __ICCARM__
12// Use *.icf ram symbal, to avoid hardcode.
13extern char __ICFEDIT_region_RAM_end__;
14#define GD32_SRAM_END          &__ICFEDIT_region_RAM_end__
15#else
16#define GD32_SRAM_SIZE         96      //96 for GD32E503xC         128 for GD32E503xE  ...
17#define GD32_SRAM_END          (0x20000000 + GD32_SRAM_SIZE * 1024)
18#endif
19#ifdef __ARMCC_VERSION
20extern int Image$$RW_IRAM1$$ZI$$Limit;
21#define HEAP_BEGIN    (&Image$$RW_IRAM1$$ZI$$Limit)
22#elif __ICCARM__
23#pragma section="HEAP"
24#define HEAP_BEGIN    (__segment_end("HEAP"))
25#else
26extern int __bss_end;
27#define HEAP_BEGIN    (&__bss_end)
28#endif
29#define HEAP_END          GD32_SRAM_END
30#endif

添加gd32e50x_libopt.h

在固件库内的随便一个例程路径内拷贝一份”gd32e50x_libopt.h”到当前bsp的board路径内,替换掉原有的“gd32f4xx_libopt.h”

修改board目录下的Kconfig和SConscript配置文件

而对于board目录下的“Kconfig”和“SConscript”配置文件也要稍作修改,基本都是把F4xx的字符串改成E50x的。稍需注意的是“SConscript”文件内对于启动文件相关的配置,E50x有高密度(hd)和互联(cl)两个版本。我这里用的E503RC或者是RE都是高密度版本,所以选择hd的汇编启动文件。而且还需要说明的是,虽然我这里没有注释掉gcc编译器下的启动文件,但其实E503的固件库内并没有提供gcc版本的启动文件,也就是说后面不能用RTT的IDE去开发了。等什么时候有了再加进来吧。或者后面看需要,不行就自己改一版gcc编译器的启动文件。目前这两个文件就暂且修改这么多,后面再看情况,如有问题再进行修改。

“SConscript”文件修改如下:

1import os
2import rtconfig
3from building import *
4Import('SDK_LIB')
5cwd = GetCurrentDir()
6# add general drivers
7src = Split('''
8board.c
9'''
)
10path =  [cwd]
11startup_path_prefix = SDK_LIB
12if rtconfig.PLATFORM in ['gcc']:
13    src += [startup_path_prefix + '/GD32E50x_Firmware_Library/CMSIS/GD/GD32E50x/Source/GCC/startup_gd32e50x_hd.s']
14elif rtconfig.PLATFORM in ['armcc''armclang']:
15    src += [startup_path_prefix + '/GD32E50x_Firmware_Library/CMSIS/GD/GD32E50x/Source/ARM/startup_gd32e50x_hd.s']
16elif rtconfig.PLATFORM in ['iccarm']:
17    src += [startup_path_prefix + '/GD32E50x_Firmware_Library/CMSIS/GD/GD32E50x/Source/IAR/startup_gd32e50x_hd.s']
18CPPDEFINES = ['GD32E50X','GD32E50X_HD']
19group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES)
20Return('group')

修改三种编译器用的链接脚本

修改”board/linker_scripts”目录下的连接文件,如无特殊要求可不对连接脚本做太多修改,只需要修改RAM和ROM地址和大小即可,以“link.sct”为例:

1LR_IROM1 0x08000000 0x00040000  {    ; load region size_region  256KB
2  ER_IROM1 0x08000000 0x00040000  {  ; load address = execution address
3   *.o (RESET, +First)
4   *(InRoot$$Sections)
5   .ANY (+RO)
6  }
7  RW_IRAM1 0x20000000 0x00018000  {  ; RW data  96KB
8   .ANY (+RW +ZI)
9  }
10}

修改BSP顶层SConstruct和rtconfig.py文件

修改新建bsp目录下的SConstruct文件和rtconfig.py文件:

SConstruct文件只需要修改“gd32_library”的值:

1gd32_library = 'GD32E50x_Firmware_Library'

修改工程模板

接下来修改工程模板文件,我这边只修改MDK5版本的工程模板:

修改Device为实际使用的GD32E503RC:

调试工具改成DAP:

利用env工具配置RTthread并生成MDK工程

在新键的bsp目录下运行env工具(env工具的安装与使用请参考RTT官方文档),对RTT做初步配置:

最后根据提示,输入命令生成mdk5的工程,(如果想要提交自己制作的BSP,请参照官方BSP制作规范):


下载验证


最后打开工程,稍微修改一下main.c内的内容,加一条调试语句,修改对应的LED引脚。编译一下,如果能编译通过说明上面修改的内容没问题,如果有错误请仔细检查上面格配置文件修改的内容是否正确或者自行根据错误提示进行修改。烧录程序就可以看到运行效果了。

1#include 
2#include 
3#include 
4#include 
5/* defined the LED2 pin: PC6 */
6#define LED_PIN GET_PIN(B, 11)
7#define BUZZER_PIN GET_PIN(B, 12)
8int main(void)
9
{
10    int count = 1;
11    /* set LED2 pin mode to output */
12    rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
13    rt_pin_write(BUZZER_PIN, PIN_LOW);
14    rt_pin_mode(BUZZER_PIN, PIN_MODE_OUTPUT);
15    rt_kprintf("无刷电机小车测试程序!\n");
16    while (count++)
17    {
18        rt_pin_write(LED_PIN, PIN_HIGH);
19        rt_thread_mdelay(500);
20        rt_pin_write(LED_PIN, PIN_LOW);
21        rt_thread_mdelay(500);
22    }
23    return RT_EOK;
24}

今天就先玩到这里,后面再使用一段时间这个BSP,需要优化的地方优化一下,然后再往码云上提交一份。


其它链接


视频方面目前只有一个前期的开题视频,简单讲了一下想做一些什么,过了一遍硬件电路的设计方案,想了解详情的可以观看下面的视频哦!更多的阶段性功能展示以及调试视频后续再慢慢更新。

【无刷电机小车——搞起来!-哔哩哔哩】 https://b23.tv/ZmvhBS7

无刷电机小车开发记录02——BSP导入RTThreadStudio:https://club.rt-thread.org/ask/article/4c90d45831ce0722.html

无刷电机小车开发记录03——PWM信号输入捕获驱动:https://club.rt-thread.org/ask/article/dc39eb608f1eba75.html

无刷电机小车开发记录04——互补PWM驱动移植:https://club.rt-thread.org/ask/article/004229252f06d18d.html


———————End——————




👇 点击阅读原文进入官网

RTThread物联网操作系统 帮助您了解RT-Thread相关的资讯.
评论
  • 大模型的赋能是指利用大型机器学习模型(如深度学习模型)来增强或改进各种应用和服务。这种技术在许多领域都显示出了巨大的潜力,包括但不限于以下几个方面: 1. 企业服务:大模型可以用于构建智能客服系统、知识库问答系统等,提升企业的服务质量和运营效率。 2. 教育服务:在教育领域,大模型被应用于个性化学习、智能辅导、作业批改等,帮助教师减轻工作负担,提高教学质量。 3. 工业智能化:大模型有助于解决工业领域的复杂性和不确定性问题,尽管在认知能力方面尚未完全具备专家级的复杂决策能力。 4. 消费
    丙丁先生 2025-01-07 09:25 80浏览
  • 彼得·德鲁克被誉为“现代管理学之父”,他的管理思想影响了无数企业和管理者。然而,关于他的书籍分类,一种流行的说法令人感到困惑:德鲁克一生写了39本书,其中15本是关于管理的,而其中“专门写工商企业或为企业管理者写的”只有两本——《为成果而管理》和《创新与企业家精神》。这样的表述广为流传,但深入探讨后却发现并不完全准确。让我们一起重新审视这一说法,解析其中的矛盾与根源,进而重新认识德鲁克的管理思想及其著作的真正价值。从《创新与企业家精神》看德鲁克的视角《创新与企业家精神》通常被认为是一本专为企业管
    优思学院 2025-01-06 12:03 113浏览
  • 村田是目前全球量产硅电容的领先企业,其在2016年收购了法国IPDiA头部硅电容器公司,并于2023年6月宣布投资约100亿日元将硅电容产能提升两倍。以下内容主要来自村田官网信息整理,村田高密度硅电容器采用半导体MOS工艺开发,并使用3D结构来大幅增加电极表面,因此在给定的占位面积内增加了静电容量。村田的硅技术以嵌入非结晶基板的单片结构为基础(单层MIM和多层MIM—MIM是指金属 / 绝缘体/ 金属) 村田硅电容采用先进3D拓扑结构在100um内,使开发的有效静电容量面积相当于80个
    知白 2025-01-07 15:02 66浏览
  • 本文介绍Linux系统更换开机logo方法教程,通用RK3566、RK3568、RK3588、RK3576等开发板,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。制作图片开机logo图片制作注意事项(1)图片必须为bmp格式;(2)图片大小不能大于4MB;(3)BMP位深最大是32,建议设置为8;(4)图片名称为logo.bmp和logo_kernel.bmp;开机
    Industio_触觉智能 2025-01-06 10:43 87浏览
  • 每日可见的315MHz和433MHz遥控模块,你能分清楚吗?众所周知,一套遥控设备主要由发射部分和接收部分组成,发射器可以将控制者的控制按键经过编码,调制到射频信号上面,然后经天线发射出无线信号。而接收器是将天线接收到的无线信号进行解码,从而得到与控制按键相对应的信号,然后再去控制相应的设备工作。当前,常见的遥控设备主要分为红外遥控与无线电遥控两大类,其主要区别为所采用的载波频率及其应用场景不一致。红外遥控设备所采用的射频信号频率一般为38kHz,通常应用在电视、投影仪等设备中;而无线电遥控设备
    华普微HOPERF 2025-01-06 15:29 125浏览
  •     为控制片内设备并且查询其工作状态,MCU内部总是有一组特殊功能寄存器(SFR,Special Function Register)。    使用Eclipse环境调试MCU程序时,可以利用 Peripheral Registers Viewer来查看SFR。这个小工具是怎样知道某个型号的MCU有怎样的寄存器定义呢?它使用一种描述性的文本文件——SVD文件。这个文件存储在下面红色字体的路径下。    例:南京沁恒  &n
    电子知识打边炉 2025-01-04 20:04 98浏览
  • PLC组态方式主要有三种,每种都有其独特的特点和适用场景。下面来简单说说: 1. 硬件组态   定义:硬件组态指的是选择适合的PLC型号、I/O模块、通信模块等硬件组件,并按照实际需求进行连接和配置。    灵活性:这种方式允许用户根据项目需求自由搭配硬件组件,具有较高的灵活性。    成本:可能需要额外的硬件购买成本,适用于对系统性能和扩展性有较高要求的场合。 2. 软件组态   定义:软件组态主要是通过PLC
    丙丁先生 2025-01-06 09:23 83浏览
  • By Toradex 秦海1). 简介嵌入式平台设备基于Yocto Linux 在开发后期量产前期,为了安全以及提高启动速度等考虑,希望将 ARM 处理器平台的 Debug Console 输出关闭,本文就基于 NXP i.MX8MP ARM 处理器平台来演示相关流程。 本文所示例的平台来自于 Toradex Verdin i.MX8MP 嵌入式平台。  2. 准备a). Verdin i.MX8MP ARM核心版配合Dahlia载板并
    hai.qin_651820742 2025-01-07 14:52 40浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球无人机锂电池产值达到2457百万美元,2024-2030年期间年复合增长率CAGR为9.6%。 无人机锂电池是无人机动力系统中存储并释放能量的部分。无人机使用的动力电池,大多数是锂聚合物电池,相较其他电池,锂聚合物电池具有较高的能量密度,较长寿命,同时也具有良好的放电特性和安全性。 全球无人机锂电池核心厂商有宁德新能源科技、欣旺达、鹏辉能源、深圳格瑞普和EaglePicher等,前五大厂商占有全球
    GIRtina 2025-01-07 11:02 63浏览
  • 根据Global Info Research项目团队最新调研,预计2030年全球封闭式电机产值达到1425百万美元,2024-2030年期间年复合增长率CAGR为3.4%。 封闭式电机是一种电动机,其外壳设计为密闭结构,通常用于要求较高的防护等级的应用场合。封闭式电机可以有效防止外部灰尘、水分和其他污染物进入内部,从而保护电机的内部组件,延长其使用寿命。 环洋市场咨询机构出版的调研分析报告【全球封闭式电机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球封闭式电机总体规
    GIRtina 2025-01-06 11:10 103浏览
  • 在智能家居领域中,Wi-Fi、蓝牙、Zigbee、Thread与Z-Wave等无线通信协议是构建短距物联局域网的关键手段,它们常在实际应用中交叉运用,以满足智能家居生态系统多样化的功能需求。然而,这些协议之间并未遵循统一的互通标准,缺乏直接的互操作性,在进行组网时需要引入额外的网关作为“翻译桥梁”,极大地增加了系统的复杂性。 同时,Apple HomeKit、SamSung SmartThings、Amazon Alexa、Google Home等主流智能家居平台为了提升市占率与消费者
    华普微HOPERF 2025-01-06 17:23 141浏览
  • 这篇内容主要讨论三个基本问题,硅电容是什么,为什么要使用硅电容,如何正确使用硅电容?1.  硅电容是什么首先我们需要了解电容是什么?物理学上电容的概念指的是给定电位差下自由电荷的储藏量,记为C,单位是F,指的是容纳电荷的能力,C=εS/d=ε0εrS/4πkd(真空)=Q/U。百度百科上电容器的概念指的是两个相互靠近的导体,中间夹一层不导电的绝缘介质。通过观察电容本身的定义公式中可以看到,在各个变量中比较能够改变的就是εr,S和d,也就是介质的介电常数,金属板有效相对面积以及距离。当前
    知白 2025-01-06 12:04 167浏览
我要评论
0