This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CCS/TMS320F28069M:switch 语句不起作用(Instaspin 代码)

Guru**** 2609285 points
Other Parts Discussed in Thread: LAUNCHXL-F28379D, DRV8301, DRV8305

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/683232/ccs-tms320f28069m-switch-statement-does-not-work-instaspin-code

器件型号:TMS320F28069M
主题中讨论的其他器件:LAUNCHXL-F28379DDRV8301DRV8305

工具/软件:Code Composer Studio

大家好、我看到开关和用例语句有非常奇怪的行为、我在为 CAN 总线配置代码编写一些函数、当我尝试使用开关时-如果它不起作用、代码运行异常、不切换到正确的用例。 然后、我决定测试 switch case 语句、将几个 case 和简单的变量增量作为任务、但它不起作用:如果 switch case 语句是无限循环  、它有时甚至不会进入循环、否则它只能连续执行(case 0:)。

然后我尝试像这样硬编码:

开关(0)

{…

编译->运行  

开关(1)

{…

编译->运行  

这样做会选择正确的情况、但这样、switch case 语句是无用的。

我将使用 launchpad XL f28069M

我在 instaspin proj_lab01上编写 CAN 总线代码、除 switch case 语句外、一切都正常

也尝试了 proj_lab01b、但 switch case 语句的行为相同。

然后、我认为我可能是 Code Composer Studio 和的一些问题  

然后、我在 LAUNCHXL-F28379D 上尝试了相同的代码、一切都正常... 因此问题发生在 f28069M 上

/*开始传输*/
int counter=0;
int loopcount=0;
for (;;)
{
switch (计数器)
{
情况0:
loopcount+=0;
中断;
案例1:
loopcount+=1;
中断;
案例2:
loopcount+=2;
中断;
案例3:
loopcount+=3;
中断;
案例4:
loopcount+=4;
中断;
默认值:
loopcount+=5;
中断;
}
counter+=1;
} 

谢谢大家

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    你好

    我已尝试您在 F28069 controlCARD 上发布的代码、但没有发现任何问题。 您是否启用了优化? 如果是、请尝试禁用。 您是否单步执行并观察了开关值? 您还可以分享有关您正在运行的方案的其他详细信息吗?

    此致
    Chris
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、先生、我检查了优化并在2级(全局优化)上进行了选择、我关闭了优化、现在它可以工作了、
    现在、我的问题是、它将以任何方式影响 instaspin 代码?
    我应该始终不进行优化吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    最好在 instaSPIN 项目中保持优化。 此外、通过启用级别2优化、执行交换机没有任何问题。 下面的这些行代码被优化阻止、因为执行代码后计数器和循环计数没有改变。 如果您将代码更改为"loopcount+=N;(N!=0)"、则将执行该代码。

    情况0:
    loopcount+=0;
    中断;
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    先生、首先、您好、感谢您的回复、  

    但我不明白这个表达式的意思: "loopcount+=N;(N!=0)"您是否意味着我需要在排除 N=0的情况下增加 N 的循环计数?

    通过再次启用优化并尝试以下操作:

    int counter=0;
    int loopcount=0;
    for (;)
    {
    
    switch (计数器)
    {
    情况0:
    loopcount+=1;
    COUNTER+=1;
    中断;
    案例1:
    loopcount+=1;
    COUNTER+=1;
    中断;
    案例2:
    loopcount+=2;
    COUNTER+=1;
    中断;
    案例3:
    loopcount+=3;
    COUNTER+=1;
    中断;
    案例4:
    loopcount+=4;
    COUNTER+=1;
    中断;
    默认值:
    loopcount+=5;
    COUNTER+=1;
    中断;
    }
    //counter+=1;
    } 

    我尝试过这种方法、通过分步调试、它甚至不会输入 switch 语句...

    我甚至尝试将开关置于(counter=0;counter<5;counter++){……}的位置 但它不起作用。。。

    谢谢主席先生的耐心

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    "switch"代码放置在 instaSPIN 实验室项目中的什么位置? "计数器"和"循环计数"在哪里定义?
    如果在 for (;)循环中添加了这些代码、但在 while (gMotorVars.Flag_enableSys)循环中未添加这些代码、您是否启用了 gMotorVars.Flag_enableSys? 如果是、这是正确的、则无法执行代码。 请您发布整个代码吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、先生、我尝试全局定义它们、在这种情况  下、当它只进入无限循环并且情况0已被执行并且只有计数器被递增时、loppcount 永远不会递增。

    当我在主函数的开头定义它们时,只有情况4和默认情况被激活,并且只有计数器在递增,循环计数保持不变....

    我使用的是第一个 proj_lab01、因此与 instaspin 代码相关的无限循环中没有任何内容、这就是我使用它编写 CAN 总线函数的原因...

    下面是完整的代码:

    秘书长的报告
    //包括

    //系统包括
    #include


    //模块
    #include "sw/modules/math/src/32b/math.h"
    #include "sw/modules/memcopy/src/Cmemcopy.h"
    #include "sw/drivers/CAN/src/32b/F28x/f2806x/CAN.h"
    #include "sw/drivers/CPU src/32b/F28x/f2806x/cpu.h"

    //驱动程序


    //平台
    #include "main.h"

    void InitECana(void);
    void configureTransmitMailbox();
    void configureReciveMailbox();
    void transmitMessage();
    void reciveMessage();


    #define TXCOUNT 100000 //传输将发生(TXCOUNT)次。
    长 I;

    /*
    * eCAN 控制寄存器需要使用32位进行读/写访问。 因此、我们
    *将为此示例创建一组影子寄存器。 阴影
    *将使用寄存器确保访问是32位而不是16位。
    *
    struct eCAN-regs ECanaShadow;
    ////////////////////////////////////////////////////////////////////////////////////
    tCANMsgObject sTXCANMessage;

    //CLK_ClkOutPreScale_e xlcout_prescaler;
    //xlcout_prescaler
    秘书长的报告
    //定义

    #define LED_BLINK FREQ_Hz 5.

    秘书长的报告
    //全局变量

    UINT_least32_t gLEDcnt = 0;//用于对 ISR 速率进行分频以使 LED 直观闪烁的计数器

    #ifdef csm_enable
    #pragma DATA_SECTION (halHandle、"ROM_accessed_data");
    #endif
    HAL_Handle halHandle;//处理到逆变器硬件抽象层

    #ifdef csm_enable
    #pragma DATA_SECTION (gUserParams、"ROM_accessed_data");
    #endif
    USER_Params gUserParams;//包含 user.h 设置

    HAL_PwmData_t gPwmData ={0、0、0};//包含全局 Q 格式的 PWM 占空比

    HAL_AdcData_t gAdcData ={0、0、0、0、0、0};//包含全局 Q 格式的电流和电压 ADC 读数

    volatile motor_Vars_t gMotorVars = motor_Vars_init;

    ifdef 闪存
    //用于在闪存中运行后台,在 RAM 中运行 ISR
    extern uint16_t * RamfuncsLoadStart、* RamfuncsLoadEnd、* RamfuncsRunStart;

    #ifdef csm_enable
    extern uint16_t * econst_start、* econst_end、* econst_ram_load;
    extern uint16_t * switch_start、* switch_end、* switch_ram_load;
    #endif
    #endif


    #ifdef DRV8301_SPI
    //连接到8301 SPI 的监视窗口接口
    DRV_SPI_8301_Vars_t gDrvSpi8301Vars;
    #endif

    #ifdef DRV8305_SPI
    //连接到8305 SPI 的监视窗口接口
    DRV_SPI_8305_Vars_t gDrvSpi8305Vars;
    #endif

    秘书长的报告
    //函数

    int 计数器=0;
    int loopcount=0;

    void main (void)

    //仅在从闪存运行时使用
    //请注意,变量闪存是由项目定义的
    ifdef 闪存
    //将时间关键代码和闪存设置代码复制到 RAM
    // RamfuncsLoadStart、RamfuncsLoadEnd 和 RamfuncsRunStart
    //符号由链接器创建。 请参阅链接器文件。
    Memcopy ((uint16_t *)&RamfuncsLoadStart、(uint16_t *)&RamfuncsLoadEnd、(uint16_t *)&RamfuncsRunStart);

    #ifdef csm_enable
    //copy .econst 至 unsecure RAM
    if (* econst_end -* econst_start)

    Memcopy ((uint16_t *)&econst_start、(uint16_t *)&econst_end、(uint16_t *)&econst_ram_load);

    //copy .switch ot unsecure RAM
    if (* switch_end -* switch_start)

    Memcopy ((uint16_t *)&switch_start、(uint16_t *)&switch_end、(uint16_t *)&switch_ram_load);

    #endif
    #endif

    //初始化硬件抽象层
    halHandle = HAL_init (&hal、sizeof (hal));

    //检查用户参数中的错误
    USER_checkForErrors (&gUserParams);

    //将用户参数错误存储在全局变量中
    gMotorVars.UserErrorCode = USER_getErrorCode (&gUserParams);

    //如果存在用户参数错误,则不允许执行代码
    if (gMotorVars.UserErrorCode!= USER_ErrorCode_NoError)

    for (;;)

    gMotorVars.Flag_enableSys = false;

    //初始化用户参数
    USER_setParams (&gUserParams);

    //设置硬件抽象层参数
    HAL_setParams (halHandle、&gUserParams);

    ifdef Launchpad
    //将 GPIO 0和1设置为仅用于项目 lab1的输出。
    //这是 Launchpad 特有的、因为 PWM 通道也使用 LaunchPad 的 LED。
    HAL_setupLaunchPadGpio0and1 (halHandle);
    #endif


    //设置故障
    HAL_setupFaults (halHandle);


    //初始化中断矢量表
    HAL_initIntVectorTable (halHandle);


    //启用 ADC 中断
    HAL_enableAdcInts (halHandle);


    //启用全局中断
    HAL_enableGlobalInts (halHandle);


    //启用调试中断
    HAL_enableDebugInt (halHandle);


    //禁用 PWM
    HAL_disablePwm (halHandle);


    #ifdef DRV8301_SPI
    //打开 DRV8301 (如果存在)
    HAL_enableDrv (halHandle);
    //初始化 DRV8301接口
    HAL_setupDrvSpi (halHandle、&gDrvSpi8301Vars);
    #endif

    #ifdef DRV8305_SPI
    //打开 DRV8305 (如果有)
    HAL_enableDrv (halHandle);
    //初始化 DRV8305接口
    HAL_setupDrvSpi (halHandle、&G);
    #endif

    InitECANa();//初始化 eCAN-A 模块

    // EALLOW;

    /*将被测邮箱配置为发送邮箱*/

    // configureTransmitMailbox();
    // sTXCANMessage.ui32MsgID = 0x12345678;// CAN 消息 ID -使用1.
    // sTXCANMessage.ui32MsgIDMask=0x00000000;// TX 不需要掩码
    // sTXCANMessage.overWritePro=0;
    // sTXCANMessage.ui32MsgLen=8;
    //sTXCANMessage.ui32MsgLen = sizeof (ucTXMsgData);//消息大小为8
    //sTXCANMessage.pucMsgData = ucTXMsgData;// ptr 至消息内容
    //void configureAnyMailbox (uint32_t ui32ObjID、tCANMsgObject * pMsgObject、uint16_t 方向)
    //configureAnyMailbox (0、&sTXCANMessage、1);

    /*开始传输*/
    for (;;)

    switch (计数器)

    情况0:
    loopcount++;
    COUNTER++;
    中断;
    案例1:
    loopcount++;
    COUNTER++;
    中断;
    案例2:
    loopcount++;
    COUNTER++;
    中断;
    案例3:
    loopcount++;
    COUNTER++;
    中断;
    案例4:
    loopcount++;
    COUNTER++;
    中断;
    默认值:
    loopcount++;
    COUNTER++;
    中断;

    }// main()函数的末尾


    中断空 mainISR (空)

    //切换状态 LED
    if (++gLEDcnt >=(uint_least32_t)(5000/ LED_BLINK FREQ_Hz)
    {//USER_ISR_FREQ_Hz
    HAL_TOGLELed (halHandle、(GPIO_Number_e) HAL_GPIO_LED3);
    gLEDcnt = 0;

    //确认 ADC 中断
    HAL_acqAdcInt (halHandle、ADC_IntNumber_1);


    //转换 ADC 数据
    HAL_readAdcData (halHandle、&gAdcData);


    //此处显示 ADC 处理和 PWM 结果代码


    //写入 PWM 比较值
    HAL_writePwmData (halHandle、&gPwmData);


    返回;
    }// mainISR()函数结束

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    很抱歉、该代码、但特定的添加代码选项不适用于整个代码...
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    主席先生,你好,有什么建议?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    如果项目启用优化级别为2 (全局优化),则将优化并删除代码,因为“循环计数”不会在其他位置再次使用。

    您可以参阅以下代码、也可以使用"View"->"Disassembly"来查看最终的优化代码。

    计数器= 0;

    TestFlag = 0x8000;

    //用于任何循环
    while (TestFlag)

    TestFlag |=0x1000;

    switch (计数器)

    情况0:
    loopcount=10;
    COUNTER++;
    TestFlag |=0x0001;
    中断;
    案例1:
    loopcount=20;
    COUNTER++;
    TestFlag |=0x0002;
    中断;
    案例2:
    loopcount=30;
    COUNTER++;
    TestFlag |=0x0004;
    中断;
    案例3:
    loopcount=40;
    COUNTER++;
    TestFlag |=0x0008;
    中断;
    案例4:
    loopcount=50;
    COUNTER++;
    TestFlag |=0x0010;
    中断;
    默认值:
    循环数+=10;
    COUNTER++;
    TestFlag |=0x0100;
    中断;


    if (循环计数> 60)

    TestFlag |=0x0200;

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、先生、我刚刚尝试过您的代码在这种情况下情况更好、开关似乎以某种方式工作:正确递增计数器、正确递增循环计数、正确执行按位运算。

    但是、我尝试将永久循环更改为 while (1)、for (;)、在该配置中、它会再次停止工作。

    如何解决此问题?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您最好使用判断力的全局变量来实现它、因为您启用了全局优化级别。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢主席先生,现在一切似乎都在正常工作。 感谢您的支持、支持是我开始了解德州仪器微控制器的主要原因、我想没有人向客户提供这种类型的奉献、再次感谢先生。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、先生、

    你是对的。 如果您使用了 while (1)前的永远循环、则代码将在不执行的情况下进行优化。 如果您不想添加变量作为判断、我需要请求 CCS 编译器团队帮助来查看此问题。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、我只想使用我需要的变量、这是我担心这个问题的原因、因为 switch 语句被用于配置 eCAN 模块邮箱并通过 canbus 发送或恢复消息的函数中、 很明显、函数应该在一个永远循环中调用、我担心其中的奇怪行为。
    现在、我仅使用两种情况(对于2个邮箱)、似乎可以正常工作。
    但是,找到代码未执行的原因是很有用的,因为 while (1) forever 循环应该是这样的,并且是使代码正常运行的方法:)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我并不完全理解这里的一切。  但我非常确信需要使用变量限定符 volatile。  在任何变量上使用 volatile、这些变量可以在编译器看到的程序的常规范围之外进行更改。  示例包括可在中断期间或通过外设更改的任何变量。  请阅读有关 易失性的文章

    谢谢、此致、

    乔治