请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
器件型号:TMS320F2812 工具/软件:TI-RTOS
我当前的设置是- PC (TwinCAT)->EtherCAT --> ET1100背负式--> SPI --> TI DSP
当我发送/接收的 FIFO 缓冲区中数据字节不足一个时、一切都能完美工作。 当我想在一个环路中调用发送/接收函数来发送/接收多个 FIFO 数据缓冲区时、它不会按预期工作。 请帮助我确定问题、因为我至少阅读了20次代码、但看不到错误。
没有中断使用。
/*
SOEs Simple Open EtherCAT Slave
*
文件:esc_hw.c
*版本:0.9.2
*日期:22-02-2010
*版权所有(C) 2007-2010 Arthur Ketels
*
SOEs 是免费软件; 您可以根据
* Free
* Software Foundation 发布的 GNU 通用公共许可证版本2的条款对其进行重新分发和/或修改。
*
*发布 SOE 的目的是希望其有用、但不
提供任何*保修;甚至没有对适销性或
*特定用途适用性的暗示保修。 有关
更多详细信息、请参阅 GNU 通用公共许可证*。
*
*作为特殊例外、如果其他文件实例化模板或使用此
文件中的宏*或内联函数、 或者、您编译此文件并将其链接
*与其他作品链接以生成基于此文件的作品、此文件
本身不会*导致生成的作品被 GNU 通用公共
*许可证覆盖。 但是、仍必须根据
GNU 通用公共许可证的第(3)节*提供此文件的源代码。
*
*此例外不会使基于
*此文件的作品可能包含在 GNU 通用公共许可证中的任何其他原因失效。
*
* EtherCAT Technology、商品名和徽标"EtherCAT"是
Beckhoff Automation GmbH 的知识产权*并受其保护。
*/
/*器件头文件*/
#include /*包括 uint16_t 定义 */
#include /*包括 true/false 定义 */
#include
#include "utypes.h"
#include "ESC.h"
#include "ESC_COC.h"
#include "cpu.h" //本地包含文件
#define ESC_EtherCAT_Read0x02
#define ESC_EtherCAT_READ_WAIT0x03
#define ESC_EtherCAT_WRITE0x04
#define ESC_EtherCAT_3BYTEADDR0x06
#define ESC_EtherCAT_WAIT0xFF
#define ESC_EtherCAT_CONTINUE0x00
#define ESC_16.EVMT_RDMINAT_RDMINATEDIT(#define EST_CL_RATE 0x6670MHz
)(#define ESCK_EFF_EVM_EVM_EVM_EEDIT (#define
) 0x60MHz)(#define EVM_E long double) a * 1000.0L)/(long double) cpu_rate)- 9.0L)/5.0L)
/*-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->-->
;F U N C T I O N D E F I N I T I O N S
;--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
void InitGpio (void)
{
EALLOW;
//IER = 0x0000;
//IFR = 0x0000;
//为 SPI 接口
GpioMuxRegs.GPFMUX.bit.SPISIMOA_GPIOF0 = 1启用四个 I/O 引脚; //从器件输入、主器件输出
GpioMuxRegs.GPFMUX.bit.SPISOMia_GPIOF1 = 1; //从器件输出、主器件输入
GpioMuxRegs.GPFMUX.bit.SPICLKA_GPIOF2 = 1; //串行时钟
GpioMuxRegs.GPFMUX.bit.SPISTEA_GPIOF3=1; //从器件发送使能(SYNC)
EDIS;
}
空 InitSPI (void)
{
EALLOW;
//初始化 SPI FIFO 寄存器
SpiaRegs.SPICCR.bit.SPISWRESET=0;//复位 SPI
SpiaRegs.SPICCR.bit.SPICHAR = 0x7;//字符长度= 8 SpiReg.SPICTRESET= 1
;SPICTRS.SPICT.SPICTRS.SPICT.SPICTRS.SPICT.1/ SpiRegs.SPICTRL.SPICTRL.SPICTRIST.SPICT.SPICTRL.BIT.SPICK= SPICT.1/ SpiRIST.SPICTRL.SPICTRL.SPICTRIST.SPICKENA = SPICK= SPICTRIST.SPICTRL.BIT.
//主控模式
SpiaRegs.SPICTL.bit.CLK_PHASE = 0;// Clk wrt SPISTEA 的1/2周期延迟(0 -无延迟、1 -延迟)
SpiaRegs.SPICTL.bit.OPCP SpiRUNINTENA=1;//中断启用
// ClkCfgRegs (0 -无延迟、1 - SPICK=0x100M
= 0x100M;SYSCL = 0x100M = 1;SYSCL = 1;SYSCL = 0x100M = 0xFCLK = 1;SYSCL = 0XCLK = 0xFCLK = 0xFCLK = 0xFCLK = 0xFCLK = 0xFCLK = 0xFCLK = 0xFCLK = 0xFCLK = 0xFCLK = 0xFCLK = 0xFCL
//波特率= LSPPCLK /(SPIBRR+1)[LSPCLK=SYSCLK/4,默认值=50m]
//---------------
SpiaRegs.SPIFFTX.All=0xC022;//启用 FIFO、将其复位、设置 TX FIFO 内部电平= 2、TXINT 禁用
SpiaRegs.SPIFFTX.bit.TXFFIENA=0;//禁用 TXFF INT
SpiaRegs.SPIFFRX.All=0x006A;//启用 FIFO,将其复位,设置 RXFFIL=10 (十进制)
SpiaRegs.SPIFFRX.bit.RXFFIL = 0x02;
SpiaRegs.SPIFFRX.bit.RXFFIENA=0;//禁用 RXFF INT
//---
SpiaRegs.SPIFFCT.ALL=0x00;// FFTXDLY = 0 (延迟 btw Tx 传输)
停机;********* SPIPRI.All=0x0020;//在 EMUStop SpiaRegs.SPICCR.bit.SPISWRESET=1;// SpiSPI Reg=SPIFS.TXIFS=SPIFT.FET.FIFO 位
*函数: void esc_read (uint16_t address、uint16_t * buf、
* uint16_t len、uint16_t * tALevent)*
*前提条件:SPI 初始
化* EthetCAT 已初始
化*
*输入: uint16_t address = EtherCAT 寄存器地址
* uint16_t * buf =向
*写入数据的指针 uint16_t len =要读取的数据大小
*
*输出: uint16_t * tALevent =返回的状态
*
副作用:无
*
*概述: 这是 EthetCAT 的主要读取函数
/
void esc_read (uint16_t offset_addr、void * buf、uint16_t len、void * tALevent)
{
uint16_t i、cmd、NumWords = 0、j;
static uint16_t readval =0;
uint16_t * ptr =(uint16_t *) 0;
uint16 = uint16、uint16、uintr = uint16、uint16、uintr、uint16、uintr、uint16、uintr、uintr、uint16、uintr、uint16、uintr、uint16、uintr、uintr、uint16、uintr、uintr、uint16
if (len > 0 && len <= 26)//It is only 有可能一次从 TI SPI 的 FIFO 读取26个字节的有效载荷(+4个字节的地址)
{
//针对 SPI xmission 将地址 cmd 字节构造为16位字、
// SPI xmits MSBit 1st、 因此、必须交换这个16b 字中的字节进行传输
//读取命令序列的字节顺序:
//字节0:A[12:5]
//字节1:A[4:0]、110b(110b 是3字节命令扩展名)
//字节2:A[15:13]、CMD[2:0]、00b(011b 是读取 W/
字节3): FFH(等待状态)
/cmd = offset_addr & 0x1f
cmd =(offset_addr & 0x1FE0)<<3;// offset_addr[12:5]是第一个地址相位字节、移位到上部字节
cmd |=((offset_addr & 0x1F)<< 3)| WORESC_READD_3TED[0
+(ESC_Wait +)| END_BYED+= 0x000+(ESD+)| EtherreadNum_read_readD+(ESC+[read_read_read_ready+)| END]+[ready+(ESC+[read_read_ready+)| END]+[ready+(ESC+[read_ready
对于(i=2、j=0;j <"="" estop0");="" while(1);="" cpu_delay_us(5);="" j="numwords;" while(spiaregs.spiffrx.bit.rxffst="" j);="" readval="(SpiaRegs.SPIRXBUF)" 0xff;="" read="" to="" talevent="" *(ptr)="(readval" 0xff);="" delay="" before="" reading="" next="" 0xff)="" ignore="" ptr="(uint16_t" *)buf;="" ptr[i]="(readval" cpu_delay_us(2);="" 0xff)<0)//输入实际以字节
{
if (current_Bytes >= 26)
{
esc_read (offset_addr +(2*i)、(void *)&pData[i]、26、(void *)&ESCvar.ALevent);
current_Bytes = 26;
i+= 13;//数据以16位为单位
}
否则
{
esc_read (offset_addr +(2*i)、(void *)&pData[i]、current_Bytes、(void *)&ESCvar.ALevent);
current_Bytes = 0;
}
}
/*********
*函数: void esc_write (uint16_t address、uint16_t * buf、
* uint16_t len、uint16_t * tALevent)
*
前提条件:SPI initialized
* EthetCAT 已初始
化*
*输入: uint16_t address = EtherCAT 寄存器地址
* uint16_t * buf =指针从
*读取数据 uint16_t len =要写入的数据大小
*
*输出: uint16_t * tALevent =返回的状态
*
副作用:无
*
*概述: 这是 EthetCAT 的主要写入函数
/
void esc_write (uint16_t offset_addr、void *wrdata、uint16_t len、void *tALevent)
{
uint16_t i、j、cmd、readval、reNumWords = 0;
uint16_t wptr、highbyte、lowbyte;
uint16_t * ptr =(uint16_t *) 0;
uint16_t writephase[16];
if (len >0 && len <= 26)//只能一次从 TI SPI 的 FIFO 传输26字节有效负载(地址的+4字节)
{
//将地址 cmd 字节构造为16位字、用于 SPI 任务、ximp
// SPI xmitsbit 第一个、所以必须交换这个16b 字中的字节进行传输
//读取命令序列的字节顺序:
//字节0:A[12:5]
//字节1:A[4:0]、110b(110b 是3字节 cmd 扩展名)
// cmd 2:A[15:13]、CMD[2:0]、字节3:byte 扩展名)//
字节3:bytes 3 A[15:13]、CMD[2:0]、00b(100b 通过 WS 读取)
/cmd = offset_addr & 0x1f
cmd =(offset_ad1F & 0x1FE0)<<3;// offset_addr[12:5]是第一个地址相位字节、移位到上部
字节|=(((offset_adcmd & 0x3edr+);EEC=[0x0000_addr[12:5])+);EEZ+
cmd =(((offset_addr & 0xE000)>> 8)|(ESC_EtherCAT_3BYTEADDR << 2))<< 8;
cmd |=(((offset_addr & 0xE000)|(ESC_EtherCAT_WRITE <<<10)>> 8);
writeptr[1]=
16;cmd = 16;(对于 ptr = 0
;uintj = 0;u+(对于 ptr = 0) i++、wptr++)
{//
交换字节以使低字节成为优先,因为 ET110 I/f 使用字节寻址
低字节= ptr[wptr]<
8;j++;highbyte = ptr[wptr >>>8;j++;writease[i]=高字节|低字节;words++;
/*0;
针对中断禁用
<numwords;i++) { while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG == 1); SpiaRegs.SPITXBUF = writephase[i] & (0xFF00);
while (SpiaRegs.SPISTS.bit.BUFFULL_FLAG = 1);
SpiaRegs.SPITXBUF =((writease[i]&(0xFF))<< 8);
}
cpu_delay_US (10);
j = advNumReWords;
ptr =(uint16_t *) tALR =(0xeff
& 0xeUS.rebyte);(spiaRegx & 0xef)(r.sprebyte);(r.spref.spref.spree+)+(r.sprevolt)= 0xe0Xr)+(r.spref)(r.sprevolt.spree.r.spree.r.spiRf)(r.spaRef)(r.spree.r.spr.spr.spr.spr.spr.spr.ef)=(+(r.spr.e
CPU_DELAY_US (2);//读取下一个字节前的延迟
while (SpiaRegs.SPIFFTX.bit.TXFFST!= 0);
SpiaRegs.SPIFFTX.bit.TXFIFO=0;//重置 Tx FIFO
SpiaRegs.SPIFFTX.bit.TXIFFIFO
= 1;// Reset_uintt =
16字节;t_uintuESPRECT_EMPT_16;//在读取前的 t_u.int_trabit_translation_rep.t = 16字节/spu.int_intu.intu.int_intt、void = 1;// CURRENT_Bytes;
CURRENT_Bytes = numbytes;
while (CURRENT_Bytes >0)//输入实际以字节为单位
{
if (CURRENT_Bytes >= 26)
{
ESC_WRITE (OFFSET_addr +(2*I)、(void *)&pData[i]、26、(void *)&ESCHV.ALevent);
CURRENT_Bytes = 26;
i+= 13;//数据为16位
}
否则
{
if (current_Bytes & 0x1)//检查剩余的字节是否为奇数
{
//current_Bytes = numbytes + 0x1;//偶数对齐
ESC_WRITE (offset_addr+(2*I)、(void *)&pData[i]、current_Bytes-1、(void *)、(ESCvar.event);void *)
//现在发送具有额外对齐字节的最后一个字节
//请注意,我们读取相邻字节并将其写回
ESC_Read (offset_addr+(numbytes-1)、(void *)&temp_value、2、(void *)&temp_ALevent);
temp_value &= 0xFF00;
temp_value |=(pData[numbytes-1])和0xFF;
ESC_WRITE (offset_addr+(numbytes-1)、(void *)&temp_value、2、(void *)&temp_ALevent);
}
否则
{
ESC_WRITE (offset_addr +(2*i)、(void *)&pData[i]、current_bytes、(void *)&ESCvar.ALevent);
}
current_bytes = 0;
}
}
}
