Светодиод мигает кнопкой - PullRequest
0 голосов
/ 10 июня 2019

Я программирую плату F401RE и пытаюсь включить / выключить светодиод нажатием кнопки на плате.Я использую низкоуровневый подход, потому что это домашняя работа в университете, и я не могу использовать библиотеки высокого уровня.

Это то, что я сделал, но он не работает, светодиод не работает ... Код долженбыть правым, чего мне не хватает?

#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 ]

4 голосов
/ 10 июня 2019

Предупреждение: я не эксперт с этим конкретным MCU.Будьте осторожны.

Вся информация о регистрах 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;
        }
    }
}
0 голосов
/ 10 июня 2019

Планируете ли вы использовать порт PC13 для входа кнопки? ORing GPIOC_MODER с 0x0C000000 устанавливает PC13 для аналогового режима. Я думаю, что вы хотите режим ввода вместо аналогового режима. Режим ввода по умолчанию для ПК13. Поэтому попробуйте закомментировать следующую строку.

//    *GPIOC_MODER = *GPIOC_MODER | 0x0C000000;
...