Предупреждение: я не эксперт с этим конкретным 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;
}
}
}