基于STM32的伺服总线EtherCAT主站设计——SOEM方案

本文介绍在正点原子的STM32H743开发板上,使用SOEM方案实现EtherCAT主站通讯,本文记录从零基础学习路线。由于本人才疏学浅,如有错误,还请指正。

下文蓝色带下划线为参考资料的网址链接,蓝色字体为参考资料名称。

一、EtherCAT介绍

在了解EtherCAT之前,建议对于TCP/IP的概念有一些了解,可以观看正点原子的介绍视频:【正点原子】手把手教你学lwIP_哔哩哔哩_bilibili(建议看完前7讲)

对于EtherCAT概念的了解,可以观看:【工业通讯】EtherCAT&EtherNet/IP基础知识讲解合集_哔哩哔哩_bilibili

本项目移植过程中,参考的文献如下:

[1]王惠娇. 基于嵌入式平台的EtherCAT主站实现研究[D].郑州大学,2018.

[2]毛令. 基于STM32的嵌入式EtherCAT主站的研究与实现[D].北方民族大学,2022

[1]刘豪志. 基于嵌入式Linux的EtherCAT主站设计及伺服控制系统研究[D].南京航空航天大学,2020.

以上绍视频和文献,对于ETH和EtherCAT帧结构、寻址模式、通讯模式、同步模式等知识点讲解比较清晰,这里就不展开介绍。我们就直入主题,介绍在STM32H743基于SOEM实现EtherCAT通讯的移植和调试过程。

二、SOME库架构分析

SOEM的代码的官网下载链接:GitHub -OpenEtherCATsociety/SOEM: Simple Open Source EtherCAT Master

SOEM库采用分层设计,并且提供了一个抽象层,将SOEM协议栈与具体操作系统和硬件分开。抽象层由OSAL和OSHW两个模块组成,OSAL是操作系统抽象层,OSHW 是硬件抽象层,移植的主要内容就是对OSAL和OSHW具体API实现,在新的操作系统和硬件平台上的重写。

SOEM的层级架构如下图所示:

基于STM32的伺服总线EtherCAT主站设计——SOEM方案_第1张图片

2.1 抽象层

抽象层可以分为操作系统抽象层OSAL硬件抽象层OSHW两部分。

OSAL模块侧重于操作系统的抽象和时间机制。由osal.h和osal.c组成。定义了基本数据类型,时间相关结构以及时间和定时器相关API和线程相关API。其中的时间和定时器相关的API是必须实现的,线程相关的API不是必须实现的。

OSHW模块侧重于为上层提供网络服务。由oshw.h/oshw.c和nicdrv.h/nicdrv.c四个文件组成。oshw.h/.c主要实现网络大小端和本地大小端的转换,nicdrv.h/.c是网络驱动,主要实现 EtherCAT帧的发送和接收。

不同平台上nicdrv模块的逻辑结构基本相同,需要实现的是三个底层API:

(1)网口的初始化 (2)MAC层帧发送 (3)MAC层帧接收

2.2 中间层

SOEM的中间层,是EtherCAT协议 栈的具体实现,包含BASE模块、MAIN模块、CONFIG模块、CONFIGDC模块、COE等。各层的功能如下表所示。

功能

BASE

将工业应用数据组装成 EtherCAT 帧

MAIN

顺序寻址、广播方式、配置地址、逻辑地址方式对从站读写读写从站 EEPROM

CONFIG

提供邮箱模式的非过程数据读写和三缓冲模式的过程数据 PDO读写初始化从站控制器的寄存器,配置从站FMMU

CONFIGDC

提供分布式时钟,实现主从站之间时钟同步

COE

CANOpen Over EtherCAT

FOE

File Over EtherCAT

SOE

Sercos Over EtherCAT

2.3 应用层

APP应用层并不属于SOEM库,应用层调用SOEM提供的服务,实现具体的应用,由用户按所需自行编辑。

三、移植SOEM到嵌入式平台STM32H743

本项目的移植流程参考文献:[1]王惠娇. 基于嵌入式平台的EtherCAT主站实现研究[D].郑州大学,2018.

网上也有人提供了程序源码,如以下的链接是基于STM32H743实现:

EasyControl ethercat总线 精简主从站方案 (amobbs.com 阿莫电子论坛

基于stm32和soem的EtherCAT主站代码分享 (amobbs.com 阿莫电子论坛

3.1 以太网口电路

移植SOEM到嵌入式平台的过程就是重写SOEM抽象层的过程。在STM32H743的开发板上,通过RMII外接一个PHY芯片,型号是LAN8720A。STM32H743的以太网口电路详见官方资料《STM32H7开发指南-HAL库版本_V1.0 66.1.1》介绍。

使用RMII接口,其电路图如下:

基于STM32的伺服总线EtherCAT主站设计——SOEM方案_第2张图片

以太网口的电路,具体可参考网上博主的教程:基于STM32构建EtherCAT主站(SOEM方案)3_stm32 ethercat_拉松的博客

3.2 主站时钟优化

STM32H743具有400MHz的CPU频率,可是实现微秒级别精度的系统时钟。为了避免使用tick机制实现系统时钟的中断干扰,采用硬件定时器级联,将TIM3和TIM2二者级联起来,其中TIM2为32位计时器,TIM3为16位计时器,将二者连起来实现48比特系统时间。

设置TIM2频率1MHz,1us计数一次。配置TIM2输出一个1Hz的时钟信号,作为TIM3的输入端。这样,TIM2的计数值就是微秒数,TIM5的计数值是秒数。

代码如下:

//计时器 通过读取CNT值实现计时 避免中断的影响 TIM2 TIM3
//设置TIM2主模式,输入时钟1mhz,产生1hz的TRGO信号
//设置TIM3为从模式,时间源为TIM2更新信号
void PhyTim_EtherCAT_Init(void)
{
    //-----------------TIM2初始化------------------//
    TIM_ClockConfigTypeDef sClockSourceConfig;    
    TIM_MasterConfigTypeDef sMasterConfig;                //定时器主模式配置
    TIM_SlaveConfigTypeDef sSlaveConfig;                //定时器从模式配置
        
    TIM2_Handler.Instance = TIM2;                        //通用定时器2
    TIM2_Handler.Init.Prescaler=199;                     //分频
    TIM2_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;    //向上计数器
    TIM2_Handler.Init.Period=1000000-1;                  //自动装载值
    TIM2_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频因子
    TIM2_Handler.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;        //自动重装载 写入新值后,计数器完成当前旧的计数后,再开始新的计数周期
    HAL_TIM_Base_Init(&TIM2_Handler);            
    
    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;        //使用内部时钟源 外部触发预分频器 关闭预分频器  TIM2->SMCR 
    HAL_TIM_ConfigClockSource(&TIM2_Handler, &sClockSourceConfig);        //定时器时钟配置    
    
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;                //TIM2设置为主模式
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;                            // 选择更新事件作为触发输出 (TRGO)
    HAL_TIMEx_MasterConfigSynchronization(&TIM2_Handler, &sMasterConfig);     
    
    HAL_TIM_Base_Start(&TIM2_Handler);                 //使能定时器2   
    
    //-----------------TIM3初始化------------------//   
    TIM3_Handler.Instance = TIM3;                                                                            //通用定时器3
    TIM3_Handler.Init.Prescaler = 0;                                   //不分频
    TIM3_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;                //向上计数器
    TIM3_Handler.Init.Period = 50000;                                //自动装载值
    TIM3_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;          //时钟分频因子
    HAL_TIM_Base_Init(&TIM3_Handler);
    
    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_ITR1;  //定时器时钟源选择
    HAL_TIM_ConfigClockSource(&TIM3_Handler, &sClockSourceConfig);
        
    sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNAL1;    //外部时钟模式1 由所选触发信号 (TRGI) 的上升沿提供计数器时钟 TIM3->SMCR[2;0]=111
    sSlaveConfig.InputTrigger = TIM_TS_ITR1;                        // 输入触发:选择 ITR0 作为输入源
    sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;// 触发极性:上升沿
    sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;// 触发预分频:无
    sSlaveConfig.TriggerFilter = 0x0;                         // 滤波:不需要任何滤
    HAL_TIM_SlaveConfigSynchronization(&TIM3_Handler, &sSlaveConfig);   //定时器从模式配置
    
    HAL_TIM_Base_Start(&TIM3_Handler);
}



//定时器底册驱动,开启时钟,设置中断优先级
//此函数会被HAL_TIM_Base_Init()函数调用
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
    if(htim->Instance==TIM6)      //0.5ms   TIM6  
    {
        __HAL_RCC_TIM6_CLK_ENABLE();
        HAL_NVIC_SetPriority(TIM6_DAC_IRQn,3,1);
        HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
    }
    else if(htim->Instance==TIM7)   //2ms   TIM7
    {
        __HAL_RCC_TIM7_CLK_ENABLE();
        HAL_NVIC_SetPriority(TIM7_IRQn,4,1);
        HAL_NVIC_EnableIRQ(TIM7_IRQn);
    }
    else if(htim->Instance==TIM2)   // TIM2
    {
        __HAL_RCC_TIM2_CLK_ENABLE();
    }
    else if(htim->Instance==TIM3)   // TIM3
    {
        __HAL_RCC_TIM3_CLK_ENABLE();
    }
}

//读取时间
uint32_t GetSec(void)   //获取时间/秒
{
    return TIM3->CNT;
}


uint32_t GetUSec(void)   //获取时间/微妙
{
    return TIM2->CNT;
}

参考资料:STM32定时器同步模式 四种_tim_masterconfigtypedef_luowei_memory的博客

3.3 网络驱动移植

STM32H743的ETH介绍详见 《STM32H7开发指南-HAL库版本_V1.0 66.1.1》,正点原子的教程也有介绍:【正点原子】手把手教你学lwIP_哔哩哔哩_bilibili

nicdrv负责Ethernet帧的打包和解包,需要实现EtherCAT帧通过MAC层发送出去,并将从MAC层接收到的EtherCAT帧送给nicdrv。Nicdrv模块的实现是EtherCAT移植的关键。

参考网上博主的介绍,相应的代码更改为H743即可。

基于STM32构建EtherCAT主站(SOEM方案)2_stm32 ethercat_拉松的博客

基于STM32构建EtherCAT主站(SOEM方案)5_拉松的博客

在调试的时候,报错找不到从站,经过调试时PHY初始化的时候,滤波模式没有设置好(F767为混杂模式设置),修正后的代码如下:

//LAN8720初始化
int32_t Lan8720_Init(void)
{    
    //===============================================================MAC====================================================================
    
    u32 sn0 = *((vu32*)(0x1FF0F420));            //获取STM32的唯一ID的前24位作为MAC地址后三字节
    u8 macaddress[6];       //MAC地址

    //MAC地址设置(高三字节固定为:2.0.0,低三字节用STM32唯一ID)
    macaddress[0]=2;                    //高三字节(IEEE称之为组织唯一ID,OUI)地址固定为:2.0.0
    macaddress[1]=0;
    macaddress[2]=0;
    macaddress[3]=(sn0>>16)&0XFF;       //低三字节用STM32的唯一ID
    macaddress[4]=(sn0>>8)&0XFF;
    macaddress[5]=sn0&0XFF;

    //硬件复位
    __set_PRIMASK(1);                     //关闭所有中断,复位过程不能被打断!
    PhyPCF8574_WriteBit(ETH_RESET_IO,1);       //硬件复位
    delay_ms(100);
    PhyPCF8574_WriteBit(ETH_RESET_IO,0);       //复位结束
    delay_ms(100);
    __set_PRIMASK(0);                     //开启所有中断
   
    NETMPU_Config();                        //MPU保护设置

    ETH_Handler.Instance=ETH;                               //ETH
    ETH_Handler.Init.MACAddr=macaddress;                    //MAC地址
    ETH_Handler.Init.MediaInterface=HAL_ETH_RMII_MODE;        //RMII接口
    ETH_Handler.Init.RxDesc=DMARxDscrTab;                   //发送描述符
    ETH_Handler.Init.TxDesc=DMATxDscrTab;                   //接收描述符
    ETH_Handler.Init.RxBuffLen=ETH_MAX_PACKET_SIZE;         //接收长度
     
    //初始化ETH
    HAL_ETH_Init(Ð_Handler);

    memset(&TxConfig, 0 , sizeof(ETH_TxPacketConfig));
    TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;    //Tx数据包硬件功能
    TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;                    //指定校验和插入控件:启用 IP 标头校验和和有效负载校验和计算和插入
    TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;                                               //指定CRC和Pad插入和替换控件
    
    
    
    //===============================================================PHY====================================================================
    
    uint32_t idx, duplex, speed = 0;
    int32_t PHYLinkState;       //Lan8720状态
    
    ETH_MACConfigTypeDef MACConf;           //ETH MAC 配置结构定义
    ETH_MACFilterConfigTypeDef filterDef;   //ETH MAC滤波器结构定义
    
    HAL_ETH_GetMACFilterConfig(Ð_Handler,&filterDef);        //获取 ETH MAC 过滤器配置
    filterDef.PromiscuousMode = ENABLE;                         //过滤器使能PM模式
    HAL_ETH_SetMACFilterConfig(Ð_Handler,&filterDef);        //设置ETH MAC 过滤器
    
    //将内存缓冲区分配给 DMA Rx 描述符
    for(idx = 0; idx < ETH_RX_DESC_CNT; idx ++)
    {
        HAL_ETH_DescAssignMemory(Ð_Handler, idx, Rx_Buff[idx], NULL);
    }
    
    
    
    //===============================================================LAN8720=================================================================    
    
    uint32_t regvalue = 0, addr = 0;
    u32 timeout=0;          //超时计时
    u32 regval=0;           //lan8720addr 只有一个网口 默认使用0
    u32 phylink=0;
    
    HAL_StatusTypeDef rtn;          //定义HAL状态结构
    
    HAL_ETH_SetMDIOClockRange(Ð_Handler);        //配置ETH MDIO接口的时钟范围
    
    //获取lan8720地址
    lan8720addr = 32;
    for(addr = 0; addr <= lan8720addr; addr ++)
    {
        rtn = HAL_ETH_ReadPHYRegister(Ð_Handler, addr, LAN8720_SMR, ®value);
        if( rtn != HAL_OK){continue;}
        if((regvalue & LAN8720_SMR_PHY_ADDR) == addr)
        {
            lan8720addr = addr;
            break;
        }
    }

    
    if(LAN8720_WritePHY(LAN8720_BCR,LAN8720_BCR_SOFT_RESET)>=0) //LAN8720软件复位 判断LAN8720寄存器读写是否正常
    {
        //等待软件复位完成
        if(LAN8720_ReadPHY(LAN8720_BCR,®val)>=0)
        {
            while(regval&LAN8720_BCR_SOFT_RESET)
            {
                if(LAN8720_ReadPHY(LAN8720_BCR,®val)<0)
                {
                    PHYLinkState=LAN8720_STATUS_READ_ERROR;
                    break;
                }
                delay_ms(10);
                timeout++;
                if(timeout>=LAN8720_TIMEOUT) break; //超时跳出,5S
            }
        }
        else
        {
            PHYLinkState=LAN8720_STATUS_READ_ERROR;
        }
    }
    else
    {
        PHYLinkState=LAN8720_STATUS_WRITE_ERROR;
    }
    
    
    //===============================================================SET=================================================================       
    
     do
    {
        delay_ms(100);
        PHYLinkState = LAN8720_GetLinkState();                //读取链接状态
    }while(PHYLinkState <= LAN8720_STATUS_LINK_DOWN);

    
    
    //打印连接状态
    printf("ETH工作状态: ");
    switch (PHYLinkState)
    {
        case LAN8720_STATUS_100MBITS_FULLDUPLEX:
            duplex = ETH_FULLDUPLEX_MODE;
            speed = ETH_SPEED_100M;
            printf(" 100Mb/s FullDuplex \r\n");
        break;
        case LAN8720_STATUS_100MBITS_HALFDUPLEX:
            duplex = ETH_HALFDUPLEX_MODE;
            speed = ETH_SPEED_100M;
            printf(" 100Mb/s HalfDuplex \r\n");
        break;
        case LAN8720_STATUS_10MBITS_FULLDUPLEX:
            duplex = ETH_FULLDUPLEX_MODE;
            speed = ETH_SPEED_10M;
            printf(" 10Mb/s FullDuplex \r\n");
        break;
        case LAN8720_STATUS_10MBITS_HALFDUPLEX:
            duplex = ETH_HALFDUPLEX_MODE;
            speed = ETH_SPEED_10M;
            printf(" 10Mb/s HalfDuplex \r\n");
        break;
        default:
            duplex = ETH_FULLDUPLEX_MODE;
            speed = ETH_SPEED_100M;
            printf(" 100Mb/s FullDuplex__ \r\n");
        break;      
    }
    

    HAL_ETH_GetMACConfig(Ð_Handler, &MACConf);           //获取 MAC 和 MTL 子系统的配置
    MACConf.DuplexMode = duplex;                            //ETH工作模式 全双工/半双工
    MACConf.Speed = speed;                                  //ETH传输速度
    MACConf.TransmitQueueMode = ETH_TRANSMITTHRESHOLD_128;  //ETH传输模式 128字节
    HAL_ETH_SetMACConfig(Ð_Handler, &MACConf);           //MAC 配置
    HAL_ETH_Start_IT(Ð_Handler);                         //开启ETH中断
    
    HAL_ETH_BuildRxDescriptors(Ð_Handler);               //将上次接收的数据包的 Rx Desc返回给 DMA
}

四、主站软件系统测试

上一节参考链接介绍,已经将Ether CAT主站协议库SOEM成功移植到嵌入式平台STM32H743上,本章从EtherCAT主站实现的有效性、可靠性、稳定性出发,对嵌入式平台的EtherCAT主站驱动从站进行测试分析。

4.1 硬件平台搭建

本项目调试所使用的伺服驱动器为英威腾的DA200,对于该伺服的介绍乐意查看以下链接:DA200交流伺服驱动器

实验平台及接线如下图所示,参考《DA200系列交流伺服驱动器中文说明书V2.2_3.2.1节》

基于STM32的伺服总线EtherCAT主站设计——SOEM方案_第3张图片

参考说明书《英威腾SV-DA200交流伺服驱动器_EtherCAT技术指南V2.62》的第2章,在ServoPlorer软件上设置以下参数:

参数

名称

数值

P0.01

电机代码

2300

P0.03

控制模式选择

8 [EtherCAT 模式]

P4.08

EtherCAT 同步类型

2: DCMode

P4.07

EtherCAT同步周期

2: 1ms

P4.09

EtherCAT 故障检测时间

100ms

4.2 EtherCAT应用层编辑

使用EtherCAT控制伺服电机,具体的配置可以总结为以下过程:

EtherCAT初始化过程

相关函数

配置初始化

ec_init()

ec_config_init(FALSE)

INVT_DA200_setup()

分配分布式时钟

ec_configdc()

配置过程数据映射

ec_config_map(&IOmap)

请求所有从站进入到安全模式

4.2.1 PDO 映射

其中的INVT_DA200_setup()为从站伺服器的PDO映射,参考《英威腾SV-DA200交流伺服驱动器_EtherCAT技术指南》介绍,具体的操作步骤为:

基于STM32的伺服总线EtherCAT主站设计——SOEM方案_第4张图片

英威腾 PDO 映射的操作步骤代码如下:

// 英威腾 PDO 映射的操作步骤
int INVT_DA200_setup(uint16 slvcnt)
{
    EtherCAT_write8(slvcnt, 0x1C12, 00, 0);                // 1 停止PDO分配功能(将0x1C12和0x1C13的子索引0设置为0) 
    EtherCAT_write8(slvcnt, 0x1600, 00, 0);                // 2 停止PDO映射功能(将0x1600~0x1603和0x1A00~0x1A03的子索引0全部设置为0)
    EtherCAT_write32(slvcnt, 0x1600, 01, 0x60400010);        // 3 设置PDO映射对象(0x1600~0x1603和0x1A00~0x1A03)的映射入口
    EtherCAT_write32(slvcnt, 0x1600, 02, 0x607A0020);        // 3 设置PDO映射对象(0x1600~0x1603和0x1A00~0x1A03)的映射入口
    EtherCAT_write8(slvcnt, 0x1600, 00, 2);                // 4 设置PDO映射对象(0x1600~0x1603和0x1A00~0x1A03)映射入口的数值
    EtherCAT_write16(slvcnt, 0x1C12, 01, 0x1600);            // 5 设置PDO分配对象(设置0x1C12和0x1C13的子索引1);
    EtherCAT_write8(slvcnt, 0x1C12, 00, 1);                // 6 重新打开PDO分配功能(将0x1C12和0x1C13的子索引0设置为1)
    
    /**********************************************************************************************************/
    EtherCAT_write8(slvcnt, 0x1C13, 00, 0);                // 1 停止PDO分配功能(将0x1C12和0x1C13的子索引0设置为0) 
    EtherCAT_write8(slvcnt, 0x1A00, 00, 0);                // 2 停止PDO映射功能(将0x1600~0x1603和0x1A00~0x1A03的子索引0全部设置为0)
    EtherCAT_write32(slvcnt, 0x1A00, 01, 0x60410010);        // 3 设置PDO映射对象(0x1600~0x1603和0x1A00~0x1A03)的映射入口
    EtherCAT_write32(slvcnt, 0x1A00, 02, 0x60640020);        // 3 设置PDO映射对象(0x1600~0x1603和0x1A00~0x1A03)的映射入口
    EtherCAT_write8(slvcnt, 0x1A00, 00, 2);                // 4 设置PDO映射对象(0x1600~0x1603和0x1A00~0x1A03)映射入口的数值
    EtherCAT_write16(slvcnt, 0x1C13, 01, 0x1A00);            // 5 设置PDO分配对象(设置0x1C12和0x1C13的子索引1);
    EtherCAT_write8(slvcnt, 0x1C13, 00, 1);                // 6 重新打开PDO分配功能(将0x1C12和0x1C13的子索引0设置为1)
    
    EtherCAT_write8(slvcnt, 0x6060, 00, 8);                 //设置操作模式 :周期性同步位置模式
    
    return 0;
}

4.2.2 EtherCAT 状态机

此外,还要实现EtherCAT状态机,状态机用于描述从站应用的状态和状态改变。状态改变请求通常由主站发起,从站响应。具体状态跳转方式如下图:

基于STM32的伺服总线EtherCAT主站设计——SOEM方案_第5张图片

状态机的实现代码如下所示:

//EtherCAT状态机
void EtherCAT_ctrl_state(void)
{ 
    switch (outputs1->controlword)          //获取当前状态 0x6041状态字   
    {
        case 0:                             //Switch on disabled
            outputs1->controlword = 6;      //Shutdown
        break;
        
        case 6:                             //Ready to switch on
            outputs1->controlword = 7;      //Disable voltage  +  Quick stop
        break;
        
        case 7:                             //Switched on
            outputs1->targetPostion = inputs1->actualPostion;       //查询【6064h: Position actual value】来获取电机实际位置反馈
            outputs1->controlword = 0x0f;   // Enable operation
        break;
        
        case 0x0f:                          //Operation enabled
            if( OpenReady == 0 )
                OpenReady = 1;
            else
                OpenReady = 0;
        break;
            
        default:
            outputs1->controlword = 6;      //Shutdown
        break;        
    }   
}

对于EtherCAT状态设置主要是对6041h状态字的查询和设置,如下图所示:

基于STM32的伺服总线EtherCAT主站设计——SOEM方案_第6张图片

4.2.3 周期性同步位置模式

使用周期性同步位置模式控制电机转动,在该模式下,插补周期与 EtherCAT同步周期相同(本文设置为1ms)。

1、 设置 6060 h为 8,选择 Cyclic Synchronous Position Mode;

2、 设置 6040 h以使能驱动器,发送 0x0F;

3、 逐次设置 607A h为目标位置(绝对位置),进行位置控制。

具体的操作方法如下图所示:

基于STM32的伺服总线EtherCAT主站设计——SOEM方案_第7张图片

通过逐次设置 607A h为目标位置(绝对位置),进行位置控制,实现电机的转动。

以上是本人使用SOEM方案在STM32H743实现EtherCAT主站通讯,的整个过程,如有错误,还请指教交流。

你可能感兴趣的:(CANopen,EtherCAT,stm32,单片机,嵌入式硬件)