Ai8051U电调(移植AM32固件)
<h2>单片机请购买24年10月之后生产的(最下方丝印前四位数>=2442)</h2><h1>介绍</h1>
<p>AM32 固件原为 ARM 处理器设计,现成功移植到强大的 <strong>Ai8051U</strong>,用于控制<strong>无刷电机 (BLDC)</strong>。该固件旨在安全、快速、平滑、快速启动和线性油门。它适用于多种车辆类型和飞行控制器。</p>
<p>AM32具有以下特点:</p>
<ol>
<li>可通过 betaflight 直通、单线串行或 arduino 升级固件</li>
<li>伺服 PWM、Dshot(300, 600) 电机协议支持</li>
<li>双向控制</li>
<li>KISS 标准 ESC 遥测</li>
<li>可变 PWM 频率</li>
<li>正弦启动模式,旨在让更大的电机加速</li>
</ol>
<h1>主控及外设配置</h1>
<p>使用AI8051U作为主控芯片,AI8051U具有充足的外设资源和优异的性能表现。</p>
<h2>MCU</h2>
<p><img src="data/attachment/forum/202412/22/134000ubno4chszbdbrsno.png" alt="mcu.png" title="mcu.png" /></p>
<h2>MCU引脚图</h2>
<p><img src="data/attachment/forum/202412/22/134012kafqbdh574zp5vak.png" alt="mcu_pins.png" title="mcu_pins.png" /></p>
<p>使用 PWMA 输出 3 组互补 PWM 来驱动 MOSFEET,使用 PWMB 捕获外部油门信号,使用 ADC 对电压和电流进行采样,用于低电压保护和过流保护。使用内部 OPA 和 BEMF 估计转子位置。TMR0 和 TMR1 用于计算换向时间,TMR2 用于串口,TMR3 和 TMR11 用于延迟功能(实际上,只需要一个),TMR4 用于完成一些周期性任务。</p>
<h2>引脚选择</h2>
<p><img src="data/attachment/forum/202412/22/134021dkkk12msyklqksll.png" alt="PINS.png" title="PINS.png" /></p>
<p>AH AL BH BL CH CL : PWMA 输出</p>
<p>INPUT: PWMB 外部输入触发</p>
<p>A_BEMF: A相反电动势<br />
B_BEMF: B相反电动势<br />
C_BEMF: C相反电动势</p>
<p>CC_BEMF: 反电动势中电</p>
<p>CMP_OUT:比较器输出</p>
<p>ADC_V: 电压检测口<br />
ADC_I: 电流检测口</p>
<p>为了统一 OPA 的中断入口,将 OPA 的输出到 P41 中,使用 P41 的引脚中断进行过零比较处理</p>
<p>P30 和 P31 用于通过 STC-LINK1、UART 或内部 USB 下载 bootloader</p>
<h1>初始化(板子仅供参考)</h1>
<h2>烧录Bootloader</h2>
<ol>
<li>对于空芯片,BootLoader 需要通过 STC-LINK1、UART 或内部 USB 进行烧录,如下图所示进行连</li>
</ol>
<p><img src="data/attachment/forum/202504/06/173312d5437mlrmt5aahtt.jpg" alt="connect.jpg" title="connect.jpg" /></p>
<ol start="2">
<li>
<p>使用 AIapp-ISP 打开 Bootloader(<a href="forum.php?mod=attachment&aid=75544" title="attachment"><img src="/source/plugin/zhanmishu_markdown/template/editor/images/upload.svg" alt="upload" /> 附件:AM32_Bootloader_AI8051U.zip</a>) 工程,编译后直接下载。</p>
<p><img src="data/attachment/forum/202412/22/134111nm3739g4ctwl47jo.png" alt="download.png" title="download.png" /></p>
</li>
<li>
<p>使用单线串口(可以将 USB 转串口芯片的 RX 和 TX 连接在一起,比如 CH340,然后连接到板子上)连接到 ESC,并使用工具配置和更新固件。我用 CH340 来表现,接线如下图所示。</p>
</li>
</ol>
<p><img src="data/attachment/forum/202504/06/173405oo7d4ezecrzgtrme.jpg" alt="config.jpg" title="config.jpg" /></p>
<p><img src="data/attachment/forum/202504/06/173429y3y3jbc30ynltwj3.jpg" alt="config3.jpg" title="config3.jpg" /></p>
<p>如果 Bootloader 烧录正确,打开 Esc_Config_Tool_1_82_WIN.exe(<a href="forum.php?mod=attachment&aid=75547" title="attachment"><img src="/source/plugin/zhanmishu_markdown/template/editor/images/upload.svg" alt="upload" /> 附件:Esc_Config_Tool_1_82_WIN.zip</a>) 配置工具并打开 ESC 电源。按照下图中的步骤进行单击。首次连接时,将显示 No EEprom!</p>
<p><img src="data/attachment/forum/202412/22/134456srygb7w9r4b49caz.png" alt="first.png" title="first.png" /></p>
<p>直接点击下面的 <strong>发送默认设置</strong> 以烧写默认值。烧录成功后,重新开机。再次连接并单击 M1。将显示我们刚刚烧录的默认参数。</p>
<p><img src="https://www.stcaimcu.com/data/attachment/forum/202412/22/134645zhokhmph5hjxkzqe.png" alt="then.png" title="then.png" /></p>
<ol start="4">
<li>
<p>刷写固件和配置固件可以使用 Keil C251 进行编译,编译后的固件位于 Objects 文件夹中。</p>
<p><img src="data/attachment/forum/202412/22/134745f98nzq0q0t4e9s9k.png" alt="hex.png" title="hex.png" />使用文本编辑器打开 HEX 文件(我更喜欢使用 VScode),为了更好的支持 HEX 文件编辑,需要安装 Hex Editor 或 Intel HEX 格式插件,该插件可以在扩展市场中找到。安装后,打开 HEX 文件。</p>
<p><img src="data/attachment/forum/202412/22/135014habamyysmvmsqms1.png" alt="Plug_in.png" title="Plug_in.png" /></p>
<p>在这个 HEX 文件中,请注意第一行。<br />
:03<strong>0000</strong>00023E58<strong>65</strong><br />
将 <strong>0000H</strong> 的值更改为 <strong>1000H</strong>,将 <strong>65H</strong> 的值更改为 <strong>55H</strong>。<br />
:03<strong>1000</strong>00023E58<strong>55</strong><br />
请注意,<strong>0000H</strong> 的值是程序的起始地址,<strong>65H</strong> 的值是校验和。<strong>1000H</strong> 的值是烧录 bootloader 后程序的起始地址。<strong>55H</strong> 的值是新的校验和。烧录 bootloader 后程序的起始地址是 <strong>0x1000H</strong>,因此 <strong>0000H</strong> 的值更改为 <strong>1000H</strong>。校验和的计算方法是将行中除起始冒号和校验和本身之外的所有数据相加,然后取总和最后一个字节的二进制补码。<strong>65H</strong> 的值更改为 <strong>55H</strong>,一般来讲,上面这个改动导致的校验位变化可以直接在校验位上面减去<strong>10H</strong>。具体计算方法可以在网上找到。如果 VScode 配合插件使用,可以直接点击地址值进行修改,插件可能会自动计算新的校验和。</p>
<p><img src="data/attachment/forum/202412/22/135842y27d21lz3i2dftzf.png" alt="Hexline.png" title="Hexline.png" /></p>
<p><img src="data/attachment/forum/202412/22/135856dzd134dkozkkq2w1.png" alt="Hex_change.png" title="Hex_change.png" /></p>
</li>
</ol>
<p>回到工具的 FLASH 界面,我们点击 Load Firmware,选择我们刚刚修改的固件,会弹出 FLash Firmware 按钮。单击以开始更新程序。</p>
<p><img src="data/attachment/forum/202412/22/135944km2eie9cga33ddhc.png" alt="updata.png" title="updata.png" /></p>
<p>更新完成后,重新上电并重新连接 ESC 以配置 ESC。</p>
<p><img src="data/attachment/forum/202412/22/140136t6htnvnwtjhoiivr.png" alt="para.png" title="para.png" /></p>
<h1>测试</h1>
<p>我移植的版本是 V2.16,支持 dshot300、dshot600、PWM 等信号。(但出于某种原因,我只实现了 PWM,不能使用 dshot)。</p>
<h1>Bootloader 程序</h1>
<p><a href="forum.php?mod=attachment&aid=75564" title="attachment"><img src="/source/plugin/zhanmishu_markdown/template/editor/images/upload.svg" alt="upload" /> 附件:AM32_Bootloader_AI8051U.zip</a></p>
<h1>AM32程序</h1>
<p>PCB文件在docs文件夹下,使用KiCAD和LCEDA进行设计(附件已更新,请注意LCEDA绘制的PCB需要在两个程序中修改一下输入引脚的 #define)</p>
<p><a href="forum.php?mod=attachment&aid=80468" title="attachment"><img src="/source/plugin/zhanmishu_markdown/template/editor/images/upload.svg" alt="upload" /> 附件:AM32_AI8051U.zip</a></p>
<h1>Esc_Config_Tool_1_82_WIN</h1>
<p><a href="forum.php?mod=attachment&aid=75566" title="attachment"><img src="/source/plugin/zhanmishu_markdown/template/editor/images/upload.svg" alt="upload" /> 附件:Esc_Config_Tool_1_82_WIN.zip</a></p>
<h1>测试视频</h1>
<video controls="controls" src="forum.php?mod=attachment&aid=75568"></video>
<video controls="controls" src="forum.php?mod=attachment&aid=75569"></video>
<p>新PCB测试</p>
<video controls="controls" src="forum.php?mod=attachment&aid=80469"></video>
<h1>Github</h1>
<p>https://github.com/Icey7122/AM32_AI8051U</p>
DSHOT 等后续的集成 单总线 的芯片出来
Ai8051U暂时无 单总线
神农鼎 发表于 2024-12-22 14:47
DSHOT 等后续的集成 单总线 的芯片出来
Ai8051U暂时无 单总线
问一下,后续芯片在高速PWM时还是得异步读写吗? Qinluoyao 发表于 2024-12-22 16:35
问一下,后续芯片在高速PWM时还是得异步读写吗?
如果外设用的时钟频率和CPU不一致,那就是异步;
如果外设用的时钟频率和CPU是一致,那就是不需要异步
<p>部分程序快速预览:</p>
<pre><code class="language-c">/*
引导程序用于AM32电调固件
基于 https://github.com/AlkaMotors/AT32F421_AM32_Bootloader
*/
#include "main.h"// 包含主头文件
#include <stdio.h>// 标准输入输出库
#include "version.h"// 包含版本信息头文件
/* 包含的头文件 --------------------------------------------------*/
#include "nstdbool.h"// 包含布尔类型定义头文件
#include <stdio.h>// 标准输入输出库
#include <stdlib.h>// 标准库,包含内存分配等函数
#include "eeprom.h"// 包含EEPROM操作相关头文件
#define USE_P21// 定义使用P21引脚作为通信引脚
// 禁用应用程序头部检查
// #define DISABLE_APP_HEADER_CHECKS
// 直接跳转到应用程序并忽略EEPROM
//#define USE_ADC_INPUT
//#define UPDATE_EEPROM_ENABLE
// 使用逻辑分析仪在输入引脚上检查MCU的时钟配置
//#define BOOTLOADER_TEST_CLOCK
// 启用后,每10ms输出一次字符串"HELLO_WORLD"
// #define BOOTLOADER_TEST_STRING
// 如果没有应用固件,则禁用跳转
//#define DISABLE_JUMP
// 可选地启用串行位敲统计
//#define SERIAL_STATS
/*
启用软件复位检查以跳转。
通常在软件复位时我们希望保持在引导程序中,
如果信号引脚浮动,但禁用此功能对CAN测试有用。
*/
#define CHECK_SOFTWARE_RESET 1
/*
在跳转前启用EEPROM配置检查。
禁用此功能对CAN开发有用。
*/
#define CHECK_EEPROM_BEFORE_JUMP 1
/*
是否应在EEPROM中更新引导程序版本?
*/
#define UPDATE_EEPROM_ENABLE 1
#include <string.h>// 包含字符串处理函数头文件
#ifndef MCU_FLASH_START// 如果未定义MCU_FLASH_START
#define MCU_FLASH_START 0xFF0000// 定义MCU_FLASH_START为0xFF0000
#endif
#ifndef FIRMWARE_RELATIVE_START// 如果未定义FIRMWARE_RELATIVE_START
#define FIRMWARE_RELATIVE_START 0x1000// 定义FIRMWARE_RELATIVE_START为0x1000
#endif
// 根据USE_Pxx宏定义选择不同的GPIO引脚和端口
#ifdef USE_P01
#define input_pin P01// 定义输入引脚为P01
#define input_port P0// 定义输入端口为P0
#define mode_set_pin GPIO_ModePin_1// 定义模式设置引脚为GPIO_ModePin_1
#define PIN_NUMBER 1// 定义引脚编号为1
#define PORT_LETTER 0// 定义端口字母为0
#elif defined(USE_P11)
#define input_pin P11// 定义输入引脚为P11
#define input_port P1// 定义输入端口为P1
#define mode_set_pin GPIO_ModePin_1// 定义模式设置引脚为GPIO_ModePin_1
#define PIN_NUMBER 1// 定义引脚编号为1
#define PORT_LETTER 1// 定义端口字母为1
#elif defined(USE_P21)
#define input_pin P21// 定义输入引脚为P21
#define input_port P2// 定义输入端口为P2
#define mode_set_pin GPIO_ModePin_1// 定义模式设置引脚为GPIO_ModePin_1
#define PIN_NUMBER 1// 定义引脚编号为1
#define PORT_LETTER 2// 定义端口字母为2
#elif defined(USE_P50)
#define input_pin P50// 定义输入引脚为P50
#define input_port P5// 定义输入端口为P5
#define mode_set_pin GPIO_ModePin_0// 定义模式设置引脚为GPIO_ModePin_0
#define PIN_NUMBER 0// 定义引脚编号为0
#define PORT_LETTER 5// 定义端口字母为5
#else
#error "未定义引导程序通信引脚"// 如果没有定义任何USE_Pxx宏,则报错
#endif
// 定义一个静态变量用于存储无效命令的计数
static uint16_t invalid_command;
#include "blutil.h"// 包含引导程序实用工具头文件
#ifndef BOARD_FLASH_SIZE// 如果未定义BOARD_FLASH_SIZE
#error "必须定义BOARD_FLASH_SIZE"// 报错提示需要定义FLASH大小
#endif
// 定义PIN_CODE为端口字母左移4位加上引脚编号
#define PIN_CODE (PORT_LETTER << 4 | PIN_NUMBER)
/*
目前只支持32k、64k或128k闪存
*/
#if BOARD_FLASH_SIZE == 32// 如果FLASH大小为32k
#define EEPROM_START_ADD (uint32_t)(MCU_FLASH_START+0x7c00)// 定义EEPROM起始地址
#define FLASH_SIZE_CODE 0x1f// 定义FLASH大小代码
#define ADDRESS_SHIFT 0// 地址偏移量为0
#elif BOARD_FLASH_SIZE == 64// 如果FLASH大小为64k
#define EEPROM_START_ADD (uint32_t)(MCU_FLASH_START+0xF800)// 定义EEPROM起始地址
#define FLASH_SIZE_CODE 0x35// 定义FLASH大小代码
#define ADDRESS_SHIFT 0// 地址偏移量为0
#elif BOARD_FLASH_SIZE == 128// 如果FLASH大小为128k
#define EEPROM_START_ADD (uint32_t)(MCU_FLASH_START+0x1f800)// 定义EEPROM起始地址
#define FLASH_SIZE_CODE 0x2B// 定义FLASH大小代码
#define ADDRESS_SHIFT 2// 地址偏移量为2,客户端传来的地址需左移2位后使用
#else
#error "不支持的BOARD_FLASH_SIZE"// 报错提示不支持的FLASH大小
#endif
/*
devinfo结构体告诉配置客户端我们的引脚代码、FLASH大小和设备类型。
主固件也可以使用它来确认我们有正确的EEPROM地址和引脚代码。
我们有两个32位的魔数值,以便主固件可以确认引导程序支持此功能。
*/
#define DEVINFO_MAGIC1 0x5925e3da// 定义第一个魔数值
#define DEVINFO_MAGIC2 0x4eb863d9// 定义第二个魔数值
// 定义devinfo结构体并将其放置在特定地址
static const struct {
uint32_t magic1;// 第一个魔数值
uint32_t magic2;// 第二个魔数值
const uint8_t deviceInfo;// 设备信息数组
} devinfo _at_ (MCU_FLASH_START + FIRMWARE_RELATIVE_START - 32) = {
{DEVINFO_MAGIC1},// 初始化第一个魔数值
{DEVINFO_MAGIC2},// 初始化第二个魔数值
{'4','7','1',PIN_CODE,FLASH_SIZE_CODE,0x06,0x06,0x01,0x30}// 初始化设备信息数组
};
// 定义函数指针类型
typedef void (*pFunction)(void);
// 定义应用程序地址
#define APPLICATION_ADDRESS (uint32_t)(MCU_FLASH_START + FIRMWARE_RELATIVE_START)
// 定义各种命令码
#define CMD_RUN 0x00// 运行命令
#define CMD_PROG_FLASH 0x01// 编程FLASH命令
#define CMD_ERASE_FLASH 0x02// 擦除FLASH命令
#define CMD_READ_FLASH_SIL0x03// 读取FLASH命令(SIL)
#define CMD_VERIFY_FLASH 0x03// 验证FLASH命令(重复定义)
#define CMD_VERIFY_FLASH_ARM 0x04// 验证FLASH命令(ARM)
#define CMD_READ_EEPROM 0x04// 读取EEPROM命令(重复定义)
#define CMD_PROG_EEPROM 0x05// 编程EEPROM命令
#define CMD_READ_SRAM 0x06// 读取SRAM命令
#define CMD_READ_FLASH_ATM0x07// 读取FLASH命令(ATM)
#define CMD_KEEP_ALIVE 0xFD// 保持连接命令
#define CMD_SET_ADDRESS 0xFF// 设置地址命令
#define CMD_SET_BUFFER 0xFE// 设置缓冲区命令
// 定义一些静态变量用于接收和处理数据
static uint16_t low_pin_count;// 低电平计数器
static char receiveByte;// 接收到的字节
static int count;// 计数器
static char messagereceived;// 标记是否接收到消息
static uint16_t address_expected_increment;// 地址预期增量
static int cmd;// 命令码
static char eeprom_req;// EEPROM请求标志
static int received;// 接收标志
// 定义接收缓冲区和负载缓冲区
static uint8_t xdata rxBuffer;// 接收缓冲区
static uint8_t xdata payLoadBuffer;// 负载缓冲区
static char rxbyte;// 接收到的字节
static uint32_t address;// 地址
// 定义一个联合体用于CRC计算
typedef union {
uint8_t bytes;// 字节数组
uint16_t word;// 16位整数
} uint8_16_u;
// 定义一些静态变量用于CRC计算和缓冲区管理
static uint16_t len;// 数据长度
static uint8_t calculated_crc_low_byte;// 计算出的CRC低字节
static uint8_t calculated_crc_high_byte;// 计算出的CRC高字节
static uint16_t payload_buffer_size;// 负载缓冲区大小
static char incoming_payload_no_command;// 标记是否有无命令的有效负载
/* 用户代码开始 */
// 声明一些函数用于发送字符串、接收缓冲区和串行写入字符
static void sendString(const uint8_t dat[], int len);
static void receiveBuffer();
static void serialwriteChar(uint8_t dat);
</code></pre>
页:
[1]