基于FPGA和EC-01M的EtherCAT主站控制系统设计
2022-11-22王景存黎佳亨
冯 深,王景存,黎佳亨
(武汉科技大学信息科学与工程学院,湖北武汉 430081)
0 引言
由于传统以太网采用CSMA/CD机制[1],应用于工业自动化控制系统时会产生实时性等问题。因此,实时工业以太网技术是在传统以太网的通信模型基础之上加以修改来实现强实时性和稳定性的工业以太网,如EtherCAT、SERCOS等[2]。EtherCAT总线具有实时性好、速度快、同步性高、开放性好、拓扑灵活、成本低等优点,在测控领域、CNC加工控制以及工业机器人等领域有广泛的应用[3]。
现有的EtherCAT主站系统多为PLC或工控计算机来完成,不适合嵌入式系统中体积小、灵活性高的要求。因此在嵌入式系统中难以应用EtherCAT总线。本文的主要思想是将EtherCAT总线的主站控制器应用到嵌入式系统中。EC-01M是EtherCAT主站控制芯片,采用SPI通讯格式,依不同通讯周期频率要求,SPI的串行时钟信号最高至24 MHz,支持40个子站设备。系统采用基于嵌入式ARM MCU+FPGA的软硬件协同设计方案[4-6],即解决了EtherCAT主站控制器所要求协议的强实时性和高稳定性,又满足了嵌入式系统体积小、灵活性高的要求。
1 系统总体设计
本系统需要控制3台伺服电机,选用的伺服控制器为CDHD2型伺服控制器,该控制器支持EtherCAT总线接口,在系统中称为EtherCAT Slave设备[7]。主控MCU采用STM32F103,FPGA选用EP3C10E144C7芯片。系统框图如图1所示。
图1 系统总体结构图
1.1 SPI数据结构
EC-01M可以控制40个EtherCAT子站,每个子站的数据帧为12 Byte。另有2个特殊的数据帧,一个为控制EC-01M芯片的数据帧,另一个为专门对应单一子站进行非周期性的参数读写(SDO Read/Write)的数据帧。因此,每次给EC-01M芯片下达命令均会传递504 Byte的数据(本文称为一个数据包),会得到504 Byte的数据回应。EC-01M芯片规定不论40个子站是否都连接了伺服控制器,都要传输504 Byte,没有连接设备的子站12 Byte数据可均为0。504 Byte的数据包格式如图2所示。由于篇幅有限,有关EC-01M芯片的硬件电路和命令集等可在其数据手册中查阅,本文不再赘述。
图2 EC-01M命令与响应数据包格式
1.2 SPI传输时序
SPI传输以Byte为单位,每次由低地址开始传,依序传至最高地址,即SPI传输从Byte0开始,再依序传Byte1、Byte2等,直至最后一个Byte为止。而SPI传输单一Byte时,采取MSB模式,即高位先传输。
EC-01M的SPI模式为Slave模式,FPGA为Master模式[8],空闲时时钟信号SPI_SCLK为低电位,数据在下降沿发送,并于上升沿接收。单字节传输时序如图3所示,SPI_SS为选通信号,当低电平时有效,SPI_CLK为时钟信号,SPI_MOSI为FPGA到EC-01M的输出数据,SPI_MISO为FPGA从EC-01M读入的数据。
图3 SPI单字节传输时序
在FPGA与EC-01M的SPI通讯过程中,要检测EC-01M的忙(SPI_Busy)信号,只有当SPI_Busy信号为低时才能进行数据包传输。当进入SPI通讯后,SPI_Busy信号立刻升为高电位,直至数据包通讯结束且EC-01M处理完命令后,SPI_Busy信号才会恢复为低电位。一个数据包(504 Byte)的时序图如图4所示。
图4 SPI 数据包(504 Byte)传输时序
SPI控制逻辑的主频率可高达24 MHz,且FPGA控制端侦测到SPI_Busy为低电位时,必须立即进行下一笔数据的交换。
2 FPGA逻辑设计
在FPGA的逻辑设计中,主要包含两大逻辑模块,一是和MCU通讯的FSMC接口模块[9-10],二是控制EC-01M的SPI控制逻辑模块[11-12]。FSMC接口模块包括:寄存器定义模块、寄存器读写模块和中断控制模块等,由于FSMC接口模块其他文献介绍较多,在此不再赘述。
2.1 SPI模块总体设计
SPI控制逻辑模块对下提供SPI接口,与主站芯片EC-01M相连,实现SPI通信协议;对上与FSMC相连,完成与MCU的数据交换。具有以下功能:
(1)支持8位、504 Byte长数据传输;
(2)支持带有SPI_SS的传输模式;
(3)支持带有SPI_BUSY的传输控制模式;
(4)支持数据包发送接收完成后产生中断请求信号。
图5为FPGA中SPI控制逻辑的设计框图。控制逻辑中SPI_MOSI、SPI_MISO、SPI_CS、SPI_CLK为标准SPI协议引脚,SPI_BUSY连接主站芯片。
图5 FPGA SPI设计框图
SPI控制逻辑分为3部分实现,即数据发送寄存器、数据接收寄存器和SPI控制逻辑(包括中断与时钟发生器及状态机控制器逻辑)。在本系统中只有3个伺服电机,因此只有60 Byte的输出寄存器和60 Byte的输入寄存器(主站12 Byte,伺服3×12=36 Byte,SDO控制器12 Byte)。
SPI控制逻辑在输出数据SPI_MOSI的同时会读取SPI_MISO引脚接收的数据。并将其移位输入到spi_rx_db接收数据寄存器中,由状态机控制器再把接收寄存器的值输出到60个接收数据寄存器中的一个寄存器中。
SPI控制逻辑工作在有限状态机,整个504 Byte的发送与接收由状态机来控制,其状态可分为空闲状态(IDLE)、预发送状态(SEND_PRE)、发送状态(SEND)、发送结束状态(SEND_OV)、忙线检查状态(CHECK_BUSY)、延时状态(DELAY)和延时结束状态(DELAY_OV),图6为状态机控制器设计框图。
图6 状态机转移图
状态机的控制信号主要有Start_Rise、cnt504、spi_busy、delay_cnt等。其中:
Start_Rise为MCU发出的SPI启动信号,当MCU通过FSMC将上一次的数据读出且将本次要发出的数据已写入寄存器后,发出此信号。SPI控制逻辑中通过高频时钟检查此信号的上升沿,将此信号置1。
cnt504为内部计数器,每发送接收1 Byte后,此计数器加1。因此当它等于504时,即完成了1包数据的传输。此计数器也指出了当前正在发送和接收的是哪个数据。(系统中只有3个伺服电机,在504 Byte中大部分字节的数据为0)。
spi_busy为主站芯片输出的忙信号,当主站可以进行SPI传输时,此信号为0。否则为1。
delay_cnt为延时计数器,它决定了两包数据之间的延时时间。在进入DELAY状态的同时,触发中断控制模块,向MCU产生INT中断请求。
最后,状态机回到空闲状态,等待MCU启动下一轮的数据传输。
2.2 其他控制模块
除了上述状态机以外,还有几个重要的控制模块,如SPI字节传输控制、SPI_CLK产生模块、SPI数据的输入和输出模块、输入寄存器的保存、输出寄存器的更新、中断信号产生等模块,下面详细介绍各模块的设计思路。
2.2.1 SPI字节传输控制
字节传输控制模块由一个计数器cnt20来实现,此计数器的计数范围为0~19,在SEND状态下由主时钟控制加1操作。主要程序如下:
always @(posedge clk or negedge rst_n)
if(!rst_n)
Cnt20 <= 8′d0;
else if(cur_st == IDLE)
Cnt20 <= 8′d0;
else if(cur_st == SEND)
begin
if(cnt20 < 8′d19)
Cnt20 <= cnt20+1'b1;
else
Cnt20 <= 8′d0;
end
else
cnt8 <=8′d0;
cur_st为状态机的当前状态。可以看出此计数器为0~19的一个循环计数器。
2.2.2 SPI_CLK产生模块
根据Cnt20的值结合状态机的状态可以完成很多功能,包括SPI_CLK信号的产生。主要程序如下:
always @(posedge clk or negedge rst_n)
if(!rst_n)
spi_clk <= 1′b0;
else if(cur_st == IDLE||cur_st == SEND_OV)
spi_clk <= 1′b0;
else if(cnt20 > 8′d2 && cnt20 < 8′d19)
spi_clk <=~spi_clk;
可以看出,在cnt20为3~18时,每个主时钟都使得spi_clk翻转1次,因此可以得到传输1 Byte所需要的8个spi_clk脉冲信号。
2.2.3 SPI数据的输入和输出
同样,在SEND状态下,可以根据cnt20的值将8位输出寄存器spi_tx_db的值输出到SPI_MOSI信号线上。主要程序如下:
if(cur_st == SEND)
begin
case(cnt8[4:1])
4′d1:spi_mosi <= spi_tx_db[7];
4′d2:spi_mosi <= spi_tx_db[6];
4′d3:spi_mosi <= spi_tx_db[5];
4′d4:spi_mosi <= spi_tx_db[4];
4′d5:spi_mosi <= spi_tx_db[3];
4′d6:spi_mosi <= spi_tx_db[2];
4′d7:spi_mosi <= spi_tx_db[1];
4′d8:spi_mosi <= spi_tx_db[0];
default:spi_mosir <= 1′b1;
endcase
end
同理,也可以将SPI_MISO线上的值读入到8位的spi_rx_db寄存器中(篇幅有限,以后只给出程序的主要部分)。
case(cnt8)
8′d3:spi_rx_db[7]<= spi_miso;
8′d5:spi_rx_db[6]<= spi_miso;
8′d7:spi_rx_db[5]<= spi_miso;
8′d9:spi_rx_db[4]<= spi_miso;
8′d11:spi_rx_db[3]<= spi_miso;
8′d13:spi_rx_db[2]<= spi_miso;
8′d15:spi_rx_db[1]<= spi_miso;
8′d17:spi_rx_db[0]<= spi_miso;
default:;
endcase;
2.2.4 输入输出寄存器更新
上面所述的只是单字节的SPI输入和输出,由于1包数据由504 Byte组成,因此,每当上述1 Byte完成后,都要把接收的数据(在输入寄存器spi_rx_db中)保存并更新输出寄存器spi_tx_db,以便下一次输入和输出,并且保存和更新的数据位置应该是在504 Byte中的相应位置,通过cnt504寄存器可以完成以上功能。主要程序如下:
if(cnt8 == 8′d2)
begin
case(cnt504)
10′d1:RX_SV00_DAT00<=spi_rx_db;
10′d2:RX_SV00_DAT01<= spi_rx_db;
……
10′d504:RX_SV00_DAT59<=spi_rx_db;
default:;
endcase
end
可以看出,每当cnt8 == 8′d2时,1 Byte的输入已经完成,因此,可以根据cnt504计数器的值将来更新和保存上述的spi_rx_db和spi_tx_db寄存器。
case(cnt504)
10′d0:spi_tx_db<= TX_SV00_DAT00;
10′d1:spi_tx_db<= TX_SV00_DAT01;
……
10′d503:spi_tx_db<=TX_SV00_DAT59;
default:spi_tx_db <= 8′d0;
endcase
每当1 Byte(spi_tx_db中)输出完成后,都要更新spi_tx_db寄存器,以便下一次输出。
2.2.5 中断信号的产生
SPI控制模块完成1包数据(504 Byte)的输入和输出后向MCU发出的中断信号。当MCU接收到中断信号后可以通过FMSC总线将504 Byte读出并写入1组新的数据。
中断信号INT在DELAY状态下发出,因为在此状态下所有输入输出都已完成。由于INT是脉冲信号,因此用一个中断计数器来规范INT信号的脉宽。主要程序如下:
中断计数器的实现:
if(cur_st == DELAY_OV)
begin
if(int_width int_width <= int_width +1′b1; end; else int_width <= 10′d0; 中断信号的产生: always @(posedge clk or negedge rst_n) if(!rst_n) spi_int <= 1′d0; else if(int_width == 10′d1) spi_int <= 1′d1; else if(int_width >= INT_WIDTH) spi_int <= 1′d0;else; 改变参数INT_WIDTH的值,可以改变INT信号脉冲的宽度。 本系统的测试是在实时运行环境下用逻辑分析仪进行采样获得。 图7为多个数据包的总体预览图。从图7可以看出,SPI数据包间隔15 ms定时发送,这是在伺服电机静止的条件下,不用发同步周期命令(CSP),只用GET STATUS命令获取子站状态,每15 ms 1个数据包即可满足要求。在伺服电机运动期间,本系统主站的同步周期时间设为1 ms,因此,每个数据包的间隔也为1 ms。 图7 SPI数据总体采样图 图8为1个数据包(504 Byte)的采集时序图。从图8可以看出,每个数据包是在SPI_BUSY为低电平的情况下开始传送的,FPGA首先发出SPI_SS(置为低电平),此时,SPI_BUSY变高电平,在SPI_CLK的驱动下开始数据发送和接收,504 Byte传输完成后,SPI_SS变高电平,此时等待SPI_BUSY变为低电平,1包数据传输结束。产生SPI_INT中断,MCU接收此中断后通过FSMC总线和FPGA中的寄存器交换数据,准备下一次传输。 图8 1个数据包的采集时序图 图9为1 Byte SPI数据传输采集图。SPI_CLK的周期为100 ns,频率为10 MHz。从图9可以看到MOSI的输出数据和FPGA要发送的数据是完全一致的。 图9 SPI数据采集图 本系统实现了基于FPGA和EC-01M芯片的Ethercat主站控制系统设计。在FPGA上设计了SPI EtherCAT主站控制逻辑,使用STM32 MCU通过FSMC总线接口访问FPGA内的SPI控制器,实现了MCU与EtherCAT主站通信的需求。经过仿真测试与实际硬件测试,证明了该系统工作正常、可靠。为EtherCAT主站控制系统在嵌入式系统的应用提供了一种切实可行的设计方法。3 系统仿真与测试
4 结束语