通过设计一个基于stm32f407的流水灯完成6种以上的流水方式

img


至少完成6种以上的流水方式,通过按键完成选择类型,开始闪烁停止闪烁等。

  • 帮你找了个相似的问题, 你可以看下: https://ask.csdn.net/questions/7755989
  • 这篇博客你也可以参考下:STM32F407——流水灯
  • 除此之外, 这篇博客: 【STM32F103笔记】4、中断之外部中断——喂~烧水啦中的 中断服务程序(中断处理程序) 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 在USER文件夹下有stm32f10x_it.c文件,结尾的it即为interrupt的缩写,这个文件存放中断服务程序,打开文件可以看到里面已经有了一些默认的空函数,当需要用到这些中断功能时,就可以在相应的函数中写入对应的中断处理程序。

    在文件结尾,有:

    /**
      * @brief  This function handles PPP interrupt request.
      * @param  None
      * @retval None
      */
    /*void PPP_IRQHandler(void)
    {
    }*/
    

    这个被注释的函数PPP_IRQHandler(void)是提供给用户编写外设中断函数用的,比如我们接下来要写的外部中断函数,其中PPP并不能随意填写,这里的名称是和startup_stm32f10x_hd.s文件中设置好的异常向量标号一致的,了解汇编和单片机地址的朋友应该明白为什么,这里可以简要说明一下:

    • 单片机地址一般指的是其内部RAM的地址分配,就像上面的vector table图里一样,地址从0开始递增,在启动文件startup_stm32f10x_hd.s中,按照vector table中的顺序,将内部RAM前面一小部分的地址从0开始分别命名,这样标号__initial_sp就对应了RAM中的0x0000地址,Reset_Handler标号对应0x0004地址,依次类推;
    • 在汇编程序中,可以认为标号代表的就是其所在的地址;
    • 单片机或是处理器内核上电或者复位时,其程序运行指针PC会跳转指向一个固定的地址,一般为0x0000或者RAM开头的某个地址,然后从这个地址开始运行;
    • 而当进入中断(或者异常)时,PC又会跳转到固定的地址,也就是vector table中对应中断的地址,比如STM32某个中断通过它的中断路径,最后触发NVIC控制器的Hard Fault中断,这是PC指针会跳转到Hard Fault对应的地址,也就是图中的0x000C开始运行;
    • 而在启动文件startup_stm32f10x_hd.s中,将这个地址命名为了HardFault_Handler,这样,PC指针就会startup_stm32f10x_hd.s文件中标号为HardFault_Handler的后续程序:
    HardFault_Handler\
                    PROC
                    EXPORT  HardFault_Handler          [WEAK]
                    B       .
                    ENDP
    
    • 从而跳转到stm32f10x_it.c文件中的HardFault_Handler()函数,进入死循环(进入死循环是因为函数中默认的处理就是while(1)):
    /**
      * @brief  This function handles Hard Fault exception.
      * @param  None
      * @retval None
      */
    void HardFault_Handler(void)
    {
      /* Go to infinite loop when Hard Fault exception occurs */
      while (1)
      {
      }
    }
    

    因此,在startup_stm32f10x_hd.s文件中找到EXTI0对应的标号EXTI0_IRQHandler,在stm32f10x_it.c文件中写入中断处理函数,函数名即为标号,和上一篇一样,将LED取反就可以:

    /**
      * @brief  This function handles EXTI0(PA0) interrupt request.
      * @param  None
      * @retval None
      */
    void EXTI0_IRQHandler(void)
    {
    	BitAction status;
    	
    	if (EXTI_GetITStatus(EXTI_Line0) == SET)
    	{
    		status = (BitAction)(1-GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13));
    		GPIO_WriteBit(GPIOC, GPIO_Pin_13, status);
    		EXTI_ClearITPendingBit(EXTI_Line0);
    	}
    }