首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不能在STM32F4单片机上闪烁LED

不能在STM32F4单片机上闪烁LED
EN

Stack Overflow用户
提问于 2020-04-27 15:29:16
回答 3查看 2.7K关注 0票数 2

我想确保我已经设置了我的第一个嵌入式软件项目正确,因此,我试图眨眼我的核心-F411RE板(STM32F411RE微控制器)的发光二极管。我不使用任何IDE,因为我想从零开始做任何事情。我的项目结构如下。

代码语言:javascript
复制
├── build
│   ├── Buggy.bin
│   ├── Buggy.dis
│   ├── Buggy.elf
│   ├── Buggy.hex
│   ├── Buggy.map
│   ├── main.o
│   ├── startup_stm32f411xe.o
│   ├── stm32f4xx_it.o
│   └── system_stm32f4xx.o
├── lib
│   ├── cmsis
│   │   ├── include
│   │   │   ├── arm_common_tables.h
│   │   │   ├── arm_const_structs.h
│   │   │   ├── arm_math.h
│   │   │   ├── core_cm0.h
│   │   │   ├── core_cm0plus.h
│   │   │   ├── core_cm3.h
│   │   │   ├── core_cm4.h
│   │   │   ├── core_cm7.h
│   │   │   ├── core_cmFunc.h
│   │   │   ├── core_cmInstr.h
│   │   │   ├── core_cmSimd.h
│   │   │   ├── core_sc000.h
│   │   │   └── core_sc300.h
│   │   └── stm32f4xx
│   │       ├── stm32f4xx.h
│   │       └── system_stm32f4xx.h
│   ├── Makefile
│   └── STM32F4xx_StdPeriph_Driver
│       ├── include
│       │   ├── misc.h
│       │   ├── stm32f4xx_adc.h
│       │   ├── stm32f4xx_crc.h
│       │   ├── stm32f4xx_dbgmcu.h
│       │   ├── stm32f4xx_dma.h
│       │   ├── stm32f4xx_exti.h
│       │   ├── stm32f4xx_flash.h
│       │   ├── stm32f4xx_flash_ramfunc.h
│       │   ├── stm32f4xx_gpio.h
│       │   ├── stm32f4xx_i2c.h
│       │   ├── stm32f4xx_iwdg.h
│       │   ├── stm32f4xx_pwr.h
│       │   ├── stm32f4xx_rcc.h
│       │   ├── stm32f4xx_rtc.h
│       │   ├── stm32f4xx_sdio.h
│       │   ├── stm32f4xx_spi.h
│       │   ├── stm32f4xx_syscfg.h
│       │   ├── stm32f4xx_tim.h
│       │   ├── stm32f4xx_usart.h
│       │   └── stm32f4xx_wwdg.h
│       ├── libstdperiph.a
│       ├── Makefile
│       └── src
│           ├── misc.c
│           ├── misc.o
│           ├── stm32f4xx_adc.c
│           ├── stm32f4xx_adc.o
│           ├── stm32f4xx_crc.c
│           ├── stm32f4xx_crc.o
│           ├── stm32f4xx_dbgmcu.c
│           ├── stm32f4xx_dbgmcu.o
│           ├── stm32f4xx_dma.c
│           ├── stm32f4xx_dma.o
│           ├── stm32f4xx_exti.c
│           ├── stm32f4xx_exti.o
│           ├── stm32f4xx_flash.c
│           ├── stm32f4xx_flash.o
│           ├── stm32f4xx_flash_ramfunc.c
│           ├── stm32f4xx_flash_ramfunc.o
│           ├── stm32f4xx_gpio.c
│           ├── stm32f4xx_gpio.o
│           ├── stm32f4xx_i2c.c
│           ├── stm32f4xx_i2c.o
│           ├── stm32f4xx_iwdg.c
│           ├── stm32f4xx_iwdg.o
│           ├── stm32f4xx_pwr.c
│           ├── stm32f4xx_pwr.o
│           ├── stm32f4xx_rcc.c
│           ├── stm32f4xx_rcc.o
│           ├── stm32f4xx_rtc.c
│           ├── stm32f4xx_rtc.o
│           ├── stm32f4xx_sdio.c
│           ├── stm32f4xx_sdio.o
│           ├── stm32f4xx_spi.c
│           ├── stm32f4xx_spi.o
│           ├── stm32f4xx_syscfg.c
│           ├── stm32f4xx_syscfg.o
│           ├── stm32f4xx_tim.c
│           ├── stm32f4xx_tim.o
│           ├── stm32f4xx_usart.c
│           ├── stm32f4xx_usart.o
│           ├── stm32f4xx_wwdg.c
│           └── stm32f4xx_wwdg.o
├── main.c
├── main.h
├── Makefile
├── startup_stm32f411xe.s
├── stm32f4xx_conf.h
├── stm32f4xx_flash.ld
├── stm32f4xx_it.c
├── stm32f4xx_it.h
└── system_stm32f4xx.c

我使用STD_Periph库处理与实际硬件的接口,并使用CMSIS对实际处理器核心和外围设备进行硬件抽象(我认为)。

C源文件应该包含每秒钟在板上闪烁LED的代码。

代码语言:javascript
复制
#include "stm32f4xx.h"

void TimingDelay_Decrement(void);

static __IO uint32_t uwTimingDelay;
static void Delay(__IO uint32_t nTime);

int main(void) {

  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

  while (1) {
      GPIO_ToggleBits(GPIOD, GPIO_Pin_13);
      Delay(1000);
  }

}

void Delay(__IO uint32_t nTime)
{ 
  uwTimingDelay = nTime;

  while(uwTimingDelay != 0x00) {
    uwTimingDelay--;
  }
}

void TimingDelay_Decrement(void)
{
  if (uwTimingDelay != 0x00)
  { 
    uwTimingDelay--;
  }
}

当我使用Makefile使用make命令构建我的项目时,一切都成功了。然后运行make,这也成功地完成了。然而,没有一个LED闪烁每一秒。我不知道问题是什么,尤其是没有错误信息,所以我很难调试。我有一种感觉,它与Makefile或链接器脚本相关,所以我将把它们包括在下面。

Makefile:

代码语言:javascript
复制
# STM32F4-Discovery Makefile

C_SRC=$(wildcard *.c) \
$(wildcard src/*.c)
# Add assembly source files here or use $(wildcard *.s) for all .s files
S_SRC = $(wildcard *.s)

# Project name
PROJ_NAME = Buggy
OUTPATH = build

BINPATH = /usr/bin/
OUTPATH := $(abspath $(OUTPATH))
BASEDIR := $(abspath ./)
MKDIR_P = mkdir -p


###################################################

# Check for valid float argument
# NOTE that you have to run make clean after
# changing these as hardfloat and softfloat are not
# binary compatible
ifneq ($(FLOAT_TYPE), hard)
ifneq ($(FLOAT_TYPE), soft)
#override FLOAT_TYPE = hard
override FLOAT_TYPE = soft
endif
endif

###################################################

AS=$(BINPATH)arm-none-eabi-as
CC=$(BINPATH)arm-none-eabi-gcc
LD=$(BINPATH)arm-none-eabi-gcc
OBJCOPY=$(BINPATH)arm-none-eabi-objcopy
OBJDUMP=$(BINPATH)arm-none-eabi-objdump
SIZE=$(BINPATH)arm-none-eabi-size

LINKER_SCRIPT = stm32f4xx_flash.ld

CPU = -mcpu=cortex-m4 -mthumb

CFLAGS  = $(CPU) -c -std=gnu99 -g -O2 -Wall
LDFLAGS  = $(CPU) -mlittle-endian -mthumb-interwork -Wl,--gc-sections,-Map=$(OUTPATH)/$(PROJ_NAME).map,--cref --specs=nano.specs

ifeq ($(FLOAT_TYPE), hard)
CFLAGS += -fsingle-precision-constant -Wdouble-promotion
CFLAGS += -mfpu=fpv4-sp-d16 -mfloat-abi=hard
else
CFLAGS += -msoft-float
endif

# Default to STM32F411xE if no device is passed
ifeq ($(DEVICE_DEF), )
DEVICE_DEF = STM32F411xE
endif

CFLAGS += -D$(DEVICE_DEF)

vpath %.a lib

# Includes
INCLUDE_PATHS = -I$(BASEDIR)/lib/cmsis/stm32f4xx -I$(BASEDIR)/lib/cmsis/include -I$(BASEDIR)
INCLUDE_PATHS += -I$(BASEDIR)/lib/STM32F4xx_StdPeriph_Driver/include

# Library paths
LIBPATHS = -L$(BASEDIR)/lib/STM32F4xx_StdPeriph_Driver

# Libraries to link
LIBS = -lstdperiph -lc -lgcc -lnosys

OBJS = $(C_SRC:.c=.o)
OBJS += $(S_SRC:.s=.o)

###################################################

.PHONY: lib proj

all: dir lib proj
    $(SIZE) $(OUTPATH)/$(PROJ_NAME).elf

lib:
    $(MAKE) -C lib FLOAT_TYPE=$(FLOAT_TYPE) BINPATH=$(BINPATH) DEVICE_DEF=$(DEVICE_DEF) BASEDIR=$(BASEDIR)

proj: $(OUTPATH)/$(PROJ_NAME).elf

.s.o:
    $(AS) $(CPU) -o $(addprefix $(OUTPATH)/, $@) $<

.c.o:
    $(CC) $(CFLAGS) -std=gnu99 $(INCLUDE_PATHS) -o $(addprefix  $(OUTPATH)/, $@) $<

$(OUTPATH)/$(PROJ_NAME).elf: $(OBJS)
    $(LD) $(LDFLAGS) -T$(LINKER_SCRIPT) $(LIBPATHS) -o $@ $(addprefix $(OUTPATH)/, $^) $(LIBS) $(LD_SYS_LIBS)
    $(OBJCOPY) -O ihex $(OUTPATH)/$(PROJ_NAME).elf $(OUTPATH)/$(PROJ_NAME).hex
    $(OBJCOPY) -O binary $(OUTPATH)/$(PROJ_NAME).elf $(OUTPATH)/$(PROJ_NAME).bin
    $(OBJDUMP) -S --disassemble $(OUTPATH)/$(PROJ_NAME).elf > $(OUTPATH)/$(PROJ_NAME).dis

dir:
    $(MKDIR_P) $(OUTPATH)

clean:
    rm -f $(OUTPATH)/*.o
    rm -f $(OUTPATH)/$(PROJ_NAME).elf
    rm -f $(OUTPATH)/$(PROJ_NAME).hex
    rm -f $(OUTPATH)/$(PROJ_NAME).bin
    rm -f $(OUTPATH)/$(PROJ_NAME).dis
    rm -f $(OUTPATH)/$(PROJ_NAME).map
    # Remove the following line if you don't want to clean the Libraries as well
    $(MAKE) clean -C lib

flash:
    st-flash --reset write $(OUTPATH)/$(PROJ_NAME).bin 0x08000000

链接器脚本:

代码语言:javascript
复制
/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = 0x20020000;    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;;      /* required amount of heap  */
_Min_Stack_Size = 0x400;; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 512K
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
}

/* Define output sections */
SECTIONS
{
  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH

  /* The program code and other data goes into FLASH */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH

  /* Constant data goes into FLASH */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH

  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
  .ARM : {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } >FLASH

  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >FLASH
  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } >FLASH
  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >FLASH

  /* used by the startup to initialize data */
  _sidata = LOADADDR(.data);

  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data : 
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM AT> FLASH


  /* Uninitialized data section */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss secion */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM

  /* User_heap_stack section, used to check that there is enough RAM left */
  ._user_heap_stack :
  {
    . = ALIGN(4);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(4);
  } >RAM



  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

  .ARM.attributes 0 : { *(.ARM.attributes) }
}

编辑:

我已经安装了cubeMX并使用了它们生成的代码。然而,闪烁的LED仍然看不到。

以下是我在main.c文件中的主要方法:

代码语言:javascript
复制
int main(void)
{
  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  while (1) {
    // write pin state
    // NOTE: You can in turn use HAL_GPIO_TogglePin
    HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
    // synchronous delay for 500 ms
    HAL_Delay(500);
  }
}

我假设生成的代码工作正常,所以错误要么在我的main.c中,要么只是硬件问题。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-04-27 19:18:51

您不能从Nucleo-F411RE用户手册中切换正确的I/O:

用户LD2:绿色LED是根据STM32目标连接到与STM32 I/O PA5 (pin 21)或PB13 (pin 34)相对应的Arduino信号D13的用户LED。

D13 heare指的是Arduino连接器D13引脚--它的名称是为了与Arduino Shields兼容,而与STM32 GPIO引脚名无关。在您的例子中,它是PA5 (用户手册中的表16 )。

您的(原始)延迟功能存在根本缺陷。繁忙的循环延迟将取决于处理器的时钟速率,使用的编译器,甚至编译器使用的选项。但更重要的是,因为从1000减少将不需要明显的时间,这样的“闪烁”将是太快,无法用人的眼睛,甚至可能超过LED本身的开/关时间。

您应该使用硬件计时器或时钟源。所有Cortex-M设备都有一个SYSCLK,默认情况下它以系统时钟速率除以8运行。例如:

代码语言:javascript
复制
void delay_millisec(unsigned ms )
{
    unsigned ticks = (ms * (SystemCoreClock/ 8)) / 1000 ;

    SysTick->LOAD = ticks;
    SysTick->VAL = 0;
    SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;

    while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0);
    SysTick->CTRL = 0;
}

然后:

代码语言:javascript
复制
 while (1) 
  {
      GPIO_ToggleBits(GPIOD, GPIO_Pin_13);
      delay_millisec(500);
  }

会产生1Hz的闪速。

一个更复杂的解决方案是让SYSCLK增量为1ms间隔的滴答计数器,并有延迟函数计数经过的刻度间隔。例如,默认的HAL_delay()实现就是这样工作的。

票数 4
EN

Stack Overflow用户

发布于 2020-04-27 21:04:26

comments...this中的10行(更像是20行,或更多取决于您如何计数)的汇编代码程序。

使用STM32F411RE的NUCLEO-F411RE。

代码语言:javascript
复制
.cpu cortex-m7
.syntax unified
.thumb

stacktop: .word 0x20001000
.word reset

.thumb_func
reset:
/*
Address offset: 0x30
Reset value: 0x0000 0000
*/
    ldr r0,=0x40023830
    ldr r1,=0x00000001
    str r1,[r0]
/*
Address offset: 0x00
Reset value: 0xA800 0000 for port A
*/
    ldr r0,=0x40020000
    ldr r1,=0xA8000400
    str r1,[r0]

    add r0,#0x18
    ldr r1,=0x00000020
    ldr r2,=0x00200000

d0:
    str r1,[r0]
    mov r3,#0x00100000
d1:
    subs r3,#1
    bne d1

    str r2,[r0]
    mov r3,#0x00100000
d2:
    subs r3,#1
    bne d2

    b d0

我使用重置值而不是读-修改-写来保存一些指令/位置。

代码语言:javascript
复制
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m7 flash.s -o flash.o
arm-none-eabi-ld -Ttext=0x08000000 flash.o -o flash.elf
arm-none-eabi-ld: warning: cannot find entry symbol _start; defaulting to 0000000008000000
arm-none-eabi-objdump -d flash.elf > flash.list
arm-none-eabi-objcopy -O binary flash.elf flash.bin

_start不重要,可以添加这两行来让这个评论消失。

代码语言:javascript
复制
flash.elf:     file format elf32-littlearm


Disassembly of section .text:

08000000 <stacktop>:
 8000000:   20001000    .word   0x20001000
 8000004:   08000009    .word   0x08000009

08000008 <reset>:
 8000008:   480b        ldr r0, [pc, #44]   ; (8000038 <d2+0x6>)
 800000a:   f04f 0101   mov.w   r1, #1
 800000e:   6001        str r1, [r0, #0]
 8000010:   480a        ldr r0, [pc, #40]   ; (800003c <d2+0xa>)
 8000012:   490b        ldr r1, [pc, #44]   ; (8000040 <d2+0xe>)
 8000014:   6001        str r1, [r0, #0]
 8000016:   f100 0018   add.w   r0, r0, #24
 800001a:   f04f 0120   mov.w   r1, #32
 800001e:   f44f 1200   mov.w   r2, #2097152    ; 0x200000

08000022 <d0>:
 8000022:   6001        str r1, [r0, #0]
 8000024:   f44f 1380   mov.w   r3, #1048576    ; 0x100000

08000028 <d1>:
 8000028:   3b01        subs    r3, #1
 800002a:   d1fd        bne.n   8000028 <d1>
 800002c:   6002        str r2, [r0, #0]
 800002e:   f44f 1380   mov.w   r3, #1048576    ; 0x100000

08000032 <d2>:
 8000032:   3b01        subs    r3, #1
 8000034:   d1fd        bne.n   8000032 <d2>
 8000036:   e7f4        b.n 8000022 <d0>
 8000038:   40023830    .word   0x40023830
 800003c:   40020000    .word   0x40020000
 8000040:   a8000400    .word   0xa8000400

复制flash.bin到您的卡和led应该眨眼,因为它做了我的。

根据文档,D1是在Arduino PA5上,也就是D13连接F411RE和F401RE核心板的地方。(使用这个PCB的是其他核心产品上的PB13 )。如果您只读到了文档中提到的PB13或PA5,那么至少尝试其中一个,然后再尝试另一个。正如注释或答案所涵盖的那样,在gpio状态变化之间,您的延迟需要足够大,以便人眼看到,因此在其中放置一个很大的延迟。

代码语言:javascript
复制
mov r3,#0x00100000

更改这些r3行(如果它抱怨,则将其更改为ldr r3,#0xwhatever_you_want),以查看下一次构建时闪烁速率的变化。

代码语言:javascript
复制
mov r3,#0x00400000
票数 2
EN

Stack Overflow用户

发布于 2020-04-27 17:55:53

如果这是您的第一个项目-不要使用SPL (标准外设库)。它不再受STM的支持,也没有新的STM32 uCs库。安装cubeMX并使用此工具项目生成的启动。

在你修改的代码中你需要

HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_13);而不是HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61462419

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档