简体   繁体   English

无法打开或关闭绿色/蓝色LED STM32F429ZI-Nucleo板?

[英]Unable to on or off Green/BLUE LED STM32F429ZI - Nucleo board?

I am trying to write a bare metal program to blink green led. 我正在尝试编写一个裸机程序来使绿色LED闪烁。 In fact, I am unable to turn any LEDs on or off. 实际上,我无法打开或关闭任何LED。 This is an off-the-shelf board. 这是一个现成的板。 The board name is NUCLEO F429ZI. 板名是NUCLEO F429ZI。 Board Image 董事会形象

I have gone through the schematics and I am sure that the pin is PA5 ie Port A and pin number 5. However, the led isn't blinking at all. 我已经看过原理图,并且可以确定引脚是PA5即端口A和引脚号5。但是,LED根本没有闪烁。 I can see that my code is loaded onto STM32 board using uVision IDE. 我可以看到我的代码已使用uVision IDE加载到STM32板上。

I have tried setting blue LED ie PB7 but that also didn't work at all. 我曾尝试设置蓝色LED,即PB7,但那也没有用。

void delayMs(int delay);

int main(void)
{
    //enable clock access to A
    RCC->AHB1ENR |= 1;  //enable GPIO A clock
    GPIOA->MODER |= 0x400; //       PA-5 01   0000 - PA0
    while(1)
    {
          GPIOA->ODR |= 0x20;
         //delay
          delayMs(100);
          GPIOA->ODR &=~ 0x20;
          delayMs(100);
    }

}

void delayMs(int delay)
{
    int i = 0;
    for(; delay >0; delay--)
    {
     for(i=0; i<3195; i++)
        {
        }
    }
}

The green LED in the STM32F429ZI should blink. STM32F429ZI中的绿色LED应闪烁。

Next, I tried turning on the blue LED that is also not working. 接下来,我尝试打开也不起作用的蓝色LED。 As per my understanding by looking at schematics - PB7 should be turned on for blue LED. 根据我对原理图的了解-PB7应该为蓝色LED开启。 But this is also not working. 但这也不起作用。

#include "stm32f4xx.h"
int main(void)
{
    RCC->AHB1ENR |= 1;
    // ob 01 00 00 00 00 00 00 00 // PB7
    GPIOB->MODER = 0x4000;
    for(;;)
    {
        GPIOB->ODR = 0x80;
    }
}

Rather unhelpfully the Nucleo F429ZI UM1974 user manual download link at https://www.st.com/en/evaluation-tools/nucleo-f429zi.html#resource appears to be broken (at time of writing), but I have found a copy elsewhere , and the pin assignments of the three user LEDs is described thus: 相反,Nucleo F429ZI UM1974用户手册下载链接无益, 网址https://www.st.com/en/evaluation-tools/nucleo-f429zi.html#resource似乎已损坏(在撰写本文时),但我发现一个复制到其他位置 ,从而描述了三个用户LED的引脚分配:

在此处输入图片说明

The schematic suggests that the factory state of solder-bridges SB120 and SB119 are set for LD1 on PB0 rather then PA5. 该示意图表明,将焊桥SB120和SB119的出厂状态设置为PB0而不是PA5上的LD1。 The problem with your attempt to set LD2 (blue) is that you did not enable GPIOB in the RCC - it enables GPIOA as in the LD1(green) attempt. 尝试设置LD2(蓝色)的问题在于您没有在RCC中启用GPIOB-它像在LD1(绿色)尝试中一样启用了GPIOA。

Another issue is that your setting of GPIO MODER assumes that the reset state for the port is zero. 另一个问题是,您对GPIO MODER的设置假定该端口的重置状态为零。 That is not the case (although it is for the specific pins in question - so you "get away with it" in this case): 事实并非如此(尽管针对特定的引脚-在这种情况下,您可以“摆脱它” ):

在此处输入图片说明

It is a good idea to define all the port/pin specific constants in one place so you can switch or add outputs easily and with less chance of error: 在一个位置定义所有端口/引脚特定的常数是一个好主意,这样您就可以轻松切换或添加输出,并且出错的机会更少:

#define LED_PORT              GPIOB
#define LED_PORT_RCC_EN       0x2u 
#define GPIO_MODE_MASK       ~0x3u
#define GPIO_MODE_OUTPUT      0x1u

#define GREEN_LED_PIN         0u
#define BLUE_LED_PIN          7u
#define RED_LED_PIN           14u
#define FLASH_LED             GREEN_LED_PIN

int main(void)
{
    RCC->AHB1ENR |= LED_PORT_RCC_EN ;
    LED_PORT->MODER &= GPIO_MODE_MASK << (FLASH_LED << 1) ;
    LED_PORT->MODER |= GPIO_MODE_OUTPUT << (FLASH_LED << 1) ;

    for(;;)
    {
          LED_PORT->ODR |= 0x1 << FLASH_LED ;
          delayMs( 100 ) ;
          LED_PORT->ODR &= ~(0x1 << FLASH_LED) ;
          delayMs( 100 ) ;
    }

    return 0 ;
}

Your delay function is seriously flawed, and likely to be optimised out to "do nothing". 您的延迟功能存在严重缺陷,可能会进行优化以“不执行任何操作”。 Your loop counter needs to be declared volatile to avoid being optimised out. 您需要将循环计数器声明为volatile,以避免被优化。 If that happens, the indicator will not visibly blink but will be pulsed at a very high frequency and be on but not at full brightness. 如果发生这种情况,指示器将不会明显闪烁,但会以很高的频率脉动并亮起,但不会达到全亮度。

The following will prevent the loops being optimised out. 以下内容将防止循环被优化。

void delayMs( unsigned delay )
{
    for( volatile unsigned d = delay; d > 0; d--)
    {
        for( volatile int i = 0; i < 3195; i++ )
        {
        }
    }
}

However it is a 180MHz part; 但是,这是一个180MHz的部分。 if you are running it at full-speed 3195 iterations it will probably not take 1ms. 如果以全速3195迭代运行它,则可能不会花费1ms。 More like a few tens of microseconds. 更像是几十微秒。 Even if running at the start-up HSI frequency of 16MHz, it is likely to of the order of a few 100s of microseconds, and will in any case vary with optimisation settings and time spent in any interrupt handlers running. 即使以16MHz的启动HSI频率运行,它也可能达到几百微秒的数量级,并且在任何情况下都将随着优化设置和运行任何中断处理程序所花费的时间而变化。 Much better to use the Cortex-M SYSTICK counter as follows: 最好使用Cortex-M SYSTICK计数器,如下所示:

static volatile uint32_t ms_tick = 0 ;

void SysTick_Init(void) 
{
    SysTick_Config( SystemCoreClock / 1000 ) ;  
}

void SysTick_Handler(void)
{
    ms_tick++;
}

void delayMs( uint32_t delay)
{
    uint32_t start_tick = ms_tick ;
    while( (ms_tick - start_tick) < delay );
}

Then the delay will be accurate regardless of the clock speed you run your processor at or interrupt load. 这样,无论您在负载下运行处理器或中断负载的时钟速度如何,延迟都将是准确的。

You should not modify ODR directly as it does a read/write on the entire port. 您不应直接修改ODR,因为它会在整个端口上进行读/写操作。 Instead you should use the BSRR register where you can affect one bit only. 相反,您应该使用BSRR寄存器,该寄存器只能影响一位。 Note that some STM32 part uses a single 32-bit BSRR register to set and clear the bits (one operation is shifted 16 bit left) whereas others use two 16-bit registers so consult the reference manual or header file for details. 请注意,某些STM32部分使用单个32位BSRR寄存器来设置和清除这些位(一个操作向左移16位),而其他部分则使用两个16位寄存器,因此有关详细信息,请参考参考手册或头文件。

Your MODER setting is incorrect. 您的MODER设置不正确。 You need to clear the 2 bits for PA5 first, before OR'ing 01 in, eg 您需要先将PA5的2位清零,然后再对01进行“或”运算,例如

GOPIOA->MODER &= ~0b1100000000;
GPIOA->MODER |= 0b0100000000;
This is complete solution for Nucleo 144 - STM32F429ZI.

#include "stm32f4xx.h"

#define LED_PORT              GPIOB
#define LED_PORT_RCC_EN       0x2u 
#define GPIO_MODE_MASK       ~0x3u
#define GPIO_MODE_OUTPUT      0x1u

#define GREEN_LED_PIN         0u
#define BLUE_LED_PIN          7u
#define RED_LED_PIN           14u
#define FLASH_LED             BLUE_LED_PIN


void delayMs( unsigned delay );

int main(void)
{
    RCC->AHB1ENR |= LED_PORT_RCC_EN ; // enable for PORT B
    //LED_PORT->MODER &= GPIO_MODE_MASK << FLASH_LED ;
    //LED_PORT->MODER |= GPIO_MODE_OUTPUT << FLASH_LED ;
      GPIOB->MODER |= 0x4000;  // blue LED PB7
      GPIOB->MODER |= 0x1;  // green LED PB0
      GPIOB->ODR |= 0x1; // green LED ODR
      GPIOB->MODER |=  0x1 << 28; // red LED PB14
      GPIOB->ODR |= 0x1 <<14; // RED LED ODR
      //GPIOB->BSRR |= 0x4000; // 7th pin 
    // connected to pull up resistor -- when we press button , it goes low
        //B1 user button is connected to PC13 - i.e. blue button
      // Enable clock to PC13 i.e. Port C
      RCC->AHB1ENR |=  0x1 << 2;
      //GPIOC->MODER |=     //Input mode PC13- 13th pin 0
       // by default pins are input only
      GPIOC->MODER |=  0;
    for(;;)
    {
               // pressed blue button
               if( (GPIOC->IDR & (1<<13)) ) // PC13
                 {
                      LED_PORT->ODR |= 0x1 << FLASH_LED ;

                 }
                 else
                 {
            LED_PORT->ODR &= ~(0x1 << FLASH_LED) ;

                 }
    }

    return 0 ;
}

void delayMs( unsigned delay )
{
    for( volatile unsigned d = delay; d > 0; d--)
    {
        for( volatile int i = 0; i < 3195; i++ )
        {
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM