本帖最后由 穿西装的强子 于 2023-8-2 10:03 编辑
1.下载和准备SOEM库,从官网给的GIT上下载:github.com/OpenEtherCATsociety/SOEM
我的版本比较旧,是1.3.1,git上最新的是1.4.0。
下载SOEM库的源代码,并根据所需的平台和编译器进行编译。
2.移植到工程内
将以上文件添加到工程内,添加好路径
编译的时候会报错,在Compiler V5的typedef __packed struct 在Compiler V6上是报错的
因此需要修改#pragma pack(push,1)
typedef struct
结束的时候再加#pragma pack(pop)
在ethercatmain.c文件中,ecx_statecheck函数需要ms定时器时间和us级延时,因此把之前工程的定时器中断计数值查询函数调用过来,再写一个us级的延时函数
uint16 ecx_statecheck(ecx_contextt *context, uint16 slave, uint16 reqstate, int timeout)
{
uint16 configadr, state, rval;
ec_alstatust slstat;
uint32_t timer2;
if ( slave > *(context->slavecount) )
{
return 0;
}
timer2=<span style="background-color: yellow;">DrvTimer_InqCount();</span>
configadr = context->slavelist[slave].configadr;
do
{
if (slave < 1)
{
rval = 0;
ecx_BRD(context->port, 0, ECT_REG_ALSTAT, sizeof(rval), &rval , EC_TIMEOUTRET);
rval = etohs(rval);
}
else
{
slstat.alstatus = 0;
slstat.alstatuscode = 0;
ecx_FPRD(context->port, configadr, ECT_REG_ALSTAT, sizeof(slstat), &slstat, EC_TIMEOUTRET);
rval = etohs(slstat.alstatus);
context->slavelist[slave].ALstatuscode = etohs(slstat.alstatuscode);
}
state = rval & 0x000f; /* read slave status */
if (state != reqstate)
{
<span style="background-color: sienna;"> DrvTimer_DelayUs(1000);</span>
}
}
while ((state != reqstate) && ((<span style="background-color: yellow;">DrvTimer_InqCount()</span>-timer2)<timeout));
context->slavelist[slave].state = rval;
return state;
}
在nicdrv.c文件中修改网口发送和接收函数
int ecx_outframe(ecx_portt *port, int idx, int stacknumber)
{
int lp, rval;
ec_stackT *stack;
if (!stacknumber)
{
stack = &(port->stack);
lp = (*stack->txbuflength)[idx];
MAC_Send((*stack->txbuf)[idx], lp);
}
else
{
stack = &(port->redport->stack);
lp = (*stack->txbuflength)[idx];
// dm9k_send_packet((*stack->txbuf)[idx], lp);
}
rval =1;
(*stack->rxbufstat)[idx] = EC_BUF_TX;
return rval;
}
int ecx_inframe(ecx_portt *port, int idx, int stacknumber)
{
uint16 l;
int rval;
int idxf;
ec_etherheadert *ehp;
ec_comt *ecp;
ec_stackT *stack;
ec_bufT *rxbuf;
// stack = &(port->stack);
if (!stacknumber)
{
stack = &(port->stack);
// if(ETH_CheckFrameReceived()) //检测是否收到数据包
{
gEtherCatPara.receiveLen=0;
memset(gEtherCatPara.receiveBuffer, 0, sizeof(gEtherCatPara.receiveBuffer));
// DrvETH_lwip_pkt_handle();
memcpy((uint8*)(*stack->rxbuf)[idx], (uint8*)gEtherCatPara.receiveBuffer, gEtherCatPara.receiveLen);
}
}
else
{
stack = &(port->redport->stack);
gEtherCatPara.receiveLen_DM9000 = 0; /* Çå³ý½ÓÊյij¤¶È */
memset(gEtherCatPara.receiveBuffer_DM9000, 0, sizeof(gEtherCatPara.receiveBuffer_DM9000));
// if(dm9k_receive_packet())
// {
// memcpy((uint8*)(*stack->rxbuf)[idx], (uint8*)gEtherCatPara.receiveBuffer_DM9000, gEtherCatPara.receiveLen_DM9000);
// }
}
rval = EC_NOFRAME;
rxbuf = &(*stack->rxbuf)[idx];
/* check if requested index is already in buffer ? */
if ((idx < EC_MAXBUF) && ((*stack->rxbufstat)[idx] == EC_BUF_RCVD))
{
l = (*rxbuf)[0] + ((uint16)((*rxbuf)[1] & 0x0f) << 8);
/* return WKC */
rval = ((*rxbuf)[l] + ((uint16)(*rxbuf)[l + 1] << 8));
/* mark as completed */
(*stack->rxbufstat)[idx] = EC_BUF_COMPLETE;
}
else
{
/* non blocking call to retrieve frame from socket */
if (ecx_recvpkt(port, stacknumber))
{
rval = EC_OTHERFRAME;
ehp =(ec_etherheadert*)(stack->tempbuf);
/* check if it is an EtherCAT frame */
if (ehp->etype == htons(ETH_P_ECAT))
{
ecp =(ec_comt*)(&(*stack->tempbuf)[ETH_HEADERSIZE]);
l = etohs(ecp->elength) & 0x0fff;
idxf = ecp->index;
/* found index equals reqested index ? */
if (idxf == idx)
{
/* yes, put it in the buffer array (strip ethernet header) */
memcpy(rxbuf, &(*stack->tempbuf)[ETH_HEADERSIZE], (*stack->txbuflength)[idx] - ETH_HEADERSIZE);
/* return WKC */
l=(*stack->txbuflength)[idx] - ETH_HEADERSIZE;
rval = ((*rxbuf)[l-2] + ((uint16)((*rxbuf)[l-1]) << 8));
/* mark as completed */
(*stack->rxbufstat)[idx] = EC_BUF_COMPLETE;
/* store MAC source word 1 for redundant routing info */
(*stack->rxsa)[idx] = etohs(ehp->sa1);
}
else
{
/* check if index exist? */
if (idxf < EC_MAXBUF)
{
// rxbuf = &(*stack->rxbuf)[idxf];
// /* put it in the buffer array (strip ethernet header) */
// memcpy(rxbuf, &(*stack->tempbuf)[ETH_HEADERSIZE], (*stack->txbuflength)[idxf] - ETH_HEADERSIZE);
// /* mark as received */
// (*stack->rxbufstat)[idxf] = EC_BUF_RCVD;
// (*stack->rxsa)[idxf] = etohs(ehp->sa1);
(*stack->rxbufstat)[idxf] = EC_BUF_EMPTY;
}
else
{
/* strange things happend */
}
}
}
}
}
return rval;
}
发送函数
uint8_t MAC_Send(uint8_t *data, int length)
{
ETH_BufferTypeDef Txbuffer;
uint8_t i;
ETH_TxPacketConfig TxPacketCfg;
TxPacketCfg.ChecksumCtrl = ETH_CHECKSUM_IPHDR_INSERT;
Txbuffer.buffer = data;
Txbuffer.len = length;
TxPacketCfg.Length = length;
TxPacketCfg.TxBuffer = Txbuffer;
HAL_ETH_Transmit_IT(ð_handle, &TxPacketCfg);
// memcpy((u8*)(DMATxDescToSet->Buffer1Addr), (u8*)data, length);
// /* Prepare transmit descriptors to give to DMA*/
// i=ETH_Prepare_Transmit_Descriptors(length);
return i;
}
根据使用ETH的THAL_ETH_Transmit_IT中断发送,将数据从网口中发出去,再将接收到的数据存储在gEtherCatPara.receiveBuffer_DM9000(之前是在DM9000的PHY上移植的),复制到内部缓存里memcpy((uint8*)(*stack->rxbuf)[idx], (uint8*)gEtherCatPara.receiveBuffer, gEtherCatPara.receiveLen);
至此,移植功能完成,下一部是对针对电机进行配置和控制。
|