主题中讨论的其他部件:controlSUITE, TMDSECATCNCD379D
工具/软件:Code Composer Studio
大家好,
我正在运行由controlSUITE提供的EtherCAT堆栈,并在检查它是否正常工作后,我在RAM和闪存中应用了一些片段,以初始化并使用2个ePWM信号,2个eQEP信号和2个ADC。 但是,当我尝试从闪存执行代码时遇到了某种问题(在RAM中,它工作正常)。 它在EtherCAT堆栈的这一特定部分跳进了非法的ISR例程,而在启用上述外围设备之前,它没有这样做
默认controlSUITE程序和HW_Init()函数在RAM和闪存配置中将cmd文件排除在构建之外,以下功能不会导致任何问题:
//#######################################################################
//
//文件:etherCAT_slaver_C28x_hal.c
//
//标题:用于EtherCAT从属控制器(ESC)的C28x HAL级别功能
//
//! \addtogroup C2k_EtherCAT_adapater_examples_list
//! <H1>PDI接口测试示例</H1>
//!
//! 此文件中的功能为EtherCAT从属设备提供HAL层接口
//! 可在C2k EtherCAT适配器板上构建的应用
//!
//! HAL可以是EMIF或SPI,具体取决于所选的PDI接口
//! 或为C2k ET1100 EtherCAT适配器板配置
//!
//------------------------------------------------
//! 用于EMIF PDI的C28x寻址与TwinCat3软件地址
//! 下面使用的C28x地址是ET1100 PDI的一个单词(16b)地址
//! 接口,而Beckhoff EtherCAT文档和TwinCat3软件使用
//! 字节地址。 ET1100上的用户RAM从0x1000偏移字节开始
//! 地址。 将其除以2,以从EMIF2获得正确的16b字偏移
//! 起始地址
//!
//! EMIF PDI一次从ET1100地址空间(即)读取两个字节
//! C28x CPU可读取的最小数据大小
//------------------------------------------------
//------------------------------------------------
//! C28x寻址与SPI PDI的TwinCat3软件地址
//! 对于SPI PDI,ET1100存储空间的寻址是直接的
//! SPI PDI使用8位字符长度进行SPI读/写,但使用HAL API
//! 调整为一次读取16位,以与EMIF PDI一致。
//! 用户可以将SPI PDI修改为从ET1100一次读取/写入一个字节
//! 地址空间。 但由于C28x数据总线的宽度为16位,本示例显示了这一点
//! 16位SPI PDI也可读/写。
//!
//! 不支持在最后一个事务上读取SPI miso针脚以获取错误状态
//! 在本HAL中
//! 此HAL支持SPI模式3
//! 此HAL将忽略miso引脚上的I0和I1字节读取
//------------------------------------------------
//! \b外部连接\n
//! 用户可以将运行TWINCAT3的PC连接到EtherCAT从属设备并查看
//! ET1100的内存窗口,用于寄存器和ET1100 RAM
//!
//! \b监视变量\n
//! -使用某些ET1100寄存器填充escRegs数据结构,可以是
//! 在内存窗口中查看是否启用了HAL Test (HAL测试)。
//!
//!
//#######################################################################
//$TI发行版:C2000 EtherCAT v解决方案支持1.00 $
//$发布日期:07/2017 $
//$Copyright:
//版权所有(C) 2017 Texas Instruments Incorporated - http://www.ti.com/
//
//以源代码和二进制形式重新分发和使用,无论是否使用
//修改,但前提是满足以下条件
//满足:
//
//重新分发源代码必须保留上述版权
//注意,此条件列表和以下免责声明。
//
//以二进制形式重新分发必须复制上述版权
//注意,此条件列表和中的以下免责声明
//随提供的文档和/或其他材料
//分发。
//
//既不是德州仪器(TI)公司的名称,也不是的名称
//其贡献者可用于支持或促销衍生产品
//未经特定的事先书面许可。
//
//本软件由版权所有者和贡献者提供
//“按原样”和任何明示或暗示的担保,包括但不包括
//仅限于适销性和适用性的暗示担保
//不承担特定目的。 在任何情况下,版权都不应享有
//所有者或贡献者对任何直接,间接,附带,
//特殊,典型或后果性损害(包括但不包括
//仅限于采购替代货物或服务;无法使用,
//数据或利润;或业务中断)
//责任理论,无论是合同,严格责任还是侵权行为
//(包括疏忽或其他)因使用而产生的任何问题
//此软件的任何版本,即使已被告知可能会造成此类损坏。
//$
//#######################################################################
//
//包含的文件
//
#include "F28x_Project.h"//设备头文件和示例包括文件
#include "F2837xD_SPI.h"
包含"DCL.h"
#include "AdcSetup.h"
#include "Posspeed.h"
#include "etherCAT_slaver_C28x_hal.h"
//
//定义
//
//#define EtherCAT_stack 1 //仅在使用EtherCAT从属堆栈时使用
//
//全局变量
//
Int AdcaResult0,AdcbResult0,AdcaResult1,AdcbResult1,dc;
浮点类比1 = 0.0f;
DCL_PID pid1 = PID_DEFAULTS;
浮子rk1;
浮子yk1;
浮子lk1;
浮子uk1;
浮子荷兰1;
DCL_PID pid2 = PID_DEFAULTS;
浮子RK2;
浮子yk2;
浮子lk2;
浮子uk2;
浮子荷兰2;
//eQEP
POSSPEED QEP_POSPEED=POSSPEED_DEFAULTS;
uINT16 int1cnt = 0;
uINT16 int2cnt = 0;
float desired pos_high = 360.0 ;
FLOAT desired _pos_low = 0.0 ;
float desired _pos = 360.0 ;
long int raW_pos1,raW_pos2,raW_pos3;
长int angle_count1=0;
unsigned long int pos_init = 2147483647;//0x7fffffffffff
float gwnia1,gwnia2,gwnia3;
float ngwnia1, ngwnia2, ngwnia3;
内部目录=0;
//指向ESC内存的指针,在ESC_INITHW()中初始化
//仅用于ASYNC16 (EMIF1或EMIF2) PDI
//uint16_t *PESC;
#ifdef PDI_HAL_TEST
//用于记录ESC寄存器的调试阵列,仅用于PDI HAL测试
esc_et1100_regs_t escRegs[esc_debug_regs_length];
#endif
#ifdef interface_SPI
// SPI变量
volatile uint16_t SPI_RxData[16];//接收数据缓冲区
易失性uint16_t SPI_XmitInProgress;
#endif
//
//HAL级别函数
//
#ifndef __cplusplus
#ifdef interface_SPI
#pragma code_section (esc_readSPI,".ti.ramfunc");
#pragma code_section (esc_writeSPI,".ti.ramfunc");
#endif
#pragma code_section (esc_timerIncPerMilliSec,".ti.ramfunc");
#pragma code_section (esc_getTimer,".ti.ramfunc");
#endif
/*************************************************************************** /
//为指定的引脚设置GPyDAT寄存器位。
UINT32_t ESC_GETTimer (无效)
{
/C28x计时器从0xFFFFFFFF递减,而堆栈从开始理解
//增量类型。
返回~(UINT32_t)(CpuTimer0Regs.TIM.All);
}
/*************************************************************************** /
void ESC_clearTimer (void)
{
CpuTimer0Regs.TIM.All = 0;
}
/*************************************************************************** /
UINT32_t ESC_TIMERIncPerMilliSec (无效)
{
返回(UINT32_t) 20万UL;// 200MHz
}
/*************************************************************************** /
//
// EtherCAT从属堆栈的SPI HAL功能
//
//SPI peripehral寄存器指针,将根据根据选择的SPI进行初始化
//构建配置
易失性结构spi_regs *SpixRegs;
/*************************************************************************************************
*@fn esc_readSPI
*@brief函数最多可读取12个字节的数据
*
*@参数
* offset_addr -必须从中读取数据的ESC地址
* numbytes -要读取的字节数,由调用方一次限制为12个
*缓冲区-指向必须将读取数据复制到的缓冲区的指针
*-如果传递NULL,则数据被复制到SPI_RxData全局数组
*
*@返回-无
******************* /
void esc_readSPI(uint16_t offset_addr,uint16_t numbytes, uint16_t* buffer)
{
UINT16_t I,cmd,高级,NumWords = 0,j;
uINT16_t *buf =(uint16_t *)0;
UINT16_t读相[16];
IF ((((void *) buffer)== NULL)
{
buf =(uint16_t *)&SPI_RxData[0];
}
否则
{
buf =缓冲;
}
//为SPI xmission将地址cmd字节构建为16位字,
// SPI xmits. MSBit 1st,所以必须交换这个16b字中的字节以进行传输
//读取cmd序列的字节顺序:
//字节0:A[12:5]
//字节1:A[4:0],110b (110b是3字节cmd扩展名)
//字节2:A[15:13],CMD[2:0],00B (011b是使用WS读取的)
//字节3:FFH (等待状态)
//cmd = offset_addr & 0x1f
cmd =(offset_addr & 0x1FE0)<<3;// offset_addr[12:5]是第一个地址阶段字节,转换为高位字节
cmd ||(((offset_addr & 0x1F)<< 3)| ESC_EtherCAT_3BYTEADDR);
readphase [0]= cmd;
NumWords++;
readphase [1]=(offset_addr & 0xE000)|(ESC_EtherCAT_READ_WAIT <<10)| ESC_EtherCAT_WAIT;
NumWords++;
对于(i=2,j =0;j<numbytes;i++){
readphase [i]=(uint16_t) ESC_EtherCAT_CONTINUE;
NumWords++;
J++;
J++;
}
readphase [--i]||(ESC_EtherCAT_RDTERMINATE);//将最后一个字节设置为0xFF
对于(i = 0;i < NumWords;I++){
SpixRegs->SPITXBUF = readphase [i]和(0xFF00);
SpixRegs->SPITXBUF =((readphase [I]&(0xFF))< 8);
}
SPI_XmitInProgress = 1;
DELAY _US (10);
j =数字字节;
While (SpixRegs->SPIFFRX.bit.RXFFST <(NumWords))
{
ASM (" NOP");//需要12ns延迟
ASM (" NOP");
ASM (" NOP");
};
While (SpixRegs->SPIFFRX.bit.RXFFST!=(数字字节))
{
////忽略前两个单词(4个字节)
高级= SpixRegs->SPIRXBUF;//忽略
}
对于(I=0;(SpixRegs->SPIFFRX.bit.RXFFST!= 0);i++)
{
建议=(SpixRegs->SPIRXBUF)和0xFF;
buf[I]=(高级和0xFF);
建议=(SpixRegs->SPIRXBUF)和0xFF;
buf[i]|=(readval和0xFF)<8);
}
DELAY _US (5);
SpixRegs->SPIFFTX.Bit.TXFIFO;//重置Tx FIFO
SpixRegs->SPIFFRX.Bit.RXFIFORESET =0;//重置FIFO指针
DELAY _US (2);
SpixRegs->SPIFFTX.bit.TXFIFO;//重新启用Tx FIFO
SpixRegs->SPIFFRX.Bit.RXFIFO = 1;//重新启用FIFO操作
SPI_XmitInProgress = 0;
}
#define FIFO长度12.
/*************************************************************************************************
*@fn esc_writeSPI
*@brief函数最多可写入12字节数据
*
*@参数
* offset_addr -必须向其写入数据的ESC地址
* numbytes -要写入的字节数,由调用方一次限制为12个
* wrdata -指向必须从中将数据写入ESC的缓冲区的指针
*
*
*@返回-无
******************* /
void esc_writeSPI(uint16_t offset_addr,uint16_t *wrdata,uint16_t numbytes)
{
UINT16_t I,j,cmd,NumWords =0;
UINT16_t wptr =0;
uINT16_t写法[2];
//为SPI xmission将地址cmd字节构建为16位字,
// SPI xmits. MSBit 1st,所以必须交换这个16b字中的字节以进行传输
//读取cmd序列的字节顺序:
//字节0:A[12:5]
//字节1:A[4:0],110b (110b是3字节cmd扩展名)
//字节2:A[15:13],CMD[2:0],00B (110b是3字节cmd扩展)
//字节3:数据的第一字节
//cmd = offset_addr & 0x1f
cmd =(offset_addr & 0x1FE0)<<3;// offset_addr[12:5]是第一个地址阶段字节,转换为高位字节
cmd ||(((offset_addr & 0x1F)<< 3)| ESC_EtherCAT_3BYTEADDR);
writephase[0]= cmd;
NumWords++;
cmd = 0x0000;
cmd =(((offset_addr & 0xE000)|(ESC_EtherCAT_write <<10)));
cmd ||(wrdata[wptr]和0x00FF);
writephase[1]= cmd;
NumWords++;
I = 0;
{
SpixRegs->SPITXBUF = writephase[i]和(0xFF00);
SpixRegs->SPITXBUF =((writephase[i+]&(0xFF))<8);
SpixRegs->SPITXBUF = writephase[i]和(0xFF00);
SpixRegs->SPITXBUF =((writephase[i]&(0xFF))<<8);
}
wptr=0;
对于(j = 1;j <(数字字节-1);j+=2)
{
SpixRegs->SPITXBUF =(wrdata[wptr]和0xFF00);
SpixRegs->SPITXBUF=((wrddata[++wptr])和0x00FF)<8);
NumWords++;
}
IF (j ==(numbytes-1))
{
SpixRegs->SPITXBUF =(wrdata[wptr]和0xFF00);
NumWords++;
}
SPI_XmitInProgress = 1;
while (SpixRegs->SPIFFTX.Bit.TXFFST !=0)
{
DELAY _US (2);
};
SpixRegs->SPIFFTX.Bit.TXFIFO;//重置Tx FIFO
SpixRegs->SPIFFRX.Bit.RXFIFORESET =0;//重置FIFO指针
DELAY _US (2);
SpixRegs->SPIFFTX.bit.TXFIFO;//重置Tx FIFO
SpixRegs->SPIFFRX.Bit.RXFIFO = 1;//重新启用FIFO操作
SPI_XmitInProgress = 0;
}
/*************************************************************************** /
uINT16_t ESC_readWordNonISR(uint16_t offset_addr)
{
UINT16_t数据;
色调;
esc_readSPI (offset_addr,2,&data);
EINT;
返回数据;
}
/*************************************************************************** /
uINT16_t esc_readWordISR(uint16_t offset_addr)
{
esc_readSPI (offset_addr,2,0);
返回(SPI_RxData[0]);
}
/*************************************************************************** /
uINT32_t ESC_readDWordNonISR (uint16_t offset_addr)
{
UINT32_t DWORD;
色调;
esc_readSPI (offset_addr,4,(uint16_t *)&DWORD);
EINT;
返回DWORD;
}
/*************************************************************************** /
uINT32_t esc_readDWordISR(uint16_t offset_addr)
{
UINT32_t DWORD;
esc_readSPI (offset_addr,4,(uint16_t *)&DWORD);
返回DWORD;
}
/*************************************************************************** /
void esc_readBlockISR(uint16_t* pData, uint16_t offset_addr,uint16_t numbytes)
{
uINT16_t i = 0,current_bytes = 0,last_byte = 0;
IF (numbytes和0x1)
{
current_bytes =(numbytes - 0x1);//偶校准
}
否则
{
current_bytes =数字字节;
}
而(current_bytes > 0)//输入实际上是以字节为单位
{
IF (current_bytes >= FIFO长度)
{
esc_readSPI (offset_addr,iffo_length,(uint16_t *)&pData[I]);
current_bytes == fifo_length;
I+= FIFO长度/2;//数据以16位表示
offset_addr += FIFO长度;
}
否则
{
esc_readSPI (offset_addr,current_bytes,(uint16_t *)&pData[I]);
offset_addr +=当前字节;
I+=当前字节/2;
current_bytes = 0;
}
}
IF (numbytes和0x1)
{
last_byte = esc_readWordISR(offset_addr);
pData[i]= pData[i]& 0xFF00;
pData[i]|=最后一个字节;
}
}
/*************************************************************************** /
void esc_readBlockNonISR(uint16_t* pData, uint16_t offset_addr,uint16_t numbytes)
{
色调;
esc_readBlockISR(pData, offset_addr, numbytes);
EINT;
}
/*************************************************************************** /
void esc_writeWordNonISR (uint16_t wrdata,uint16_t offset_addr)
{
色调;
esc_writeSPI (offset_addr,&wrdata,0x02);
EINT;
}
/*************************************************************************** /
void esc_writeWordISR(uint16_t wrdata,uint16_t offset_addr)
{
esc_writeSPI (offset_addr,&wrdata,0x02);
}
/*************************************************************************** /
void esc_writeDWordNonISR(UINT32_t wrdata, uint16_t offset_addr)
{
色调;
esc_writeSPI (offset_addr,(uint16_t *)&wrdata,0x04);
EINT;
}
/*************************************************************************** /
void esc_writeWordISR(UINT32_t wrdata, uint16_t offset_addr)
{
esc_writeSPI (offset_addr,(uint16_t *)&wrdata,0x04);
}
/*************************************************************************** /
void esc_writeBlockISR(uint16_t* pData, uint16_t offset_addr,uint16_t numbytes)
{
uINT16_t i = 0,current_bytes = 0;
IF (numbytes和0x1)
{
current_bytes =(numbytes - 0x1);//偶校准
}
否则
{
current_bytes =(数字字节);
}
而(current_bytes > 0)//输入实际上是以字节为单位
{
IF (current_bytes >= FIFO长度)
{
esc_writeSPI (offset_addr,(uint16_t *)&pData[i],FIFO长度);
current_bytes == fifo_length;
I+= FIFO长度/2;//数据以16位表示
offset_addr += FIFO长度;
}
否则
{
esc_writeSPI (offset_addr,(uint16_t *)&pData[i],current_bytes);
offset_addr +=当前字节;
I+=当前字节/2;
current_bytes = 0;
}
}
IF (numbytes和0x1)
{
//现在发送带有额外校准字节的最后一个字节
//请注意,我们读取相邻的字节并将其写回
esc_readSPI(offset_addr, 2,&I);
I &= 0xFF00;
i |=(pData[((numbytes-1)>>1)]和0xFF;//pData是16位指针
esc_writeSPI(offset_addr,&I, 2);
}
}
/*************************************************************************** /
void esc_writeBlockNonisr (uint16_t* pData, uint16_t offset_addr,uint16_t numbytes)
{
色调;
esc_writeBlockISR(pData, offset_addr, numbytes);
EINT;
}
//------------------
//初始化SPI端口的函数
//------------------
void esc_initSPIFIFO (void)
{
uINT16_t m;
EALLOW;
// FIFO配置
SpixRegs->SPIFFCT.All=0x0;//将SPI置于复位状态
对于(m=0;m<3;m++);
SpixRegs->SPIFFRX.all=0x2040;// RX FIFO已启用,清除FIFO
SpixRegs->SPIFFRX.Bit.RXFFIL =16;//设置RX FIFO级别
SpixRegs->SPIFFTX.all=0xE040;// FIFO已启用,TX FIFO已释放,
// SPI配置
SpixRegs->SPIFFTX.Bit.TXFFIL =16;//设置TX FIFO级别
SpixRegs->SPICCR.bit.SPICHAR = 0x7;//0xF;//字符长度=8
SpixRegs->SPICCR.bit.CLKPOLARITY =1;//上升边缘
SpixRegs->SPICCR.bit.HS_MODE = 0;//非高速模式
SpixRegs->SPICTL.bit.SPIINTENA =1;//已启用
SpixRegs->SPICTL.bit.Talk =1;//
SpixRegs->SPICTL.bit.Master_slave =1;//主模式
SpixRegs->SPICTL.bit.CLK_PHASE =0;//添加Clk wrt SPISTEA的1/2周期延迟
SpixRegs->SPICTL.bit.OVERRUNINTENA =1;//启用了溢出中断
SpixRegs->SPISTS.all=0x0000;//清除状态位(TxBufFull,INT, Overlife)
// SpixRegs->SPIBRR.ALL = 0x63;// LSPCLK/100
ClkCfgRegs.LOSPPCN.ALL = 0x1;// 0 = SYSCLK/1 = 200m;1 = SYSCLK/2 = 100m
SpixRegs->SPIBRR.All=0x004;//波特率= LSPCLK /(SPIBRR+1)[LSPCLK=SYSCLK/4 (默认为50m])
SpixRegs->SPIFFCT.All=0x00;
SpixRegs->SPIPRI.All=0x0020;// EmuStop (EmuStop)时事务完成后停止
SpixRegs->SPIFFTX.bit.TXFFIENA = 0;//禁用TXFF INT
SpixRegs->SPIFFRX.Bit.RXFFIENA = 0;//禁用RXFF INT
SpixRegs->SPICCR.bit.SPISWRESET=1;//启用SPI
EDIS;
}
//------------------
//初始化SPIB端口的GPIO的功能
// GPIO64,GPIO65,GPIO66,GPIO63
//不用于TMDSECATCNCD379D套件
//------------------
void esc_initSPIBGpio(void)
{
EALLOW;
//在SPISIMO/SPISOMI/SPICLK/SPISTE引脚上启用上拉拔
gpioCtrlRegs.GPCPUD.all &= 0xFFFFFFF8;
gpioCtrlRegs.GPBPUD.all &= 0xFFFFFFFE;
//启用SPISIMO/SPISOMI/SPICLK引脚
gpioCtrlRegs.GPCGMUX1.bit.GPIO64 = 0x3;
GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 0x3;
gpioCtrlRegs.GPCGMUX1.bit.GPIO65 = 0x3;
GpioCtrlRegs.GPCMUX1.bit.GPIO65 = 0x3;
gpioCtrlRegs.GPCGMUX1.bit.GPIO66 = 0x3;
GpioCtrlRegs.GPCMUX1.bit.GPIO66 = 0x3;
gpioCtrlRegs.GPBGMUX2.bit.GPIO63 = 0x3;
gpioCtrlRegs.GPBMUX2.bit.GPIO63 = 0x3;
//启用SPISIMO/SPISOMI/SPICLK引脚作为异步
gpioCtrlRegs.GPCQSEL1.all || 0xF;
gpioCtrlRegs.GPBQSEL2.bit.GPIO63 = 0x3;
EDIS;
}
//------------------
//初始化***端口的GPIO的功能
// GPIO122,GPIO123,GPIO124,GPIO125
//用于TMDSECATCNCD379D套件的功能
//------------------
void esc_initSPICGpio(void)
{
EALLOW;
//带有HD连接器的新控制卡
//在SPISIMO/SPISOMI/SPICLK/SPISTE引脚上启用上拉拔
1221.23124125亿
gpioCtrlRegs.GPDPUD.ALL &= 0xC3FFFFFF;
//启用SPISIMO/SPISOMI/SPICLK引脚
gpioCtrlRegs.GPDGMUX2.bit.GPIO122 = 0x1;
gpioCtrlRegs.GPDGMUX2.bit.GPIO123 = 0x1;
gpioCtrlRegs.GPDGMUX2.bit.GPIO124 = 0x1;
gpioCtrlRegs.GPDGMUX2.bit.GPIO125 = 0x1;
gpioCtrlRegs.gPDMUX2.bit.GPIO122 = 0x2;
gpioCtrlRegs.gPDMUX2.bit.GPIO123 = 0x2;
GpioCtrlRegs.GPDMUX2.bit.GPIO124 = 0x2;
gpioCtrlRegs.gPDMUX2.bit.GPIO125 = 0x2;
//启用SPISIMO/SPISOMI/SPICLK引脚作为异步
gpioCtrlRegs.GPDQSEL2.all |= 0x03F0万;
EDIS;
}
//------------------
//初始化SPIÁ 端口的GPIO的函数
// GPIO58 (SIMOA),GPIO59 (Somia),GPIO60 (CLKA),GPIO61 (拉美经济体系)
// GPIO16,GPIO17,GPIO18,GPIO19 (注释掉)
//不用于TMDSECATCNCD379D套件
//------------------
void esc_initSPIAGpio(void)
{
EALLOW;
/*为所选引脚启用内部上拉*/
//用户可以启用或禁用上拉。
//这将启用指定引脚的上拉。 在SPISIMO/SPISOMI/SPICLK/SPISTE引脚上启用上拉拔
gpioCtrlRegs.GPBPUD.bit.GPIO58 = 0;//在GPIO58上启用上拉(SPISIMO-A)
gpioCtrlRegs.GPBPUD.bit.GPIO59 = 0;//在GPIO59上启用上拉(SPISOMI-A)
gpioCtrlRegs.GPBPUD.bit.GPIO60 = 0;//在GPIO60上启用上拉(SPICLK-A)
gpioCtrlRegs.GPBPUD.bit.GPIO61 = 0;//在GPIO61上启用上拉(SPISTE-A)
/*将所选引脚的限定条件设置为仅异步*/
//这将为所选引脚选择异步(无限定条件)。
gpioCtrlRegs.GPBQSEL2.bit.GPIO58 = 3;//异步输入GPIO58 (SPISIMO-A)
gpioCtrlRegs.GPBQSEL2.bit.GPIO59 = 3;//异步输入GPIO59 (SPISOMI-A)
gpioCtrlRegs.GPBQSEL2.bit.GPIO60 = 3;//异步输入GPIO60 (SPICLK-A)
gpioCtrlRegs.GPBQSEL2.bit.GPIO61 = 3;//异步输入GPIO61 (SPISTE-A)
//使用GPIO寄存器配置SPI-A引脚
//这指定了哪些GPIO引脚将是SPI功能引脚。
//G-Mux
GpioCtrlRegs.GPBGMUX2.bit.GPIO58 = 3;//启用(SPISIMO-A)
GpioCtrlRegs.GPBGMUX2.bit.GPIO59 = 3;//启用(SPISOMI-A)
GpioCtrlRegs.GPBGMUX2.bit.GPIO60 = 3;//启用(SPISCLK-A)
GpioCtrlRegs.GPBGMUX2.bit.GPIO61 = 3;//启用(SPISTE-A)
//Mux
gpioCtrlRegs.GPBMUX2.bit.GPIO58 = 3;//启用(SPISIMO-A)
GpioCtrlRegs.GPBMUX2.bit.GPIO59 = 3;//启用(SPISOMI-A)
GpioCtrlRegs.GPBMUX2.bit.GPIO60 = 3;//启用(SPISCLK-A)
gpioCtrlRegs.GPBMUX2.bit.GPIO61 = 3;//启用(SPISTE-A)
EDIS;
}
/*EALLOW;(TI针对SPI-A和GPIO 16,17,18,19的旧配置)
//在SPISIMO/SPISOMI/SPICLK/SPISTE引脚上启用上拉拔
gpioCtrlRegs.gpapud.all &= 0xFFF0FFFFFFFFF;
//启用SPISIMO/SPISOMI/SPICLK引脚
gpioCtrlRegs.GPAMUX2.all |= 0x0.0055万;
//启用SPISIMO/SPISOMI/SPICLK引脚作为异步
gpioCtrlRegs.GPAQSEL2.all || 0x0.0003万F;
EDIS;
}*/
/*************************************************************************** /
void ESC_释放ET1100重置(void)
{
GPIO _SetupPinMux (ESC_RESET_ET1100_GPIO,GPIO _MUX_CPU1,0);
GPIO _WritePin (ESC_RESET_ET1100_GPIO,1);//释放重置
}
/*************************************************************************** /
void esc_holdET1100InReset (void)
{
GPIO _SetupPinMux (ESC_RESET_ET1100_GPIO,GPIO _MUX_CPU1,0);
GPIO_WritePin (ESC_RESET_ET1100_GPIO,0);//在复位中保持
}
/*************************************************************************** /
void ESC_configureLatch0GPIO (void)
{
//此功能将SYNC0 GPIO配置为锁存输出(输入到ESC)
GPIO_SetupPinOptions (ESC_SYNC0_GPIO,GPIO输出,GPIO上拉);
GPIO_SetupPinMux (ESC_SYNC0_GPIO,GPIO _MUX_CPU1,0);
}
/*************************************************************************** /
void ESC_configureLatch1GPIO (void)
{
//此功能将SYNC1 GPIO配置为锁存输出
GPIO_SetupPinOptions (ESC_SYNC1_GPIO,GPIO输出,GPIO上拉);
GPIO_SetupPinMux (ESC_SYNC1_GPIO,GPIO _MUX_CPU1,0);
}
//------------------
// ISR来处理PDI ISR
//------------------
中断void ESC_applicationLayerISR()
{
//调用从属堆栈ISR例程
#ifdef etherCAT_stack
PDI_ISR();
#endif
PieCtrlRegs.PIEACG.ALL |= 0x01;//发出pie ack
}
//------------------
// ISR来处理SYNC0 ISR
//------------------
中断无效ESC_applicationSync0ISR()
{
#ifdef etherCAT_stack
Sync0_ISR();
#endif
//XINT5,PIE 12.INT3
PieCtrlRegs.PIEACK/bit.ACK12 = 1;
}
//------------------
// ISR来处理SYNC1 ISR
//------------------
中断无效ESC_applicationSync1ISR()
{
#ifdef etherCAT_stack
Sync1_ISR();
#endif
//XINT4,PIE 12.INT2
PieCtrlRegs.PIEACK/bit.ACK12 = 1;
}
//------------------
//函数启用controlCARD配置上SYNC0信号的调试
//------------------
void esc_enableSync0DebugOnCCARD(void)
{
//用于调试SYNC0行。-以下代码将GPIO2连接到SYNC0
//内部原因是在HW板上,我们不能在HighRose连接器上的SYNC0上放置范围
//Connect SYNC0 (GPIO86)是的Input1
EALLOW;
InputXbarRegs.INPUT1SELECT = ESC_SYNC0_GPIO;//input1与GPIO113绑定
OutputXbarRegs.OUTPUT1MUX0TO15CFG.bit.MUX1 = 0x1;//INPUTXBAR1到OUTPUTXBAR1
OutputXbarRegs.OUTPUT1MUXENABLE.Bit.MUX1 = 0x1;
GpioCtrlRegs.GPAGMUX1.bit.GPIO2 = 0x01;//GPIO2到OUTPUTXBAR1
GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0x01;
EDIS;
}
//------------------
//在controlCARD配置上配置SYNC0信号的功能
//------------------
void ESC_configureSync0GPIO (void)
{
GPIO_SetupPinOptions (ESC_SYNC0_GPIO,GPIO输入,GPIO上拉| GPIO异步);
GPIO_SetupPinMux (ESC_SYNC0_GPIO,GPIO _MUX_CPU1,0);
EALLOW;
InputXbarRegs.INPUT14SELECT = ESC_SYNC0_GPIO;//input14与XINT5绑定
PieVectorTable.XINT5_INT =&ESC_applicationSync0ISR;
XintRegs.XINT5CR.bit.Polarity = 1;//下降边缘中断
XintRegs.XINT5CR.bit.enable = 1;
PieCtrlRegs.PIEIER12.bit.INTx3 =1;//启用组12,INT3 (XINT5)
IER |= 0x0800;
EDIS;//这是禁用写入EALLOW保护寄存器所必需的
esc_enableSync0DebugOnCCARD();
}
//------------------
//函数启用controlCARD配置上SYNC0信号的调试
//------------------
void esc_enableSync1DebugOnCCARD(void)
{
//用于SYNC1行的调试。-以下代码将GPIO3连接到SYNC1
//内部原因是在HW板上,我们不能在HighRose连接器上的SYNC1上放置范围
//Connect SYNC1是的Input1
EALLOW;
InputXbarRegs.INPUT2SELECT = ESC_SYNC1_GPIO;//input2与SYNC1绑定
OutputXbarRegs.OUTPUT2MUX0TO15CFG.bit.MUX3 = 0x1;//INPUTXBAR2到OUTPUTXBAR2
OutputXbarRegs.OUTPUT2MUXENABLE.bit.MUX3 = 0x1;
GpioCtrlRegs.GPAGMUX1.bit.GPIO3 = 0x01;//GPIO3至OUTPUTXBAR2
GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 0x01;
EDIS;
}
//------------------
//在controlCARD配置上配置SYNC1信号的功能
//------------------
void esc_configureSync1GPIO (void)
{
GPIO_SetupPinOptions (ESC_SYNC1_GPIO,GPIO输入,GPIO上拉| GPIO异步);
GPIO_SetupPinMux (ESC_SYNC1_GPIO,GPIO _MUX_CPU1,0);
EALLOW;
InputXbarRegs.INPUT13SELECT = ESC_SYNC1_GPIO;//input13与XINT4绑定
PieVectorTable.XINT4_INT =&ESC_applicationSync1ISR;
XintRegs.XINT4CR.bit.polarity = 1;//下降边缘中断
XintRegs.XINT4CR.bit.enable = 1;
PieCtrlRegs.PIEIER12.bit.INTx2 = 1;//启用组12,INT2 (XINT4)
IER |= 0x0800;
EDIS;//这是禁用写入EALLOW保护寄存器所必需的
esc_enableSync1DebugOnCCARD();
}
/*************************************************************************** /
void ESC_resetET1100 (void)
{
GPIO _SetupPinMux (ESC_RESET_ET1100_GPIO,GPIO _MUX_CPU1,0);
GPIO_WritePin (ESC_RESET_ET1100_GPIO,0);//保持复位低
DELAY _US (500*1000);
GPIO _WritePin (ESC_RESET_ET1100_GPIO,1);//释放重置
DELAY _US (500*1000);
}
/*************************************************************************** /
UINT16_t ESC_ET1100EEPROMLoadedCheck (无效)
{
uINT16_t ii = 0;
GPIO_SetupPinMux (ESC_EEPROM_LOADD_GPIO,GPIO _MUX_CPU1,0);
while (!gPIO_ReadPin (ESC_EEPROM_LOADD_GPIO))
{
DELAY _US (500*1000);
II++;
如果(ii > 10)
中断;
}
如果(ii > 10)
返回0;
否则
返回1;
}
/*************************************************************************** /
void ESC_passFailSignalSetup (void)
{
//注意:-使用EMIF1时不调用此功能,因为存在
//与GPIO31和GPIO34与EMIF1信号和LED冲突
//因此,对于2.0 ,用户只知道是否有错误
//两个LED (GPIO31和GPIO34高或低始终意味着没有错误亮起
// Launchpad XL 2.0)
GPIO_SetupPinMux (34,GPIO _MUX_CPU1,0);
GPIO_SetupPinMux (31,GPIO _MUX_CPU1,0);
GPIO_SetupPinOptions (34,1,GPIO _OPENDRAIN | GPIO _上拉);
GPIO_SetupPinOptions (31,1,GPIO _OPENDRAIN | GPIO _上拉);
//GPIO34和GPIO31处于高位-表示无错误
//默认情况下,保持GPIO31和GPIO34低以供通过
GpioDataRegs.GPADAT.bit.GPIO31 = 1;
GpioDataRegs.GPBDAT.bit.GPIO34 = 1;
}
/*************************************************************************** /
void esc_signalFail (void)
{
//将GPIO34和GPIO31切换为FAIL
GpioDataRegs.GPBTOGLE.bit.GPIO34 = 1;
GpioDataRegs.GPATOGLE.bit.GPIO31 = 1;
DELAY _US (10 * 1000);
}
/*************************************************************************** /
void esc_signalPass (void)
{
//保持GPIO31和GPIO34低通
GpioDataRegs.GPADAT.bit.GPIO31 = 1;
GpioDataRegs.GPBDAT.bit.GPIO34 = 1;
DELAY _US (500 * 1000);
}
//------------------
// ISR来处理EPWM1 ISR
// prdTick - EPWM1每4个QCLK计数(一个周期)中断一次
//------------------
中断无效epwm1_isr (无效)
{
IF (int1cnt == 2)//10kHz控制环路频率
{
EALLOW;
//取消注释以下行,以便读取第三个编码器的值
//------------------
////读取第三个编码器
////读取eQEp的原始值
qep_posspeed.calc(&qep_posspeed);
//
////读取原始位置eQEP3
// if ((unsigned long int) qep_posspeed.raW_pos3 > pos_init)
// raW_pos3 =(无符号长整型) qep_posspeed.raW_pos3 - pos_init;
//其他
// raW_pos3 =-(pos_init -(无符号长int) qep_posspeed.raW_pos3);
// gwnia3 = 360.0f *(raW_pos3 * 8.0f * 26.0f)
//(2000.0f * 343.0f * 48.0f);//2000行
//------------------
//控制电机1膝部(BLDC)
//读取第一个编码器
//读取eQEp的原始值
qep_posspeed.calc(&qep_posspeed);
//读取原始位置eQEP1
如果(unsigned long int) qep_posspeed.raW_pos1 > pos_init)
raW_pos1 =(无符号长整型) qep_posspeed.raW_pos1 - pos_init;
否则
raW_pos1 =-(pos_init -(无符号长int) qep_posspeed.raW_pos1);
angle_count1=raW_pos1;
//将原始值转换为度
gwnia1 = 360.0f *(raW_pos1 * 8.0f * 26.0f)/(2000.0f * 343.0f * 48.0f);
//标准化gwnia1的值
ngwnia1 =(gwnia1 * 1.0f)/ 360.0f;
//运行PID控制器
uk1 = dcl_runPID_c4(&pid1, rk1, ngwnia1, lk1);
//设置方向
如果(uk1 >= 0.0f)
GPIO写入引脚(dir1_GPIO,0);
否则
{
GPIO写入引脚(dir1_GPIO,1);
uk1 =-uk1;
}
//更新PWM占空比
//EPwm1Regs.CMPA.bit.CMPA =(1.0f - uk1)* SP;
EPwm1Regs.CMPA.bit.CMPA =(1.0f-SP*LED_Frequency)* 0.01 ;
int1cnt = 0;
}
int1cnt++;
EDIS;
//清除此计时器的INT标志
EPwm1Regs.ETCLR.bit.INT = 1;
//
//确认此__interrupt以接收来自组3的更多__interrupts
//
PieCtrlRegs.PIEACG.ALL = PIEACK_Group3;
}
//------------------
// ISR来处理EPWM2 ISR
// prdTick - EPWM2每4个QCLK计数(一个周期)中断一次
//------------------
中断无效epwm2_isr(void)
{
IF (int2cnt == 2)//10kHz控制环路频率
{
EALLOW;
//控制电机2 Hip (刷式直流)
//读取eQEp的原始值
qep_posspeed.calc(&qep_posspeed);
如果(unsigned long int) qep_posspeed.raW_pos2 > pos_init)
raW_pos2 =(无符号长整型) qep_posspeed.raW_pos2 - pos_init;
否则
raW_pos2 =-(pos_init -(无符号长int) qep_posspeed.raW_pos2);
//将原始值转换为度
gwnia2 = 360.0f *(raW_pos2 * 12.0f * 26.0f)/(2000.0f * 637.0f * 48.0f);
//标准化gwnia2的值
ngwnia2 =(gwnia2 * 1.0f)/ 360.0f;
//运行PID控制器
uk2 = DCL_runPID_C4(&pid2, Rk2, ngwnia2, lk2);
//设置方向
如果(uk2 >= 0.0f)
GPIO写入引脚(dir2_GPIO,0);
否则
{
GPIO写入引脚(dir2_GPIO,1);
uk2 =-uk2;
}
//更新PWM占空比
EPwm2Regs.CMPA.bit.CMPA =(1.0f - uk2)* SP;
//重置中断计数器
int2cnt = 0;
}
int2cnt++;
EDIS;
//清除此计时器的INT标志
EPwm2Regs.ETCLR.bit.INT = 1;
//
//确认此__interrupt以接收来自组3的更多__interrupts
//
PieCtrlRegs.PIEACG.ALL = PIEACK_Group3;
}
//------------------
//处理ADC信号的功能
//------------------
void ReadAnalog (void)
{
//
//转换,等待完成并存储结果
//通过软件ADCA立即开始转换
//
AdcaRegs.ADCSOCFRC1.ALL = 0x0003;//SOC0和SOC1
//
//立即通过软件ADCB开始转换
//
AdcbRegs.ADCSOCFS2 = 0x0003;//SOC0和SOC1
//
//等待ADCA完成,然后确认标志
//
while (AdcaRegs.ADCINTFLG.bit.ADCINT1 ==0)
;
ADcaRegs.ADCINTFLGCLL.Bit.ADCINT1 = 1;
//
//等待ADCB完成,然后确认标志
//
while (AdcbRegs.ADCINTFLG.bit.ADCINT1 ==0)
;
ADcbRegs.ADCINTFLGCLL.bit.ADCINT1 = 1;
//
//存储结果
//
AdcaResult0 = AdcaResultRegs.ADCRESULT0;
AdcaResult1 = AdcaResultRegs.ADCRESULT1;
AdcbResult0 = AdcbResultRegs.ADCRESULT0;
AdcbResult1 = AdcbResultRegs.ADCRESULT1;
}
/*************************************************************************** /
void esc_initHW(void)
{
#ifdef闪存
//将时间关键代码和闪存设置代码复制到RAM
// RamfuncsLoadStart,RamfuncsLoadEnd和RamfuncsRunStart
//符号由链接器创建。 请参阅链接程序文件。
memcpy (&RamfuncsRunStart,&RamfuncsLoadStart,(UINT32_t)&RamfuncsLoadSize);
#endif
InitSysCtrl();
//仅在从闪存运行时使用
//请注意,变量flash由编译器定义
#ifdef闪存
//呼叫闪存初始化以设置闪存等待
//此功能必须驻留在RAM中
InitFlash();//调用闪存包装程序init函数
#endif //(闪存)
//
//启用PWM1,PWM2和PWM3
//
CpuSysRegs.PCLKCR2.bit.EPWM1 = 1;
CpuSysRegs.PCLKCR2.bit.EPWM2 = 1;
//
//清除所有__interrupts并初始化PIE矢量表:
//禁用CPU __interrupts
//
色调;
//将PIE控件寄存器初始化为其默认状态。
//默认状态是禁用所有PIE中断和标志
//被清除。
//此函数位于F2837xD_PIECTRL.c文件中。
InitPieCtrl();
//禁用CPU中断并清除所有CPU中断标志:
EALLOW;
IER = 0x0000;
IFR = 0x0000;
EDIS;
//使用指向外壳中断的指针初始化PIE矢量表
// GService例程(ISR)。
//这将填充整个表,即使中断也是如此
//在本例中不使用。 这对于调试非常有用。
// shell ISR例程位于F2837xD_DefaultIsr.C.中
//此函数位于F2837xD_PieVect.C.中
InitPieVectorTable();
EALLOW;
//初始化GPIO:
//此示例函数可在F2837xD_GPIO.c文件和中找到
//说明了如何将GPIO设置为其默认状态。
//
此示例跳过InitGpio();//
GPIO_SetupPinMux (dir1_GPIO,GPIO _MUX_CPU1,0);
GPIO设置插件选项(dir1_GPIO,GPIO输出,GPIO推送);
GPIO_SetupPinMux (dir2_gPIO,gPIO_MUX_CPU1,0);
GPIO_SetupPinOptions (dir2_gPIO,gPIO_OUTPUT,gPIO_PushPull);
//
//在这种情况下,仅初始化eQEP1,2,3和ePWM1,2的GPIO
//此函数位于F2837xD_eQEP.c中
//
InitEQep1Gpio();
InitEQep2Gpio();
InitEQep3Gpio();
Initepwm1gpio();
Initepwm2gpio();
InitCpuTimers();
//------------------
//TxCnt=0;
SPI_XmitInProgress = 0;
#ifdef use_spia
SpixRegs = SpiaRegs (&S);
esc_initSPIAGpio();
#Elif use_spic
SpixRegs = SpicRegs(&S);
esc_initSPICGpio();
#否则
SpixRegs = SpibRegs (&S);
esc_initSPIBGpio();
#endif
esc_initSPIFIFO();
//本示例中使用的中断被重新映射到
//此文件中找到ISR函数。
EALLOW;//这是写入EALLOW保护寄存器所必需的
PieVectorTable.XINT1_INT =&ESC_applicationLayerISR;
PieVectorTable.EPWM1_INT =&epwm1_ISR;
PieVectorTable.EPWM2_INT =&epwm2_isr;
EDIS;//这是禁用写入EALLOW保护寄存器所必需的
//初始化eQEP外设
qep_posspeed.init(&qep_posspeed);
//
//配置ADC并将其打开
//
CpuSysRegs.PCLKCR13.bit.ADC_A = 1;
配置ADC();
//
//为软件转换设置ADC
//
SetupADCSoftware();
//初始化ePWM外设
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
EDIS;
initEpwm();
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;
//从ET1100配置外部中断
EALLOW;
InputXbarRegs.INPUT4SELECT = ESC_SPI_INT_GPIO;
GPIO_SetupPinOptions (ESC_SPI_INT_GPIO,GPIO输入,GPIO上拉| GPIO异步);
XintRegs.XINT1CR.bit.polarity = 0x0;//下降边缘中断
XintRegs.XINT1CR.bit.enable =1;
//EDIS;
//
//启用连接到EPWM1-3 INT的CPU INT3:
//
IER |= M_INT3;
//
//在PIE中启用TINT0:组3 __interrupt 1
//
PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
//PieCtrlRegs.PIEIER3.bit.INTx3 = 1;
//启用此示例所需的中断
PieCtrlRegs.PIECTRL.bit.ENPIE =1;//启用PIE块
PieCtrlRegs.PIEIER1.bit.INTx4 = 1;//启用组1,INT4 (XINT1)
IER || 0x01;//启用CPU INT1
EINT;//启用全局中断
ERTM;//启用全局实时__interrupt DBGM
ESC_passFailSignalSetup();
EALLOW;
//CpuTimer0Regs.tcr.bit.tie = 1;
CpuTimer0Regs.tcr.bit.ts = 0;//开始计时器
ESC_configureSync0GPIO ();
ESC_configureSync1GPIO ();
// esc_configureLatch0gPIO()
// esc_configureLatch1gPIO();
IF(!ESC_ET1100EEPROMLoadedCheck())
{
// EEPROM加载失败
//信号故障
同时(1)
{
//失败
esc_signalFail ();
DELAY _US (500 * 1000);
}
}
rk1 = 0.0f;//设定值为0度
RK2 = 0.0f;
//delay_US(2*100万);//wait for 2 sec
}
/*************************************************************************** /
您是否有任何线索,为什么它仅在通过闪存执行时导致此问题?
提前感谢您的参与
Stamatis