目录

一、生成协议栈及XML文件

 二、使用stm32CuboMX配置外设

 三、协议栈移植


         鉴于本人对EtherCAT的掌握程度十分有限,这篇文章仅作为我搭建基础从站的过程记录不做更多讲解。本文内容主要为SPI模式的基础搭建,更多深入的学习资料和细节,大家可以通过进一步的网上搜索来获取。

软件工具:XMLNotepad2007,SSC_V5.11,TwinCAT3,Keil5,STM32CubeMX

资源:lan9252-pic32-sdk_v1.1

一、生成协议栈及XML文件

        我是使用的 SSC_V5.11 来自动生成协议栈与XML文件,期间使用到了LAN9252的官方SDK文件 lan9252-pic32-sdk_v1.1 版本,网站有许多资源可以自行下载。流程可参考官方的 AN1916 文件

1. 下载完SSC_V5.11后找到并打开SSC Tool程序。

 2. 点击左上角 File -> New 弹出新建工程的选项卡,选择左下角 Import  -> 选择lan9252-pic-32_sdk_v1.1 文件夹下的 Microchip_LAN9252_SSC_Config.xml 导入官方的工程模板,一路确定完成导入。

 

 3. 选择 Custom -> Microchip-SPI-GPIO -> OK 使用官方模板后,XML中的一些参数就不需要自己来修改了,非常的方便。

 4. 点击OK后会提示让你选取9252_HW.c文件,这个文件可以在lan9252-pic-32_sdk_v1.1/SSC/Common文件夹下找到。

 

 

        完成之后是这样的一个界面,可以按需自行更改项目信息,这里只是自己为了搭建从站进行测试,我这里先不做任何的修改。想了解里面每一项功能的可以阅读下面这篇文章

EtherCAT Slave Stack Code Tool(SSC)使用笔记-CSDN博客文章浏览阅读1w次,点赞87次,收藏190次。学习EtherCAT有几个月了,准备做一个EtherCAT从站,摸爬滚打一路走来,遇到不少问题,这里仅作学习记录使用。移植过的平台 STM32F103,STM32F407,ari32F103。从站芯片LAN9252。EtherCAT Slave Stack Code Tool (SSC) V5.12(该软件自动生成EtherCAT从站核心代码。_slave stack code tool https://blog.csdn.net/efei123/article/details/136231104?fromshare=blogdetail&sharetype=blogdetail&sharerId=136231104&sharerefer=PC&sharesource=a1547998353&sharefrom=from_link

 5.使用Excel配置对象字典

        通过选择上方工具栏 Tool -> Application -> Create new 来创建Excel设置通信数据,第一次创建会先提示你保存项目,自己新建一个文件夹保存进去即可。

刚刚创建的Excel如下,0x6000~0x6FFF 定义输入,0x7000~0x7FFF定义输出(这里的输入输出是以主站的角度来看的),我们可以在对应位置添加自己的对象。

 按自己的需求简单创建对象,d1用来测通讯,d2用来补位。

需要注意这里一定要四字节对齐!!!一定要四字节对齐!!!一定要四字节对齐!!!

因为我们后面移植协议栈时需要删除 __packed 关键字,删除之后会变成默认的四字节对齐,创建字典时如果没有字节对齐会导致与从站通讯不上,编译代码时还不会报错,到时候找问题你就找去吧,一找一个不吱声别问我咋发现的T^T。

添加完后保存并退出,弹出的窗口点击OK。

6.生成协议栈源码

        点击左上角 Project -> Create new Slave Files -> 右下角Start -> OK ->Close 完成之后关闭SSC Tool工具就可以了。

 

         这时候打开刚刚工程的保存位置,看见如下四个文件说明成功了。其中 Src 里面保存的就是自动生成的协议栈代码,不过是基于PIC32的,后面我们将把它慢慢修改成STM32的代码。 .xml 文件后续我们需要通过 TwinCAT 烧写进从站的EEPROM,想要阅读可以使用 XMLNotepad 工具,网上有很多资源可以自己按需下载。

7. 官方给的SDK文件里有我们需要的SPI驱动,将驱动的.c .h文件复制到刚刚生成的Src文件夹内。

 二、使用stm32CuboMX配置外设

与LAN9252的SPI通讯需要以下几个外设:

1. 一组4线标准SPI

2. 1ms定时器

3. 三个外部中断 :主中断 IRQ,两个时钟同步中断 SYNC0、SYNC1

 时钟树:

1ms定时器:

 SPI配置:记得额外配置SPI_CS

外部中断配置:下降沿触发

 配置中断优先级:IRQ与1ms定时中断抢占优先级1,两个时钟同步中断抢占优先级2

 

到此与LAN9252通讯需要的外设已经配置完成了,接下来可以配置其他自己所需的外设。

比如我在最一开始在字典的输出部分加入的LED来测试通讯功能。

创建工程:

 打开刚刚创建的工程,将刚刚生成的Src文件夹中的内容全部添加到项目,熟悉之后可以按自己的喜好和习惯分组,我这边直接全部放在了ECAT文件夹下了。

 三、协议栈移植

        此时编译会产生一大堆报错,不要害怕,我们一点一点改掉就好了。接下来我会带你们挨个的解决这些报错,希望各位在抄答案前先能自己尝试着慢慢修改,一定能有所收货。

遇到的报错及解决方案:

我们从第一个错误位置开始依次往下解决

..\EtherCAT\Src\9252_HW.c(190): warning:  #223-D: function "INTDisableInterrupts" declared implicitlyDISABLE_AL_EVENT_INT;

通过全局搜索定位到当前文件的106行,通过宏明可以看出这是关闭全局变量的函数,将对应位置改为用stm32的方式实现,并添加对应头文件。

#include "main.h"#define DISABLE_GLOBAL_INT          __disable_irq()
#define ENABLE_GLOBAL_INT           __enable_irq()
#define DISABLE_AL_EVENT_INT        DISABLE_GLOBAL_INT
#define ENABLE_AL_EVENT_INT         ENABLE_GLOBAL_INT
..\EtherCAT\Src\9252_HW.c(256): warning:  #223-D: function "PMPWriteDWord" declared implicitlyPMPWriteDWord (0x54, data);

因为我们使用的是SPI通信,将被USE_SPI包含的252-261范围内仅保留SPIWriteDord函数,并添加SPI驱动的头文件。并对本文件内所有被#ifndef USE_SPI 过滤的代码做同样操作。

  #include "SPIDriver.h" //添加头文件//这只是部分修改后效果,未全部展示,文件内被 #ifndef USE_SPI 过滤的地方有很多,前后文都有,自己慢慢修改//IRQ enable,IRQ polarity, IRQ buffer type in Interrupt Configuration register.//Wrte 0x54 - 0x00000101data = 0x00000101;SPIWriteDWord (0x54, data);//Write in Interrupt Enable register -->//Write 0x5c - 0x00000001data = 0x00000001;SPIWriteDWord (0x5C, data);//Read Interrupt Status register//Read 0x58.SPIReadDWord(0x58);

往下划注释掉HW_SetLed()函数内的代码,并删除这之后的所有函数,那些是PIC32芯片的中断服务程序我们不需要。

void HW_SetLed(UINT8 RunLed,UINT8 ErrLed)
{/* Here RunLed is not used. Because on chip supported RUN Led is available*/    //    LED_ECATRED   = ErrLed;
}
// 这个函数之下的所有内容删除

..\EtherCAT\Src\9252_HW.c(295): error:  #20: identifier "INTCONbits" is undefinedINIT_SYNC0_INT

追踪到宏定义的位置,可以看出这是一个SYNC0的初始化函数,中断初始化的代码在使用Cubomx生成代码时已经自动添加了,我们直接把宏后面的定义内容删除,使其变成一个空的宏。

通过问题1和问题3不难发现9252_HW.c文件中的宏都是基于PIC32系列芯片来写的,我们只需要全部将其修改为适配STM32即可。

将114~166行所有宏定义用HAL库函数重写,并删除用不到的宏,全部修改完后如下所示:

#ifdef PIC32_HW
BOOL bEscInterrupt = 0;
BOOL bSync0Interrupt = 0;
BOOL bSync1Interrupt = 0;
BOOL bTimer5Interrupt = 0;
///
// Global Interrupt setting#define DISABLE_GLOBAL_INT          __disable_irq()
#define ENABLE_GLOBAL_INT           __enable_irq()
#define DISABLE_AL_EVENT_INT        DISABLE_GLOBAL_INT
#define ENABLE_AL_EVENT_INT         ENABLE_GLOBAL_INT///
// ESC Interrupt//0 - falling edge 1-
#define    INIT_ESC_INT           #define    INT_EL                  	HAL_GPIO_ReadPin(LAN9252_IRQ_GPIO_Port,LAN9252_IRQ_Pin) //ESC Interrupt input port#define    ACK_ESC_INT            	__HAL_GPIO_EXTI_CLEAR_IT(LAN9252_IRQ_Pin)#define IS_ESC_INT_ACTIVE    ((INT_EL) == 0) //0 - fro active low; 1 for hactive high
///
// SYNC0 Interrupt#ifndef RUN_FROM_SVB_FPGA#define    INIT_SYNC0_INT                    #define    INT_SYNC0                       HAL_GPIO_ReadPin(LAN9252_SYNC0_GPIO_Port,LAN9252_SYNC0_Pin) //Sync1 Interrupt input port#define    DISABLE_SYNC0_INT               HAL_NVIC_DisableIRQ(LAN9252_SYNC0_EXTI_IRQn)//{(_INT1IE)=0;}//disable interrupt source INT1#define    ENABLE_SYNC0_INT                HAL_NVIC_EnableIRQ(LAN9252_SYNC0_EXTI_IRQn) //enable interrupt source INT1#define    ACK_SYNC0_INT                   __HAL_GPIO_EXTI_CLEAR_IT(LAN9252_SYNC0_Pin)#define    IS_SYNC0_INT_ACTIVE              ((INT_SYNC0) == 0) //0 - fro active low; 1 for hactive high#define    INIT_SYNC1_INT                   #define    INT_SYNC1                        HAL_GPIO_ReadPin(LAN9252_SYNC1_GPIO_Port,LAN9252_SYNC1_Pin) //Sync1 Interrupt input port#define    DISABLE_SYNC1_INT                HAL_NVIC_DisableIRQ(LAN9252_SYNC1_EXTI_IRQn)//disable interrupt source INT2#define    ENABLE_SYNC1_INT                 HAL_NVIC_EnableIRQ(LAN9252_SYNC1_EXTI_IRQn) //enable interrupt source INT2#define    ACK_SYNC1_INT                    __HAL_GPIO_EXTI_CLEAR_IT(LAN9252_SYNC1_Pin)#define    IS_SYNC1_INT_ACTIVE              ((INT_SYNC1) == 0) //0 - fro active low; 1 for hactive high
#else// Place-holder#endif///
// Hardware timer#define STOP_ECAT_TIMER         	HAL_TIM_Base_Stop_IT(&htim7)
#define INIT_ECAT_TIMER         	HAL_TIM_Base_Init(&htim7)#define START_ECAT_TIMER          HAL_TIM_Base_Start_IT(&htim7)#endif // end of PIC32_HW

改完之后重新编译会发现少了很多错误,接着一个一个改就好了。

..\EtherCAT\Src\ecatappl.c(250): warning:  #223-D: function "HW_GetTimer" declared implicitlyStartTimerCnt = (UINT32) HW_GetTimer();

跟第一个问题同样的方法,找到宏所在位置,发现是灰色的没被编译,可以选择将限制条件#ifdef PIC32_HW 删掉,也可以选择改为#ifdef STM32F4(具体定义什么根据自己的芯片型号来,需要头文件main.h)注释掉两个没有的头文件和 “ // Defines,types ”区域内的所有内容。

将#define ECAT_TIMER_INC_P_MS 后面的数值改为你配置1ms定时器时的计数重载器的值。

再根据宏名和给的注释将152-166行附近的宏以同样的方式用HAL库函数实现。

修改后代码如下:

//添加头文件
#include "main.h"
#include "tim.h"
#include "spi.h"
#include "gpio.h"
#include "stm32f4xx_hal.h"///
// Hardware timer settings#define ECAT_TIMER_INC_P_MS              2000 /**< \brief 312 ticks per ms*////
// Interrupt and Timer Defines#ifndef DISABLE_ESC_INT#define    DISABLE_ESC_INT()           	HAL_NVIC_DisableIRQ(LAN9252_SYNC0_EXTI_IRQn) /**< \brief Disable interrupt source INT1*/
#endif
#ifndef ENABLE_ESC_INT#define    ENABLE_ESC_INT()           	HAL_NVIC_EnableIRQ(LAN9252_SYNC0_EXTI_IRQn) /**< \brief Enable interrupt source INT1*/
#endif//TODO
#ifndef HW_GetTimer#define HW_GetTimer()      		__HAL_TIM_GET_COUNTER(&htim7) /**< \brief Access to the hardware timer*/
#endif#ifndef HW_ClearTimer#define HW_ClearTimer()       __HAL_TIM_SET_COUNTER(&htim7,0) /**< \brief Clear the hardware timer*/
#endif#endif

改完再重新编译一下又少了很多错误,此时第一个错误应该是来自 SPIDriver.h 文件,接下来借此机会我们来直接修改SPI驱动使适配STM32。

在 SPIDriver.h 中修改如下内容:

删除plib.h,并增加如下头文件

#include "ecat_def.h"
#include "gpio.h"
#include "spi.h"
#include "main.h"

将宏CSLOW()与CSHIGH()修复为自己SPI的控制引脚

	#define SPI_OFF		 		HAL_GPIO_WritePin(SPI1_CS_GPIO_Port,SPI1_CS_Pin,GPIO_PIN_SET)#define SPI_ON		 		HAL_GPIO_WritePin(SPI1_CS_GPIO_Port,SPI1_CS_Pin,GPIO_PIN_RESET)#define CSLOW()      	SPI_ON#define CSHIGH()     	SPI_OFF

 在 SPIDriver.c 中修改如下内容:

删除Delay、SPIPut、SPIOpen三个函数。

修改SPIWrite与SPIRead函数,用HAL库方式实现。

void SPIWrite(UINT8 data)
{HAL_SPI_Transmit(&hspi1,&data,1,2000);
}
UINT8 SPIRead()
{UINT8 data;HAL_SPI_Receive(&hspi1,&data,1,2000);return (data);
}

剩下的就是UINT32_VAL与UINT16_VAL类型未定义引起的问题,这两个变量是PIC芯片内的库文件包含的,我们添加一个 "GenericTypeDefs.h" 头文件到工程并引用即可。

GenericTypeDefs.h

/*******************************************************************Generic Type Definitions********************************************************************FileName:        GenericTypeDefs.hDependencies:    NoneProcessor:       PIC10, PIC12, PIC16, PIC18, PIC24, dsPIC, PIC32Compiler:        MPLAB C Compilers for PIC18, PIC24, dsPIC, & PIC32Hi-Tech PICC PRO, Hi-Tech PICC18 PROCompany:         Microchip Technology Inc.Software License AgreementThe software supplied herewith by Microchip Technology Incorporated(the "Company") is intended and supplied to you, the Company'scustomer, for use solely and exclusively with products manufacturedby the Company.The software is owned by the Company and/or its supplier, and isprotected under applicable copyright laws. All rights are reserved.Any use in violation of the foregoing restrictions may subject theuser to criminal sanctions under applicable laws, as well as tocivil liability for the breach of the terms and conditions of thislicense.THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITEDTO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR APARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL ORCONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.********************************************************************File Description:Change History:Rev   Date         Description1.1   09/11/06     Add base signed types1.2   02/28/07     Add QWORD, LONGLONG, QWORD_VAL1.3   02/06/08     Add def's for PIC321.4   08/08/08     Remove LSB/MSB Macros, adopted by Peripheral lib1.5   08/14/08     Simplify file headerDraft 2.0   07/13/09     Updated for new release of coding standards
*******************************************************************/#ifndef __GENERIC_TYPE_DEFS_H_
#define __GENERIC_TYPE_DEFS_H_#ifdef __cplusplus
extern "C"{
#endif/* Specify an extension for GCC based compilers */
#if defined(__GNUC__)
#define __EXTENSION __extension__
#else
#define __EXTENSION
#endif/* get compiler defined type definitions (NULL, size_t, etc) */
#include <stddef.h>
#include "ecat_def.h"//typedef enum _BOOL { FALSE = 0, TRUE } BOOL;    /* Undefined size */
//typedef enum _BIT { CLEAR = 0, SET } BIT;#define PUBLIC                                  /* Function attributes */
#define PROTECTED
#define PRIVATE   static/* INT is processor specific in length may vary in size */
//typedef signed int          INT;
//typedef signed char         INT8;
//typedef signed short int    INT16;
//typedef signed long int     INT32;/* MPLAB C Compiler for PIC18 does not support 64-bit integers */
#if !defined(__18CXX)
__EXTENSION typedef signed long long    INT64;
#endif/* UINT is processor specific in length may vary in size */
//typedef unsigned int        UINT;
//typedef unsigned char       UINT8;
//typedef unsigned short int  UINT16;
/* 24-bit type only available on C18 */
#if defined(__18CXX)
typedef unsigned short long UINT24;
#endif
//typedef unsigned long int   UINT32;     /* other name for 32-bit integer */
/* MPLAB C Compiler for PIC18 does not support 64-bit integers */
#if !defined(__18CXX)
__EXTENSION typedef unsigned long long  UINT64;
#endiftypedef union
{UINT8 Val;struct{__EXTENSION UINT8 b0:1;__EXTENSION UINT8 b1:1;__EXTENSION UINT8 b2:1;__EXTENSION UINT8 b3:1;__EXTENSION UINT8 b4:1;__EXTENSION UINT8 b5:1;__EXTENSION UINT8 b6:1;__EXTENSION UINT8 b7:1;} bits;
} UINT8_VAL, UINT8_BITS;typedef union
{UINT16 Val;UINT8 v[2];struct{UINT8 LB;UINT8 HB;} byte;struct{__EXTENSION UINT8 b0:1;__EXTENSION UINT8 b1:1;__EXTENSION UINT8 b2:1;__EXTENSION UINT8 b3:1;__EXTENSION UINT8 b4:1;__EXTENSION UINT8 b5:1;__EXTENSION UINT8 b6:1;__EXTENSION UINT8 b7:1;__EXTENSION UINT8 b8:1;__EXTENSION UINT8 b9:1;__EXTENSION UINT8 b10:1;__EXTENSION UINT8 b11:1;__EXTENSION UINT8 b12:1;__EXTENSION UINT8 b13:1;__EXTENSION UINT8 b14:1;__EXTENSION UINT8 b15:1;} bits;
} UINT16_VAL, UINT16_BITS;/* 24-bit type only available on C18 */
#if defined(__18CXX)
typedef union
{UINT24 Val;UINT8 v[3];struct{UINT8 LB;UINT8 HB;UINT8 UB;} byte;struct{__EXTENSION UINT8 b0:1;__EXTENSION UINT8 b1:1;__EXTENSION UINT8 b2:1;__EXTENSION UINT8 b3:1;__EXTENSION UINT8 b4:1;__EXTENSION UINT8 b5:1;__EXTENSION UINT8 b6:1;__EXTENSION UINT8 b7:1;__EXTENSION UINT8 b8:1;__EXTENSION UINT8 b9:1;__EXTENSION UINT8 b10:1;__EXTENSION UINT8 b11:1;__EXTENSION UINT8 b12:1;__EXTENSION UINT8 b13:1;__EXTENSION UINT8 b14:1;__EXTENSION UINT8 b15:1;__EXTENSION UINT8 b16:1;__EXTENSION UINT8 b17:1;__EXTENSION UINT8 b18:1;__EXTENSION UINT8 b19:1;__EXTENSION UINT8 b20:1;__EXTENSION UINT8 b21:1;__EXTENSION UINT8 b22:1;__EXTENSION UINT8 b23:1;} bits;
} UINT24_VAL, UINT24_BITS;
#endiftypedef union
{UINT32 Val;UINT16 w[2];UINT8  v[4];struct{UINT16 LW;UINT16 HW;} word;struct{UINT8 LB;UINT8 HB;UINT8 UB;UINT8 MB;} byte;struct{UINT16_VAL low;UINT16_VAL high;}wordUnion;struct{__EXTENSION UINT8 b0:1;__EXTENSION UINT8 b1:1;__EXTENSION UINT8 b2:1;__EXTENSION UINT8 b3:1;__EXTENSION UINT8 b4:1;__EXTENSION UINT8 b5:1;__EXTENSION UINT8 b6:1;__EXTENSION UINT8 b7:1;__EXTENSION UINT8 b8:1;__EXTENSION UINT8 b9:1;__EXTENSION UINT8 b10:1;__EXTENSION UINT8 b11:1;__EXTENSION UINT8 b12:1;__EXTENSION UINT8 b13:1;__EXTENSION UINT8 b14:1;__EXTENSION UINT8 b15:1;__EXTENSION UINT8 b16:1;__EXTENSION UINT8 b17:1;__EXTENSION UINT8 b18:1;__EXTENSION UINT8 b19:1;__EXTENSION UINT8 b20:1;__EXTENSION UINT8 b21:1;__EXTENSION UINT8 b22:1;__EXTENSION UINT8 b23:1;__EXTENSION UINT8 b24:1;__EXTENSION UINT8 b25:1;__EXTENSION UINT8 b26:1;__EXTENSION UINT8 b27:1;__EXTENSION UINT8 b28:1;__EXTENSION UINT8 b29:1;__EXTENSION UINT8 b30:1;__EXTENSION UINT8 b31:1;} bits;
} UINT32_VAL;/* MPLAB C Compiler for PIC18 does not support 64-bit integers */
#if !defined(__18CXX)
typedef union
{UINT64 Val;UINT32 d[2];UINT16 w[4];UINT8 v[8];struct{UINT32 LD;UINT32 HD;} dword;struct{UINT16 LW;UINT16 HW;UINT16 UW;UINT16 MW;} word;struct{__EXTENSION UINT8 b0:1;__EXTENSION UINT8 b1:1;__EXTENSION UINT8 b2:1;__EXTENSION UINT8 b3:1;__EXTENSION UINT8 b4:1;__EXTENSION UINT8 b5:1;__EXTENSION UINT8 b6:1;__EXTENSION UINT8 b7:1;__EXTENSION UINT8 b8:1;__EXTENSION UINT8 b9:1;__EXTENSION UINT8 b10:1;__EXTENSION UINT8 b11:1;__EXTENSION UINT8 b12:1;__EXTENSION UINT8 b13:1;__EXTENSION UINT8 b14:1;__EXTENSION UINT8 b15:1;__EXTENSION UINT8 b16:1;__EXTENSION UINT8 b17:1;__EXTENSION UINT8 b18:1;__EXTENSION UINT8 b19:1;__EXTENSION UINT8 b20:1;__EXTENSION UINT8 b21:1;__EXTENSION UINT8 b22:1;__EXTENSION UINT8 b23:1;__EXTENSION UINT8 b24:1;__EXTENSION UINT8 b25:1;__EXTENSION UINT8 b26:1;__EXTENSION UINT8 b27:1;__EXTENSION UINT8 b28:1;__EXTENSION UINT8 b29:1;__EXTENSION UINT8 b30:1;__EXTENSION UINT8 b31:1;__EXTENSION UINT8 b32:1;__EXTENSION UINT8 b33:1;__EXTENSION UINT8 b34:1;__EXTENSION UINT8 b35:1;__EXTENSION UINT8 b36:1;__EXTENSION UINT8 b37:1;__EXTENSION UINT8 b38:1;__EXTENSION UINT8 b39:1;__EXTENSION UINT8 b40:1;__EXTENSION UINT8 b41:1;__EXTENSION UINT8 b42:1;__EXTENSION UINT8 b43:1;__EXTENSION UINT8 b44:1;__EXTENSION UINT8 b45:1;__EXTENSION UINT8 b46:1;__EXTENSION UINT8 b47:1;__EXTENSION UINT8 b48:1;__EXTENSION UINT8 b49:1;__EXTENSION UINT8 b50:1;__EXTENSION UINT8 b51:1;__EXTENSION UINT8 b52:1;__EXTENSION UINT8 b53:1;__EXTENSION UINT8 b54:1;__EXTENSION UINT8 b55:1;__EXTENSION UINT8 b56:1;__EXTENSION UINT8 b57:1;__EXTENSION UINT8 b58:1;__EXTENSION UINT8 b59:1;__EXTENSION UINT8 b60:1;__EXTENSION UINT8 b61:1;__EXTENSION UINT8 b62:1;__EXTENSION UINT8 b63:1;} bits;
} UINT64_VAL;
#endif /* __18CXX *//***********************************************************************************//* Alternate definitions */
typedef void                    VOID;typedef char                    CHAR8;
typedef unsigned char           UCHAR8;typedef unsigned char           BYTE;                           /* 8-bit unsigned  */
typedef unsigned short int      WORD;                           /* 16-bit unsigned */
typedef unsigned long           DWORD;                          /* 32-bit unsigned */
/* MPLAB C Compiler for PIC18 does not support 64-bit integers */
#if !defined(__18CXX)
__EXTENSION
typedef unsigned long long      QWORD;                          /* 64-bit unsigned */
#endif /* __18CXX */
//typedef signed char             CHAR;                           /* 8-bit signed    */
typedef signed short int        SHORT;                          /* 16-bit signed   */
typedef signed long             LONG;                           /* 32-bit signed   */
/* MPLAB C Compiler for PIC18 does not support 64-bit integers */
#if !defined(__18CXX)
__EXTENSION
typedef signed long long        LONGLONG;                       /* 64-bit signed   */
#endif /* __18CXX */
typedef union
{BYTE Val;struct{__EXTENSION BYTE b0:1;__EXTENSION BYTE b1:1;__EXTENSION BYTE b2:1;__EXTENSION BYTE b3:1;__EXTENSION BYTE b4:1;__EXTENSION BYTE b5:1;__EXTENSION BYTE b6:1;__EXTENSION BYTE b7:1;} bits;
} BYTE_VAL, BYTE_BITS;typedef union
{WORD Val;BYTE v[2];struct{BYTE LB;BYTE HB;} byte;struct{__EXTENSION BYTE b0:1;__EXTENSION BYTE b1:1;__EXTENSION BYTE b2:1;__EXTENSION BYTE b3:1;__EXTENSION BYTE b4:1;__EXTENSION BYTE b5:1;__EXTENSION BYTE b6:1;__EXTENSION BYTE b7:1;__EXTENSION BYTE b8:1;__EXTENSION BYTE b9:1;__EXTENSION BYTE b10:1;__EXTENSION BYTE b11:1;__EXTENSION BYTE b12:1;__EXTENSION BYTE b13:1;__EXTENSION BYTE b14:1;__EXTENSION BYTE b15:1;} bits;
} WORD_VAL, WORD_BITS;typedef union
{DWORD Val;WORD w[2];BYTE v[4];struct{WORD LW;WORD HW;} word;struct{BYTE LB;BYTE HB;BYTE UB;BYTE MB;} byte;struct{WORD_VAL low;WORD_VAL high;}wordUnion;struct{__EXTENSION BYTE b0:1;__EXTENSION BYTE b1:1;__EXTENSION BYTE b2:1;__EXTENSION BYTE b3:1;__EXTENSION BYTE b4:1;__EXTENSION BYTE b5:1;__EXTENSION BYTE b6:1;__EXTENSION BYTE b7:1;__EXTENSION BYTE b8:1;__EXTENSION BYTE b9:1;__EXTENSION BYTE b10:1;__EXTENSION BYTE b11:1;__EXTENSION BYTE b12:1;__EXTENSION BYTE b13:1;__EXTENSION BYTE b14:1;__EXTENSION BYTE b15:1;__EXTENSION BYTE b16:1;__EXTENSION BYTE b17:1;__EXTENSION BYTE b18:1;__EXTENSION BYTE b19:1;__EXTENSION BYTE b20:1;__EXTENSION BYTE b21:1;__EXTENSION BYTE b22:1;__EXTENSION BYTE b23:1;__EXTENSION BYTE b24:1;__EXTENSION BYTE b25:1;__EXTENSION BYTE b26:1;__EXTENSION BYTE b27:1;__EXTENSION BYTE b28:1;__EXTENSION BYTE b29:1;__EXTENSION BYTE b30:1;__EXTENSION BYTE b31:1;} bits;
} DWORD_VAL;/* MPLAB C Compiler for PIC18 does not support 64-bit integers */
#if !defined(__18CXX)
typedef union
{QWORD Val;DWORD d[2];WORD w[4];BYTE v[8];struct{DWORD LD;DWORD HD;} dword;struct{WORD LW;WORD HW;WORD UW;WORD MW;} word;struct{__EXTENSION BYTE b0:1;__EXTENSION BYTE b1:1;__EXTENSION BYTE b2:1;__EXTENSION BYTE b3:1;__EXTENSION BYTE b4:1;__EXTENSION BYTE b5:1;__EXTENSION BYTE b6:1;__EXTENSION BYTE b7:1;__EXTENSION BYTE b8:1;__EXTENSION BYTE b9:1;__EXTENSION BYTE b10:1;__EXTENSION BYTE b11:1;__EXTENSION BYTE b12:1;__EXTENSION BYTE b13:1;__EXTENSION BYTE b14:1;__EXTENSION BYTE b15:1;__EXTENSION BYTE b16:1;__EXTENSION BYTE b17:1;__EXTENSION BYTE b18:1;__EXTENSION BYTE b19:1;__EXTENSION BYTE b20:1;__EXTENSION BYTE b21:1;__EXTENSION BYTE b22:1;__EXTENSION BYTE b23:1;__EXTENSION BYTE b24:1;__EXTENSION BYTE b25:1;__EXTENSION BYTE b26:1;__EXTENSION BYTE b27:1;__EXTENSION BYTE b28:1;__EXTENSION BYTE b29:1;__EXTENSION BYTE b30:1;__EXTENSION BYTE b31:1;__EXTENSION BYTE b32:1;__EXTENSION BYTE b33:1;__EXTENSION BYTE b34:1;__EXTENSION BYTE b35:1;__EXTENSION BYTE b36:1;__EXTENSION BYTE b37:1;__EXTENSION BYTE b38:1;__EXTENSION BYTE b39:1;__EXTENSION BYTE b40:1;__EXTENSION BYTE b41:1;__EXTENSION BYTE b42:1;__EXTENSION BYTE b43:1;__EXTENSION BYTE b44:1;__EXTENSION BYTE b45:1;__EXTENSION BYTE b46:1;__EXTENSION BYTE b47:1;__EXTENSION BYTE b48:1;__EXTENSION BYTE b49:1;__EXTENSION BYTE b50:1;__EXTENSION BYTE b51:1;__EXTENSION BYTE b52:1;__EXTENSION BYTE b53:1;__EXTENSION BYTE b54:1;__EXTENSION BYTE b55:1;__EXTENSION BYTE b56:1;__EXTENSION BYTE b57:1;__EXTENSION BYTE b58:1;__EXTENSION BYTE b59:1;__EXTENSION BYTE b60:1;__EXTENSION BYTE b61:1;__EXTENSION BYTE b62:1;__EXTENSION BYTE b63:1;} bits;
} QWORD_VAL;
#endif /* __18CXX */#undef __EXTENSION#ifdef __cplusplus}
#endif
#endif /* __GENERIC_TYPE_DEFS_H_ */

问题:

..\EtherCAT\Src\9252_HW.c(316): warning:  #223-D: function "ConfigIntTimer5" declared implicitlyConfigIntTimer5(T5_INT_ON | T5_INT_PRIOR_3 );

没有定义的函数,直接删除。

问题:

..\EtherCAT\Inc\eoeappl.h(209): error:  #1032: Definition of nested anonymous union in packed "struct <unnamed>" must be __packed} u; /**< \brief Data*/

这个错误是由 __packed 关键字引发的,我们直接使用Ctrl+F全局搜索关键字packed,追踪到了ecat_def.h的742行和754行,将这两个宏后面的映射语句删掉,使其变成空的宏。

修改完这处错误不出意外的话再次编译就不会报错了,剩下的一些警告可以自己解决,当然,直接无视也没什么问题。

接下来就是将协议栈暴露给我们的几个函数在代码相应的位置调用,以及编写自己的业务逻辑。

 1.在 LAN9252_IRQ引脚对应的中断服务程序中调用 PDI_Isr();我这里对应的是EXTI0

#include "applInterface.h" //添加头文件void EXTI0_IRQHandler(void)
{/* USER CODE BEGIN EXTI0_IRQn 0 */PDI_Isr();/* USER CODE END EXTI0_IRQn 0 */HAL_GPIO_EXTI_IRQHandler(LAN9252_IRQ_Pin);/* USER CODE BEGIN EXTI0_IRQn 1 *//* USER CODE END EXTI0_IRQn 1 */
}

2.在 LAN9252_SUNC0和LAN9252_SUNC1引脚对应的中断服务程序中调用 Sync0_Isr() 和 Sync1_Isr()

/*** @brief This function handles EXTI line1 interrupt.*/
void EXTI1_IRQHandler(void)
{/* USER CODE BEGIN EXTI1_IRQn 0 */DISABLE_ESC_INT();Sync1_Isr();ENABLE_ESC_INT();/* USER CODE END EXTI1_IRQn 0 */HAL_GPIO_EXTI_IRQHandler(LAN9252_SYNC1_Pin);/* USER CODE BEGIN EXTI1_IRQn 1 *//* USER CODE END EXTI1_IRQn 1 */
}/*** @brief This function handles EXTI line3 interrupt.*/
void EXTI3_IRQHandler(void)
{/* USER CODE BEGIN EXTI3_IRQn 0 */DISABLE_ESC_INT();Sync0_Isr();ENABLE_ESC_INT();/* USER CODE END EXTI3_IRQn 0 */HAL_GPIO_EXTI_IRQHandler(LAN9252_SYNC0_Pin);/* USER CODE BEGIN EXTI3_IRQn 1 *//* USER CODE END EXTI3_IRQn 1 */
}

注意,设备上电后我们不可以直接调用HAL_NVIC_EnableIRQ函数将各种中断使能,因为此时协议栈相关数据都没初始化好,直接使能这些中断将导致严重的逻辑问题。

因此我们需要回到gpio.c中,将CuboMX自动生成的使能语句注释掉。

  位置在MX_GPIO_Init()函数的结尾。/* EXTI interrupt init*/HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 0);// HAL_NVIC_EnableIRQ(EXTI0_IRQn);HAL_NVIC_SetPriority(EXTI1_IRQn, 2, 0);// HAL_NVIC_EnableIRQ(EXTI1_IRQn);HAL_NVIC_SetPriority(EXTI3_IRQn, 2, 0);// HAL_NVIC_EnableIRQ(EXTI3_IRQn);

3. 在自己设置的1ms定时器的中断服务函数中调用ECAT_CheckTimer()

void TIM7_IRQHandler(void)
{/* USER CODE BEGIN TIM7_IRQn 0 */ECAT_CheckTimer();/* USER CODE END TIM7_IRQn 0 */HAL_TIM_IRQHandler(&htim7);/* USER CODE BEGIN TIM7_IRQn 1 *//* USER CODE END TIM7_IRQn 1 */
}

4. 在主函数中添加头文件 #include "applInterface.h" ,调用协议栈的初始化函数HW_Init()和MainInit(),并在while循环中调用MainLoop。

主函数中最好只放一个MainLoop函数,应用逻辑写在APPL_Application函数中,需要注意不要在APPL_Application函数中进行耗时操作,如果耗时操作无法避免,可以另加操作系统,在其他线程中处理,否则会导致通信异常。

 /* USER CODE BEGIN 2 */HW_Init();MainInit();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */MainLoop();}

5. 完成上述步骤剩下的就是在协议栈开放给我们的业务逻辑接口中编辑自己的业务逻辑。

如果你们一开始使用SSC生成协议栈时没自己命名的话,接口可以在PIC32 EtherCAT Slave.c文件中找到。

需要自己写的主要是下面三个函数:

//输入数据映射,将需要发送的数据映射到pData指向的空间
void APPL_InputMapping(UINT16* pData) //输出数据映射,将想要接收的数据从pData指向的空间取出
void APPL_OutputMapping(UINT16* pData) //应用逻辑
void APPL_Application(void)              

下面是我的一段参考代码,变量Value0x6000与Led0x7000是与自己当时在Excel中添加的字典是一一对应的,变量名可以在 PIC32 EtherCAT SlaveQbjects.h 文件中找到,以后如果需要修改对象字典只需要使用SSC重新生成协议栈文件将后,把工程原有的PIC32 EtherCAT SlaveQbjects.h 替换成新生成的,并重写这三个函数即可。

/
/**
\param      pData  pointer to input process data\brief      This function will copies the inputs from the local memory to the ESC memoryto the hardware
*
void APPL_InputMapping(UINT16* pData)
{pData[0] = Values0x6000.V1;pData[1] = Values0x6000.V2;
}
;
/
/**
\param      pData  pointer to output process data\brief    This function will copies the outputs from the ESC memory to the local memoryto the hardware
*
void APPL_OutputMapping(UINT16* pData)
{Led0x7000.D1 = *pData;
}/
/**
\brief    This function will called from the synchronisation ISR or from the mainloop if no synchronisation is supported
*
void APPL_Application(void)
{Values0x6000.V1 = 0x1234;Values0x6000.V2 = 0x5678;Led0x7000.D1 ? HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET) : HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);}

至此我们的一个基于STM32和LAN9252的简单从站就完成了,下面就是使用TwinCAT往EEPROM中烧写XML文件并测试了。

四、测试

我这里使用的是 TwinCAT3 ,依然是自己找资源下载即可。

1.将 C:\TwinCAT\3.1\Config\Io\EtherCAT 路径下的所有 .xml 文件删除,并将SSC生成的XML文件拷贝过来。

 2.打开TwinCAT3新建一个EtherCAT工程,FILE -> New -> Project

 3. 先用一根网线将你的电路板与电脑连接起来,然后添加网卡驱动 TWNCAT -> Show Realtime EtherCAT Compatible Devices...

4. 扫描设备,一路确定,等待EEPROM烧写完成

         

 下面这种状态就表示通信成功了

 观察是否输出了自己期望的数据以及能否正常控制LED

 

到此就恭喜各位完成了STM32+LAN9252从站的搭建。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/89332.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/89332.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/89332.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode 热题 100】239. 滑动窗口最大值——(解法二)滑动窗口+单调队列

Problem: 239. 滑动窗口最大值 题目&#xff1a;给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值 。 【LeetCode 热题 100】239. 滑…

MySQL 8.0 连接 5.x 服务器认证问题

总的来说&#xff0c;答案是&#xff1a;可以&#xff0c;但是需要特别注意认证方式的兼容性问题。 MySQL 8.0 引入了新的默认认证插件 caching_sha2_password&#xff0c;而 MySQL 5.x&#xff08;及更早版本&#xff09;使用的是 mysql_native_password。当你用一个 8.0 的客…

Spring原理揭秘(一)

什么是spring&#xff1f; spring框架是一个轻量级的开源的JavaEE框架。 所谓轻量级则是&#xff1a;占用空间小&#xff0c;代码侵入性低&#xff0c;代码耦合度低&#xff0c;降低代码复杂度&#xff0c;可以轻易适配多种框架。 随着spring的不断发展&#xff0c;它所占用…

Visual Studio Code自用搜索技巧整理

多文件跨行搜索 用途 在多个日志文件中搜索跨行日志 方法 1.用VS Code打开待搜索文件所在的目录&#xff1b; 2.按快捷键&#xff08;CtrlShiftF&#xff09;打开全局搜索&#xff1b; 3.点击搜索框右侧的开启正则表达式&#xff1b; 4.输入正则表达式&#xff0c;例如&…

Axure PR 9 验证码登录 案例

大家好&#xff0c;我是大明同学。 这期内容&#xff0c;我们来用Axure来制作一个短信验证登录页面的小案例。 验证码登录小案例 创建手机号输入框所需的元件 1.打开一个新的 RP 文件并在画布上打开 Page 1。 2.在元件库中拖出一个矩形元件&#xff0c;选中矩形元件&#xf…

监听器模式

1. 问题背景 假设我们有一个 银行账户管理系统&#xff0c;该系统需要监控用户账户余额的变动&#xff0c;并在发生变动时&#xff0c;自动执行一些相关的操作&#xff0c;比如发送 余额变动通知&#xff08;如短信、邮件等&#xff09;。为了实现这一功能&#xff0c;我们希望…

帕鲁杯应急响应赛题:知攻善防实验室

一、背景信息 在这个跳跃的数字舞台上&#xff0c;数据安全成了政企单位稳航的重要压舱石。某政企单位&#xff0c;作为一艘驶向未来 的巨轮&#xff0c;对数据的把控丝毫不敢松懈。眼下&#xff0c;我们即将启航一场无与伦比的探险——“信息安全探索之 旅”。 这趟旅程的目的…

【硬核数学】2.2 深度学习的“微积分引擎”:自动微分与反向传播《从零构建机器学习、深度学习到LLM的数学认知》

欢迎来到本系列的第七篇文章。在上一章&#xff0c;我们用张量武装了我们的线性代数知识&#xff0c;学会了如何描述和操作神经网络中的高维数据流。我们知道&#xff0c;一个神经网络的“前向传播”过程&#xff0c;就是输入张量经过一系列复杂的张量运算&#xff08;矩阵乘法…

DAY 45 Tensorboard使用介绍

浙大疏锦行https://blog.csdn.net/weixin_45655710知识点回顾&#xff1a; tensorboard的发展历史和原理tensorboard的常见操作tensorboard在cifar上的实战&#xff1a;MLP和CNN模型 作业&#xff1a;对resnet18在cifar10上采用微调策略下&#xff0c;用tensorboard监控训练过程…

2023年全国硕士研究生招生考试英语(一)试题总结

文章目录 题型与分值分布完形填空错误 1&#xff1a;考察连词 or 前后内容之间的逻辑关系错误2&#xff1a;错误3&#xff1a;错误4&#xff1a;这个错得最有价值&#xff0c;因为压根没读懂错误5&#xff1a;学到的短语&#xff1a; 仔细阅读排序/新题型翻译小作文大作文 题型…

react-数据Mock实现——json-server

什么是mock&#xff1f; 在前后端分离的开发模式下&#xff0c;前端可以在没有实际后端接口的支持下先进行接口数据的模拟&#xff0c;进行正常的业务功能开发 json-server实现数据Mock json-server是一个node的包&#xff0c;可以在不到30秒内获得零编码的完整Mock服务 实现…

使用POI导入解析excel文件

首先校验 /*** 校验导入文件* param file 上传的文件* return 校验结果&#xff0c;成功返回包含成功状态的AjaxResult&#xff0c;失败返回包含错误信息的AjaxResult*/private AjaxResult validateImportFile(MultipartFile file) {if (file.isEmpty()) {return AjaxResult.er…

从0开始学习计算机视觉--Day06--反向传播算法

尽管解析梯度可以让我们省去巨大的计算量&#xff0c;但如果函数比较复杂&#xff0c;对这个损失函数进行微分计算会变得很困难。我们通常会用反向传播技术来递归地调用链式法则来计算向量每一个方向上的梯度。具体来说&#xff0c;我们将整个计算过程的输入与输入具体化&#…

企业流程知识:《学习观察:通过价值流图创造价值、消除浪费》读书笔记

《学习观察&#xff1a;通过价值流图创造价值、消除浪费》读书笔记 作者&#xff1a;迈克鲁斯&#xff08;Mike Rother&#xff09;&#xff0c;约翰舒克&#xff08;John Shook&#xff09; 出版时间&#xff1a;1999年 历史地位&#xff1a;精益生产可视化工具的黄金标准&am…

Day02_C语言IO进程线程

01.思维导图 02.将当前的时间写入到time. txt的文件中&#xff0c;如果ctrlc退出之后&#xff0c;在再次执行支持断点续写 1.2022-04-26 19:10:20 2.2022-04-26 19:10:21 3.2022-04-26 19:10:22 //按下ctrlc停止&#xff0c;再次执行程序 4.2022-04-26 20:00:00 5.2022-04-26 2…

FFmpeg中TS与MP4格式的extradata差异详解

在视频处理中&#xff0c;extradata是存储解码器初始化参数的核心元数据&#xff0c;直接影响视频能否正确解码。本文深入解析TS和MP4格式中extradata的结构差异、存储逻辑及FFmpeg处理方案。 &#x1f4cc; 一、extradata的核心作用 extradata是解码必需的参数集合&#xff0…

【CV数据集介绍-40】Cityscapes 数据集:助力自动驾驶的语义分割神器

&#x1f9d1; 博主简介&#xff1a;曾任某智慧城市类企业算法总监&#xff0c;目前在美国市场的物流公司从事高级算法工程师一职&#xff0c;深耕人工智能领域&#xff0c;精通python数据挖掘、可视化、机器学习等&#xff0c;发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…

SAP月结问题9-FAGLL03H与损益表中研发费用金额不一致(FAGLL03H Bug)

SAP月结问题9-FAGLL03H与损益表中研发费用金额不一致(S4 1709) 财务反馈&#xff0c;月结后核对数据时发现FAGLL03H导出的研发费用与损益表中的研发费用不一致&#xff0c;如下图所示&#xff1a; 对比FAGLL03H与损益表对应的明细&#xff0c;发现FAGLL03H与损益表数据存在倍数…

HTML inputmode 属性详解

inputmode 是一个 HTML 属性&#xff0c;用于指定用户在编辑元素或其内容时应使用的虚拟键盘布局类型。它主要影响移动设备和平板电脑的输入体验。 语法 <input inputmode"value"> <!-- 或 --> <textarea inputmode"value"></texta…

软考中级【网络工程师】第6版教材 第1章 计算机网络概述

考点分析&#xff1a; 本章重要程度&#xff1a;一般&#xff0c;为后续章节做铺垫&#xff0c;有总体认识即可&#xff0c;选择题1-2分高频考点&#xff1a;OSI模型、TCP/IP模型、每个层次的功能、协议层次新教材变化&#xff1a;删除网络结构、删除X.25、更新互联网发展【基本…