【STM32+LAN9252+HAL庫】EtherCAT從站搭建 保姆級教程

目錄

一、生成協議棧及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、更新互聯網發展【基本…