wuyu40 发表于 2025-8-1 16:49

极海APM32E030 Micro-EVB开发板测评+无刷电机6拍控制信号测评

#申请开发板#
 极海APM32E030R芯片是32 位 Arm®Cortex®-M0+内核,最高工作频率:72MHz,Flash 存储器:64KB,SRAM 存储器:8KB
开发方式如下:
1)连接 H2/H3 或 H4/H5 可使用板载 Geehy LINK 进行串口调试
2)断开 Geehy LINK 连接后,第三方调试工具可通过 JP1 连接仿真器进行 MCU 烧录调试
3)Type-C(数据通信)直接连接 PC 端进行 MCU 仿真调试
4)使用keil v 5.36编译环境
到官网找到如下文件:

使用的操作系统为win10(GEEHY-LINK(WinUSB)设备不支持在 Windows7 上免驱使用)假定已经安装keil (版本 V5.29 以上),安装Geehy.APM32E030_DFP.1.0.3也就是mcu支持包,阅读用户手册,按照指示连接硬件;该固件基于 CMSIS-DAP V1,会使用 USB 枚举成一个 HID 和 MSC 设备。
使用 USB 线成功连接电脑后,设备管理器上会出现:CMSIS DAP winUSB

在 keil 软件上配置选择使用 SW 模式或者 JTAG 模式。点击“Options for Target” ,在打开的界面中选择“Debug”,然后再选择“CMSIS-DAP Debugger”,如图 :

点击“Settings”按钮进入设置界面,选择 SWD 或者 JTAG 模式以及频率:

无刷直流电机的换向控制原理
如下图示例极通电导通时, 电流由 A 极流向 C 极, 这样形成了定子合成磁场. 永磁体转子会根据定子合成磁场的方向进行旋转. 通过对三相交替通电 (A+ C-) , (A+ B-) , (C+ B-), (C+ A-) , (B+ A-) , (B+ C-) , 完成磁场旋转. 每一步只改变其中一极的导通状态, 共六步来完成定子合成磁场旋转一周, 即每步磁场旋转 60° —— 该方法被称为 “六步换向法”. 如下图所示六步换向法的基本原理:

为了实现定子磁场的旋转 (即六步换向), 需要交替有序地导通定子的三相电极. 而实现三相电极交替导通的驱动电路为三相全桥逆变电路, 控制上按照六步换向时序进行控制;

完成以上配置之后测试6开关驱动工程,工程使用了定时器模块原理如下:

定时器可以看作三个模块组合,第一定时器基本功能,完成定时器周期性计数;第二定时器输出PWM功能,将计数值不断与比较寄存器做比较产生6根引脚的PWM输出信号控制无刷直流电机(或者其他类型交流电机)功率开关;第三定时器捕获功能,可以接HALL传感器等用来检测转子实时位置;在本工程中完成了6开关信号驱动,所以需要设置定时器1、2模块,代码如下:
    GPIO_Config_T GPIO_ConfigStruct;
    TMR_TimeBase_T baseConfig;
    TMR_OCConfig_T OCcongigStruct;
    TMR_BDTInit_T BDTConfig;
    //定义需要的结构体变量
    RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR1);
    RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA | RCM_AHB_PERIPH_GPIOB);
      //打开外设时钟
    /* 设置定时器1通道1引脚TMR1_CH1 */
    GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_8, GPIO_AF_PIN2);
    /* TMR1_CH2 */
    GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_9, GPIO_AF_PIN2);
    /* TMR1_CH3 */
    GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_10, GPIO_AF_PIN2);
    /* 设置刹车信号引脚*/
    GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_6, GPIO_AF_PIN2);
    /* TMR1_CH1N */
    GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_7, GPIO_AF_PIN2);
    /* TMR1_CH2N */
    GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_0, GPIO_AF_PIN2);
    /* TMR1_CH3N */
    GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_1, GPIO_AF_PIN2);
    /* Config TMR1 GPIO for complementary output PWM */
    GPIO_ConfigStruct.pin   = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_6;
    GPIO_ConfigStruct.mode    = GPIO_MODE_AF;
    GPIO_ConfigStruct.outtype = GPIO_OUT_TYPE_PP;
    GPIO_ConfigStruct.speed   = GPIO_SPEED_50MHz;
    GPIO_Config(GPIOA, &GPIO_ConfigStruct);
    GPIO_ConfigStruct.pin = GPIO_PIN_0 | GPIO_PIN_1;
    GPIO_Config(GPIOB, &GPIO_ConfigStruct);
    /* 设置定时器1工作模式TMR1 */
    baseConfig.clockDivision   = TMR_CKD_DIV1;
    baseConfig.counterMode       = TMR_COUNTER_MODE_UP;
    baseConfig.div               = 0;
    baseConfig.period            = 2047;
    baseConfig.repetitionCounter = 0;
    TMR_ConfigTimeBase(TMR1, &baseConfig);
    /* 设置定时器输出通道工作模式*/
    OCcongigStruct.OC_Mode         = TMR_OC_MODE_TMRING;
    OCcongigStruct.Pulse         = 1023;
    OCcongigStruct.OC_Idlestate    = TMR_OCIDLESTATE_SET;
    OCcongigStruct.OC_OutputState= TMR_OUTPUT_STATE_ENABLE;
    OCcongigStruct.OC_Polarity   = TMR_OC_POLARITY_HIGH;
    OCcongigStruct.OC_NIdlestate   = TMR_OCNIDLESTATE_SET;
    OCcongigStruct.OC_OutputNState = TMR_OUTPUT_NSTATE_ENABLE;
    OCcongigStruct.OC_NPolarity    = TMR_OC_NPOLARITY_HIGH;
    TMR_OC1Config(TMR1, &OCcongigStruct);
    OCcongigStruct.Pulse = 511;
    TMR_OC2Config(TMR1, &OCcongigStruct);
    OCcongigStruct.Pulse = 255;
    TMR_OC3Config(TMR1, &OCcongigStruct);
    /* 用在电机控制上下桥臂需要设置死区时间等 */
    BDTConfig.RMOS_State      = TMR_RMOS_STATE_ENABLE;
    BDTConfig.IMOS_State      = TMR_IMOS_STATE_ENABLE;
    BDTConfig.lockLevel       = TMR_LOCK_LEVEL_OFF;
    BDTConfig.deadTime      = 0x01;
    BDTConfig.breakState      = TMR_BREAK_STATE_DISABLE;
    BDTConfig.breakPolarity   = TMR_BREAK_POLARITY_HIGH;
    BDTConfig.automaticOutput = TMR_AUTOMATIC_OUTPUT_ENABLE;
    TMR_ConfigBDT(TMR1, &BDTConfig);
    /* Timer1 Commutation Interrupt */
    TMR_EnableInterrupt(TMR1, TMR_INT_CCU);
    NVIC_EnableIRQ(TMR1_BRK_UP_TRG_COM_IRQn);
    /* Enable Capture Compare Preload Control */
    TMR_EnableCCPreload(TMR1);
    TMR_EnablePWMOutputs(TMR1);
    TMR_Enable(TMR1);
    while (1)
    {
      /* 每隔1s产生com事件*/
      Delay_ms(100);
      TMR_GenerateEvent(TMR1, TMR_EVENT_CCU);
}
在com中断函数中进行6拍换相,根据下图所示的开关切换方式进行换相;

void TMR1_BRK_UP_TRG_COM_IRQHandler(void)
{
    /* The interrupt flag bit must be cleared first. */
    /* 清除TMR1 COM中断标志位*/
    TMR_ClearIntFlag(TMR1, TMR_INT_CCU);
    PWMStep++;
    switch (PWMStep)
    {
      case 1:
            /* configuration: Channel1 and Channel2 PWM1 Mode */
            TMR_SelectOCxMode(TMR1, TMR_CHANNEL_1, TMR_OC_MODE_PWM1);
            TMR_SelectOCxMode(TMR1, TMR_CHANNEL_2, TMR_OC_MODE_PWM1);
            /* configuration: Channel1 */
            TMR_EnableCCxChannel(TMR1, TMR_CHANNEL_1);
            TMR_DisableCCxNChannel(TMR1, TMR_CHANNEL_1);
            /* configuration: Channel2 */
            TMR_DisableCCxChannel(TMR1, TMR_CHANNEL_2);
            TMR_EnableCCxNChannel(TMR1, TMR_CHANNEL_2);
            /* configuration: Channel3 */
            TMR_DisableCCxChannel(TMR1, TMR_CHANNEL_3);
            TMR_DisableCCxNChannel(TMR1, TMR_CHANNEL_3);
            break;
      case 2:
            /* configuration: Channel2 and Channel3 PWM1 Mode */
            TMR_SelectOCxMode(TMR1, TMR_CHANNEL_2, TMR_OC_MODE_PWM1);
            TMR_SelectOCxMode(TMR1, TMR_CHANNEL_3, TMR_OC_MODE_PWM1);
            /* configuration: Channel1 */
            TMR_DisableCCxChannel(TMR1, TMR_CHANNEL_1);
            TMR_DisableCCxNChannel(TMR1, TMR_CHANNEL_1);
            /* configuration: Channel2 */
            TMR_DisableCCxChannel(TMR1, TMR_CHANNEL_2);
            TMR_EnableCCxNChannel(TMR1, TMR_CHANNEL_2);
            /* configuration: Channel3 */
            TMR_EnableCCxChannel(TMR1, TMR_CHANNEL_3);
            TMR_DisableCCxNChannel(TMR1, TMR_CHANNEL_3);
            break;
      case 3:
            /* configuration: Channel3 and Channel1 PWM1 Mode */
            TMR_SelectOCxMode(TMR1, TMR_CHANNEL_3, TMR_OC_MODE_PWM1);
            TMR_SelectOCxMode(TMR1, TMR_CHANNEL_1, TMR_OC_MODE_PWM1);
            /* configuration: Channel1 */
            TMR_DisableCCxChannel(TMR1, TMR_CHANNEL_1);
            TMR_EnableCCxNChannel(TMR1, TMR_CHANNEL_1);
            /* configuration: Channel2 */
            TMR_DisableCCxChannel(TMR1, TMR_CHANNEL_2);
            TMR_DisableCCxNChannel(TMR1, TMR_CHANNEL_2);
            /* configuration: Channel3 */
            TMR_EnableCCxChannel(TMR1, TMR_CHANNEL_3);
            TMR_DisableCCxNChannel(TMR1, TMR_CHANNEL_3);
            break;
      case 4:
            /* configuration: Channel1 and Channel2 PWM1 Mode */
            TMR_SelectOCxMode(TMR1, TMR_CHANNEL_1, TMR_OC_MODE_PWM1);
            TMR_SelectOCxMode(TMR1, TMR_CHANNEL_2, TMR_OC_MODE_PWM1);
            /* configuration: Channel1 */
            TMR_DisableCCxChannel(TMR1, TMR_CHANNEL_1);
            TMR_EnableCCxNChannel(TMR1, TMR_CHANNEL_1);
            /* configuration: Channel2 */
            TMR_EnableCCxChannel(TMR1, TMR_CHANNEL_2);
            TMR_DisableCCxNChannel(TMR1, TMR_CHANNEL_2);
            /* configuration: Channel3 */
            TMR_DisableCCxChannel(TMR1, TMR_CHANNEL_3);
            TMR_DisableCCxNChannel(TMR1, TMR_CHANNEL_3);
            break;
      case 5:
            /* configuration: Channel2 and Channel3 PWM1 Mode */
            TMR_SelectOCxMode(TMR1, TMR_CHANNEL_2, TMR_OC_MODE_PWM1);
            TMR_SelectOCxMode(TMR1, TMR_CHANNEL_3, TMR_OC_MODE_PWM1);
            /* configuration: Channel1 */
            TMR_DisableCCxChannel(TMR1, TMR_CHANNEL_1);
            TMR_DisableCCxNChannel(TMR1, TMR_CHANNEL_1);
            /* configuration: Channel2 */
            TMR_EnableCCxChannel(TMR1, TMR_CHANNEL_2);
            TMR_DisableCCxNChannel(TMR1, TMR_CHANNEL_2);
            /* configuration: Channel3 */
            TMR_DisableCCxChannel(TMR1, TMR_CHANNEL_3);
            TMR_EnableCCxNChannel(TMR1, TMR_CHANNEL_3);
            break;
      case 6:
            /* configuration: Channel3 and Channel1 PWM1 Mode */
            TMR_SelectOCxMode(TMR1, TMR_CHANNEL_3, TMR_OC_MODE_PWM1);
            TMR_SelectOCxMode(TMR1, TMR_CHANNEL_1, TMR_OC_MODE_PWM1);
            /* configuration: Channel1 */
            TMR_EnableCCxChannel(TMR1, TMR_CHANNEL_1);
            TMR_DisableCCxNChannel(TMR1, TMR_CHANNEL_1);
            /* configuration: Channel2 */
            TMR_DisableCCxChannel(TMR1, TMR_CHANNEL_2);
            TMR_DisableCCxNChannel(TMR1, TMR_CHANNEL_2);
            /* configuration: Channel3 */
            TMR_DisableCCxChannel(TMR1, TMR_CHANNEL_3);
            TMR_EnableCCxNChannel(TMR1, TMR_CHANNEL_3);
            PWMStep = 0;
            break;
      default:
            PWMStep = 0;
            break;
    }
}
开发板接到逻辑分析仪进行检测,接线如图:

逻辑分析仪波形如下:



迷雾隐者 发表于 2025-8-4 19:42

测评很详细,特别是无刷电机的6拍控制信号部分,学习了!

幻想收藏家 发表于 2025-8-6 21:21

测评很详细,APM32E030的性能看起来不错,特别是在无刷电机控制方面。
页: [1]
查看完整版本: 极海APM32E030 Micro-EVB开发板测评+无刷电机6拍控制信号测评