LED指示灯闪烁

时间:2019-06-10 17:18:31

标签: c microcontroller stm32

我正在对F401RE板进行编程,我试图通过按板上的按钮来切换LED的开/关。我使用的是低级方法,因为这是大学的功课,我无法使用高级库。

这是我所做的,但不起作用,led灯不动... 该代码应该是正确的,我缺少什么?

#include "stm32f4xx.h"
int main(void){

    int flag=0;
    //PORT REGISTERS
    volatile uint32_t *GPIOA_MODER = (uint32_t*) (0x40020000 + 0x00);
    volatile uint32_t *GPIOA_ODR = (uint32_t*) (0x40020000 + 0x14);
    volatile uint32_t *GPIOC_MODER = (uint32_t*) (0x40020000 + 0x0800 + 0x00);
    volatile uint32_t *GPIOC_IDR = (uint32_t*) (0x40020000 + 0x0800 + 0x10);

    //CLOCK REGISTERS
    volatile uint32_t *RCC_AHB1ENR = (uint32_t*) (0x40023800 + 0x30);

    *RCC_AHB1ENR |= 0x05U;

    *GPIOA_MODER = *GPIOA_MODER | 0x400;

    *GPIOC_MODER = *GPIOC_MODER | 0x0C000000;

    *GPIOA_ODR = *GPIOA_ODR | 0x20;

    // Application code (Infinite loop)
    while (1){

        if((((*GPIOC_IDR>>13) & 0x01) == 0x01)){
            flag=1;
        }else if((((*GPIOC_IDR>>13) & 0x01) == 0x00)  && flag==1){
            *GPIOA_ODR = *GPIOA_ODR ^ 0x20;
            flag=0;
        }
    }
}

2 个答案:

答案 0 :(得分:4)

警告:我不是是使用此特定MCU的专家。小心点。

this参考手册中提取的所有MCU寄存器信息。


无论如何,既然我已经完成了免责声明,那就让我们开始吧。

//Lines 16-20
...
*GPIOA_MODER = *GPIOA_MODER | 0x400;

*GPIOC_MODER = *GPIOC_MODER | 0x0C000000;

*GPIOA_ODR = *GPIOA_ODR | 0x20;
...

我相信这是包含错误的代码段。您将GPIOA_MODER5设置为使用通用输出模式,并将GPIOC_MODER13设置为使用模拟模式。再一次,这里不是专家,但是我认为应该将其设置为使用输入模式。不执行任何操作(因为端口C的重置值为0x00000000),或者使用*GPIOC_MODER = *GPIOC_MODER & ~(0x0C000000);显式重置寄存器的那部分。


在调试过程中,我重新格式化了您的代码,以符合我大学的编码标准以及我的个人喜好。这里是。

#include "stm32f4xx.h"

//Magic numbers are BAD. Use macros instead.
#define GPIOA_MEMOFFSET 0x40020000
#define GPIOC_MEMOFFSET 0x40020800
#define CLOCK_MEMOFFSET 0x40023800

//more macros. These are bit offsets for various registers.
#define GPIOC_MODER13 26
#define GPIOA_MODER5 10
#define GPIOC_IDR13 13
#define GPIOA_ODR5 5
#define RCC_AHB1ENR_GPIOAEN 0
#define RCC_AHB1ENR_GPIOCEN 1

int main(void)
{
    //Different compilers have different lengths for ints.
    //uint8_t is always 8 bits long.

    uint8_t flag=0;

    //This area has been width formatted to be easier to read. 
    //The compiler doesn't care about whitespace. See the macros at work?

    //PORT REGISTERS
    volatile uint32_t *GPIOA_MODER = (uint32_t*) (GPIOA_MEMOFFSET + 0x00);
    volatile uint32_t *GPIOA_ODR   = (uint32_t*) (GPIOA_MEMOFFSET + 0x14);
    volatile uint32_t *GPIOC_MODER = (uint32_t*) (GPIOC_MEMOFFSET + 0x00);
    volatile uint32_t *GPIOC_IDR   = (uint32_t*) (GPIOC_MEMOFFSET + 0x10);
    //CLOCK REGISTERS
    volatile uint32_t *RCC_AHB1ENR = (uint32_t*) (CLOCK_MEMOFFSET + 0x30);

    //No, it's not as concise as your version. But since all of this is constant,
    //any GOOD compiler will literally turn all that into a 5. It makes debugging
    //for other programmers easier to see what's actually going on. 
    *RCC_AHB1ENR |= (1 << RCC_AHB1ENR_GPIOAEN) | (1<<RCC_AHB1ENR_GPIOCEN); 

    //I turned every assignment operator into its equivalent boolean assignment.
    *GPIOA_MODER |= (0b01 << GPIOA_MODER5);
    *GPIOA_MODER &= ~(0b10 << GPIOA_MODER5);

    *GPIOC_MODER &= ~(0b11 << GPIOC_MODER13);

    *GPIOA_ODR = *GPIOA_ODR | (1 << GPIOA_ODR5);

    // Application code (Infinite loop)
    while (1)
    {
        //Lots of work here. C standard defines false as 0 and true as !false
        //so you're able to turn 'if (xx!=0)' into just 'if (xx)'
        //...usually. The rules get iffy when you do weird things. 
        if (*GPIOC_IDR & (1<<GPIOC_IDR13)) //AND masking IDR13.
        {
            flag=1;
        }
        else if(!(*GPIOC_IDR & (1<<GPIOC_IDR13)) && flag) //AND masking IDR13 again, but also boolean inverting the result. 
        {
            *GPIOA_ODR ^= (1<<GPIOA_ODR5);
            flag=0;
        }
    }
}

答案 1 :(得分:0)

您是否打算将端口引脚PC13用于按钮输入?将GPIOC_MODER与0x0C000000进行OR运算会将PC13设置为模拟模式。我认为您想要输入模式而不是模拟模式。输入模式是PC13的默认模式。因此,请尝试仅注释掉以下行。

<Style ...">
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Margin="5" Text="Save"/>
                    <Image Source="Resources\icons\save.png" Margin="5" 
                    Height="16" Width="16"></Image>
                </StackPanel>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>