如果不是 "halting clock cycles",则 TM4C123 上的 LED 闪烁失败

LED blinking on TM4C123 fails if not "halting clock cycles"

我正在按照 this tutorial 学习嵌入式系统。在他们附加的用于 TM4C123 上 LED 闪烁的代码中,他们创建了变量 ulLoop 这让我感到困惑,因为他们只是将点击启用字节分配给 ulLoop 但之后从未使用过它。但是,我尝试删除写 ulLoop = SYSCTL_RCGCGPIO_R; 的行并且 LED 停止闪烁,正如他们在教程中所说的那样“uloop 变量和包含 uloop 的语句存在于那里,只是为了在移动到外围设备之前停止 3 个时钟周期,这是使用 TIVA 时必须的。"

我不明白他们所说的“停止 3 个时钟周期”和“移动到外围设备”是什么意思,以及为什么它需要停止 3 个时钟周期,而不是 4 或 5 个周期,或者根本不需要。此外,如果我对教程中提到的有关魔术变量的内容一无所知,只是发现程序无法运行,那么在没有更多信息的情况下我应该如何知道问题出在哪里,因为在构建过程中没有错误和警告。如果问题没有以正确的方式提出或听起来很愚蠢,请原谅我。

#define SYSCTL_RCGCGPIO_R (*(( volatile unsigned long *)0x400FE608 ) )
#define GPIO_PORTF_DATA_R (*(( volatile unsigned long *)0x40025038 ) ) 
#define GPIO_PORTF_DIR_R  (*(( volatile unsigned long *)0x40025400 ) ) 
#define GPIO_PORTF_DEN_R  (*(( volatile unsigned long *)0x4002551C ) )

#define GPIO_PORTF_CLK_EN  0x20
#define GPIO_PORTF_PIN1_EN 0x02
#define LED_ON1        0x02
#define GPIO_PORTF_PIN2_EN 0x04
#define LED_ON2        0x04
#define GPIO_PORTF_PIN3_EN 0x08
#define LED_ON3        0x08

#define DELAY_VALUE   1000000
volatile unsigned long j=0; 
static void Delay(void){
    for (j=0; j<DELAY_VALUE ; j++);
}


int main ( void )
{
volatile unsigned long ulLoop ;          // I don't understand why creating this variable
SYSCTL_RCGCGPIO_R |= GPIO_PORTF_CLK_EN ;
ulLoop = SYSCTL_RCGCGPIO_R;              // But if not adding this line the LED won't blink
GPIO_PORTF_DIR_R |= GPIO_PORTF_PIN1_EN ;
GPIO_PORTF_DEN_R |= GPIO_PORTF_PIN1_EN ;    
GPIO_PORTF_DIR_R |= GPIO_PORTF_PIN2_EN ;
GPIO_PORTF_DEN_R |= GPIO_PORTF_PIN2_EN ;
GPIO_PORTF_DIR_R |= GPIO_PORTF_PIN3_EN ;
GPIO_PORTF_DEN_R |= GPIO_PORTF_PIN3_EN ;
        
// Loop forever . 
        while (1) 
        {  
            GPIO_PORTF_DATA_R &= LED_ON3;
            GPIO_PORTF_DATA_R &= LED_ON2;
            GPIO_PORTF_DATA_R |= LED_ON1;
            Delay();
            GPIO_PORTF_DATA_R &= LED_ON1;
            GPIO_PORTF_DATA_R &= LED_ON2;
            GPIO_PORTF_DATA_R |= LED_ON3;   
            Delay();
            GPIO_PORTF_DATA_R &= LED_ON3;
            GPIO_PORTF_DATA_R &= LED_ON1;
            GPIO_PORTF_DATA_R |= LED_ON2;
            Delay();
                
        }
}

因为上一行

SYSCTL_RCGCGPIO_R |= GPIO_PORTF_CLK_EN ;

程序正在启用时钟,这一行

ulLoop = SYSCTL_RCGCGPIO_R; 

只是一个虚拟代码,它为微控制器时钟提供了一点时间来稳定。

你会发现这对你将要使用的任何微控制器都有效,在时钟设置后你必须留出一些时间让时钟稳定。

现在,为什么是 3 个时钟周期?您在阅读微控制器数据表时应该找到此信息,其中应指定稳定时钟需要多少个时钟周期?

为什么不是 5 个或更多?当然,你不想在这个操作中浪费这么多的时钟周期,所以程序的其余部分可以尽快执行。

这条虚拟线如何对应3个时钟周期?

ulLoop = SYSCTL_RCGCGPIO_R; 

好吧,这在一个控制器与另一个控制器之间或更具体地说,在编译器与另一个控制器之间确实是不同的。编译器确实将此 C 代码行翻译成汇编代码。每条装配线需要一个时钟周期来执行。所以看起来无论是谁编写这段代码,只要查看编译器生成的汇编代码,就会发现这一行被翻译成 3 条汇编指令。

how am I supposed to know where the problem is without further information

在嵌入式系统世界中,这可以通过调试来实现。有些问题真的很难调试,尤其是当它出现在控制器初始化序列中时。 按照数据表 instructions/recommendations.

初始化控制器(时钟、外围设备)时,您应该非常小心