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.

[参考译文] 编译器/EK-TM4C123GXL:程序的一部分未按预期运行。 我需要添加无用的代码才能使其运行。

Guru**** 2457760 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/646955/compiler-ek-tm4c123gxl-a-part-of-the-program-does-not-run-as-expected-i-need-to-add-useless-code-in-order-to-make-it-run

器件型号:EK-TM4C123GXL

工具/软件:TI C/C++编译器

大家好。 我尝试构建这个简单的程序、在这个程序中、只要用户希望内置 LED 的切换间隔、就可以按住一个与引脚 PD2连接的按钮。 PD2配置为 WTIMER2B、内置 LED (PF3)由 TIMER0A 超时中断切换。

该按钮连接到下拉电阻器。 因此、我相信它不会浮动。

完整计划如下:

/*
blinky.c
*
创建时间:2017年11月30日
* 作者:Solomon Tan
*
需要连接:
* 无
*
*此代码的用途:使用 GPTM 输入边沿计时器切换内置 LED、以便在按下按钮的时间间隔内切换灯。
*
*/


#include 
#include 
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "driverlib/interrupt.h"
#include "inc/hw_ints.h"
#include "driverlib/pin_map.h"

#define "_dimetime1**#define /deltimetime1#define

#define #define _gimeintry23



;_time.h =_gimetc.h #define #define #define #define #include "intry23
//此 WTIMER2B 中断测量 PD2处于高电平的时间。
//测量的时间存储在变量 timeMeasured 中。
//*********
void edgeInputTimerInt (void){
TimerIntClear (WTIMER 2_base、TIMER_CAPB_EVENT);//确认信号边沿中断

uint32_t pinStatus = GPIOPinRead (GPIO_PORTD_base、GPIO_PIN_1)& 0x2;
if (pinStatus){
GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_3、GPIO_PIN_3);
} 否则{
//从计时器读取并存储在 var timeEnd 中
时间测量= TimerValueGet (WTIMEer2_base、TIMER_B);
isTimeMeasured = true;
GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_3、0x0);
}

}

//*********
//此 TIMER0A 中断在超时时切换内置 LED。
//超时取决于 Time Measured 设置的值。
//*********
void timer0A_timeout (void){
TimerIntClear (TIMER0_BASE、TIMER_TINA_TIMEOUT);

GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_3、0x8^(GPIOPinRead (GPIO_PORTF_BASE、GPIO_PIN_3)& 0x8));
TimerEnable (TIMER0_BASE、TIMER_A);
}


int main (void){

SysCtlClockSet (SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_16MHz | SYSCTL_OSC_MAIN);//将时钟设置为40MHz

SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);
while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOF));
GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_3 | GPIO_PIN_1);//将 PF1和 PF3设置为输出。 (实际上只需要 PF3作为我们的 LED)

SysCtlPeripheralEnable (SYSCTL_Periph_TIMER0);
while (!SysCtlPeripheralReady (SYSCTL_Periph_TIMER0));
TimerConfigure (TIMER0_BASE、TIMER_CFG_PERIODICURE);//配置为全宽度周期定时器。 单次触发只计算一次、并自动禁用计时器。
TimerIntRegister (TIMER0_BASE、TIMER_A、TIMER0A_TIMEOUT);

SysCtlPeripheralEnable (SYSCTL_Periph_GPIOD);
while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOD));

SysCtlPeripheralEnable (SYSCTL_Periph_WTIME2);
while (!SysCtlPeripheralReady (SYSCTL_Periph_WTIME2));


GPIOPinConfigure (GPIO_PD1_WT2CCP1);//将 PD1配置为宽 GPTM
GPIOPinTypeTimer (GPIO_PORTD_base、GPIO_PIN_1);//将 PD1配置为回显引脚-它触发计时器模块。
GPIOPinTypeGPIOOutput (GPIO_PORTD_base、GPIO_PIN_2);//将 PD2配置为触发输出。
TimerDisable (WTIMER 2_base、timer_B);//在配置前禁用计时器
TimerConfigure (WTIMER 2_base、TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_CAP_TIME_UP);// Timer B 是输入事件计时器。
TimerControlEvent (WTIMER 2_base、TIMER_B、TIMER_EVENT_BLE_PER边 沿);//将计时器(TimerB)配置为对两个边沿计时。
TimerIntClear (WTIMER 2_base、TIMER_CAPB_EVENT);//清除上次运行的任何杂散中断
TimerIntEnable (WTIMER 2_base、TIMER_CAPB_EVENT);//在信号边沿上生成中断
TimerIntRegister (WTIMER 2_base、TIMER_B、edgeInputTimerInt);//寄存器 echoPinTimerInt ()作为 WTimer 2B 的 ISR
TimerEnable (WTIMER 2_base、TIMER_B);//启用计时器
IntEnable (INT_WTIMEer2B);//为 WTimer 2B 启用 NVIC 中断
IntMasterEnable();

while (1){
如果(isTimeMeasured){//在 WTIMEER2B 中断成功测量 PD2引脚的高电平时间之后,我们启用 TIMER0并禁用 WTIMER2B,以便 LED 定期切换。 之后我们不再更改计时。
isTimeMeasured = false;
TimerLoadSet (TIMER0_BASE、TIMER_A、时间测量);
TimerEnable (TIMER0_BASE、TIMER_A);
TimerIntEnable (TIMER0_BASE、TIMER_TINA_TIMEOUT);
IntEnable (INT_TIMER0A);
GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_1、GPIO_PIN_1);
TimerDisable (WTIMER 2_base、Timer_B);
} 否则{//this block of code is 无用。 但是、我的程序仅在我添加到该其他块后才起作用。 如果没有它、即使通过 WTIMER 2B 中断将 isTimeMeasured 设置为 true、if (isTimeMeasured){...}也是如此 永不运行。
GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_1、0x0);
}
}


//

彩色 LED PortF
//暗 --0
//红色 R- 0x02
//蓝色 --B 0x04
//绿色-G- 0x08
//黄色 RG-0x0A
//天蓝色-GB 0x0C
//白色 RGB 0x0E
//粉色 R-B 0x06

//天蓝色-GB 0x0C
//白色 RGB 0x0E
//粉红色 R-B 0x06

我所面临的问题是代码的这一部分。   

while (1){
如果(isTimeMeasured){//在 WTIMEER2B 中断成功测量 PD2引脚的高电平时间之后,我们启用 TIMER0并禁用 WTIMER2B,以便 LED 定期切换。 之后我们不再更改计时。
isTimeMeasured = false;
TimerLoadSet (TIMER0_BASE、TIMER_A、时间测量);
TimerEnable (TIMER0_BASE、TIMER_A);
TimerIntEnable (TIMER0_BASE、TIMER_TINA_TIMEOUT);
IntEnable (INT_TIMER0A);
GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_1、GPIO_PIN_1);
TimerDisable (WTIMER 2_base、Timer_B);
} 否则{//this block of code is 无用。 但是、我的程序仅在我添加到该其他块后才起作用。 如果没有它、即使通过 WTIMER 2B 中断将 isTimeMeasured 设置为 true、if (isTimeMeasured){...}也是如此 永不运行。
GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_1、0x0);
}
} 

if (isTimeMeasured){...}中的代码块 如果我不包括其他{...}、则不会执行 i (不会执行一次)。 我不明白为什么。 我的 WTIMER2B 中断运行正常。 因此、isTimeMeasured 将在 PD2引脚的下降沿之后变为 true。

只要 isTimeMeasured 变为 true、则  if (isTimeMeasured){...}  应该执行、不应该执行? 我用 while (1){...}包装了该块 因此、程序将等待 WTIMEMER2B 中断将 isTimeMeasured 设置为 true。  

是否有人、或许有相同经验的人、与我分享这种情况的原因?  

如果我提供的信息不完整、请告诉我您需要的其他信息。 谢谢你。

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

    [引用用户="Solomon Tan ]_Bool isTimeMeasured = false;

    [引用用户="Solomon Tan ]/*********

    //此 WTIMER2B 中断测量 PD2处于高电平的时间。

    //测量的时间存储在变量 timeMeasured 中。

    //*********

    void edgeInputTimerInt (void){

       TimerIntClear (WTIMER 2_base、TIMER_CAPB_EVENT);

            //确认信号边沿中断

       uint32_t pinStatus = GPIOPinRead (GPIO_PORTD_base、GPIO_PIN_1)& 0x2;

       if (pinStatus){

             GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_3、GPIO_PIN_3);

            }

       否则{

            //从计时器读取并存储在 var timeEnd 中

           时间测量= TimerValueGet (WTIMEer2_base、TIMER_B);

           isTimeMeasured = true;

          GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_3、0x0);

          }

    }[/报价]

    请注意粗体

    [引用用户="Solomon Tan "] while (1){if (isTimeMeasured){

    [引用 user="Solomon Tan "]}否则{

        //此代码块无用。 但是、我的程序仅在我添加到该其他块后才起作用。 如果没有它、即使通过 WTIMER 2B 中断将 isTimeMeasured 设置为 true、if (isTimeMeasured){...}也是如此 永不运行。     

        GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_1、0x0);}[/QUERPE]

    首先、不使用其他器件:

    编译器可以自由地读取 isTimeMeasured 一次、因为它永远不会在 while 循环内的程序控制下发生更改。

    添加 else 后,您可以添加对编译器不解析*的函数的调用。 现在、编译器无法再假设 isTimeMeasured 不变(GPIOPinWrite 可能已经更改了它)、因此它必须在 while 中每次重新读取它。

    通常的解决方案是使 isTimeMeasured 具有易失性。 这是可行的,但重要的是要记住什么是不稳定的承诺,更重要的是,什么是不承诺。 volatile 保证每次访问变量的次数和写入的顺序都将相同。 不会多或少。 它不保证访问将是原子的。 它不保证不会移动或优化非易失性访问。

    Robert

    *注意:这意味着如果编译器能够指示 GPIOPinWrite 不修改 isTimeMeasured、则可以自由地不再次读取它。 另请注意、编译器的视图是永远不会调用中断、因为在 while 循环中从未引用中断。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢 Robert 的帮助! 添加 volatile 可以解决我的问题。 我不能相信我忽略了它。 我现在把头发撕开了,哈哈。