基于标准外设库的LED流水灯

一、MDK5 Keil5中使用标准固件的STM32工程的建立过程

1、下载STM32F10x标准外设库

在这里插入图片描述

  • 将下载好的压缩包解压到keil文件夹中保存。
    在这里插入图片描述

2、STM32工程建立

  • 首先新建工程文件夹,打开新建的工程文件夹,在文件夹中再新建以下文件夹
    在这里插入图片描述

  • 在CMSIS文件夹中新建startup文件夹,并存放已经下载完成的官方固件库中的如下文件
    在这里插入图片描述

    需要拷贝的文件位置为STM32F10x_StdPeriph_Lib_V3.5.0 > Libraries > CMSIS > CM3 > DeviceSupport >ST >STM32F10x
    在这里插入图片描述
    STM32F10x_StdPeriph_Lib_V3.5.0 > Libraries > CMSIS > CM3 > CoreSupport
    在这里插入图片描述

  • CMSIS > startup文件中存放启动文件,启动文件位于下载的压缩包中STM32F10x_StdPeriph_Lib_V3.5.0 > Libraries > CMSIS > CM3 > DeviceSupport >ST >STM32F10x > startup > arm
    在这里插入图片描述

  • Doc文件夹用于存放客户说明文件
    在这里插入图片描述

    文件位于STM32F10x_StdPeriph_Lib_V3.5.0 > Project > STM32F10x_StdPeriph_Template > TrueSTUDIO > STM3210B-EVAL
    在这里插入图片描述

  • Libraries文件夹存放库文件
    在这里插入图片描述

    在这里插入图片描述

    库文件位于STM32F10x_StdPeriph_Lib_V3.5.0 > Libraries > STM32F10x_StdPeriph_Driver
    在这里插入图片描述

  • Project文件夹用于存放自己建立的Keil5工程文件

  • User文件夹存放一部分STM32F10x_StdPeriph_Lib_V3.5.0 > Project > STM32F10x_StdPeriph_Template中的文件,并新建main.c文件
    在这里插入图片描述

3.新建Keil工程

  • 打开Keil5,点击Project新建工程,工程目录选择新建的Fwlib_Template > Project文件夹并设置工程文件名
    在这里插入图片描述

  • 选择STM32F103C8
    在这里插入图片描述

  • 直接关掉下一个弹窗,在工程建立后右击target1,选择Add Group,新建如下文件夹
    在这里插入图片描述

  • 双击文件夹添加文件
    在STARTUP文件夹中添加启动文件夹
    在这里插入图片描述

    在USER文件夹中添加main.csystem_stm32f10x.c
    在这里插入图片描述

    FWLIB文件夹中添加Libraries > incLibraries > src中的文件
    在这里插入图片描述

    同理将其他文件夹中的文件添加到工程中
    在这里插入图片描述

  • 添加完成后点击魔法棒,选择C/C++,在Define中添加宏定义USE_STDPERIPH_DRIVER,用于编译头文件#include"stm32f10x.h",之后如下图依次点击,将包含头文件的文件夹添加进来,可以让工程优先在添加进来的文件夹中搜索头文件,最后点击OK保存。
    在这里插入图片描述

二、基于标准外设库的LED流水灯

1、硬件设计

硬件仿真调试

2、软件设计

(1)编程思路
  1. 使能GPIO端口时钟;
  2. 初始化GPIO目标引脚为推挽输出模式;
  3. 编写程序控制GPIO引脚输出高、低电平。
(2)代码编写
  • 1.设置GPIO口时钟,处于使能状态
    在标准库函数中,只需要调用开启时钟的函数即可。在STM32中,调用APB2使能配置的函数为
    RCC_APB2PeriphResetCmd函数

    void RCC_APB2PeriphResetCmd(u32 RCC_APB2Periph, FunctionalState NewState) 
    

    第一个参数 uint32 RCC_APB2Periph,是指定的端口,我们这里使用GPIOA,故在主函数中写 RCC_APB2Periph_GPIOA。第二个参数是指定端口使能还是失能,我们选择使能,填上 ENABLE。对于A、B、C三个端口的完整调用如下:

     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    //使能PA,PB,PC端口时钟
    
  • 2.配置GPIO端口模式

    在GPIO端口配置中,有一个GPIO_Init函数,专门用来设置端口状态的。
    在这里插入图片描述

    void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
    

    第一个参数指定端口,我们填入GPIOA。第二个参数是一个结构体变量取地址。是结构体变量的声明,GPIO_InitStruct是结构体变量名。我们跳转GPIO_InitTypeDef定义如下

    typedef struct
    {
      uint16_t GPIO_Pin;
      GPIOSpeed_TypeDef GPIO_Speed;
      GPIOMode_TypeDef GPIO_Mode;
    }GPIO_InitTypeDef;
    

    可知结构体中含有三个参数。GPIO_Pin是指定具体引脚;GPIO_Mode是指定模式,也就是是输入还是输出,怎样输入输出。GPIO_Speed是指定输出的速度。

    设置结构体内参数时一定要按照结构体的格式规范写入,打开PA5,PB10,PC14引脚,设置为推挽输出模式,输出速度为50MHZ。最后调用GPIO_Init函数,配置完成。

    //定义一个GPIO_InitTypeDef类型的结构体
    GPIO_InitTypeDef  GPIO_InitStructure;
    //选择要控制的GPIO引脚	
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_5;				 //LED0-->PA4 端口配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;				 //LED1-->PB9 端口配置
    GPIO_Init(GPIOB, &GPIO_InitStructure);	  				 //推挽输出 ,IO口速度为50MHz
    GPIO_SetBits(GPIOB,GPIO_Pin_10);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;	    		 //LED2-->PC13 端口配置, 推挽输出
    GPIO_Init(GPIOC, &GPIO_InitStructure);	  				 //推挽输出 ,IO口速度为50MHz
    
  • 3.利用控制高低电平变化的函数实现流水灯

    使用GPIO_SetBits函数和GPIO_ResetBits函数设置端口引脚的高低电平

    void GPIO_SetBits(GPIO_TypeDef* GPIOx, u16 GPIO_Pin)
    

    在这里插入图片描述

    void GPIO_ResetBits(GPIO_TypeDef* GPIOx, u16 GPIO_Pin)
    

    在这里插入图片描述

  • 4.延时函数

    delay.h

    #ifndef __DELAY_H
    #define __DELAY_H
    #include "stm32f10x.h"       // Device header
    
    //Delay.h
    void Delay_us(uint32_t us);
    void Delay_ms(uint32_t ms);
    void Delay_s(uint32_t s);
    #endif
    

    delay.c

    #include "stm32f10x.h"
    //Delay.c
    /**
    * @brief  微秒级延时
    * @param  xus 延时时长,范围:0~233015
    * @retval 无
    */
    void Delay_us(uint32_t xus)
    {
      SysTick->LOAD = 72 * xus;				//设置定时器重装值
      SysTick->VAL = 0x00;					//清空当前计数值
      SysTick->CTRL = 0x00000005;				//设置时钟源为HCLK,启动定时器
      while(!(SysTick->CTRL & 0x00010000));	//等待计数到0
      SysTick->CTRL = 0x00000004;				//关闭定时器
    }
    
    /**
    * @brief  毫秒级延时
    * @param  xms 延时时长,范围:0~4294967295
    * @retval 无
    */
    void Delay_ms(uint32_t xms)
    {
      while(xms--)
      {
      	Delay_us(1000);
      }
    }
    
    /**
    * @brief  秒级延时
    * @param  xs 延时时长,范围:0~4294967295
    * @retval 无
    */
    void Delay_s(uint32_t xs)
    {
      while(xs--)
      {
      	Delay_ms(1000);
      }
    } 
    
  • 5.完整主函数

    main.c

    #include "stm32f10x.h"
    #include "delay.h"
    
    
    int main(void)
    { 
    
    
    //定义一个GPIO_InitTypeDef类型的结构体
    GPIO_InitTypeDef  GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    //使能PA,PB,PC端口时钟
    //选择要控制的GPIO引脚	
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;				 //LED0-->PA4 端口配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    //调用库函数初始化GPIO
    GPIO_Init(GPIOA, &GPIO_InitStructure);					 //根据设定参数初始化GPIOA4
    GPIO_SetBits(GPIOA,GPIO_Pin_5);						 //PA4 输出高
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;				 //LED1-->PB9 端口配置
    GPIO_Init(GPIOB, &GPIO_InitStructure);	  				 //推挽输出 ,IO口速度为50MHz
    GPIO_SetBits(GPIOB,GPIO_Pin_10);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;	    		 //LED2-->PC13 端口配置, 推挽输出
    GPIO_Init(GPIOC, &GPIO_InitStructure);	  				 //推挽输出 ,IO口速度为50MHz
    GPIO_SetBits(GPIOC,GPIO_Pin_14); 						 //PC13 输出高 
    while(1)
    {
    	    GPIO_ResetBits(GPIOA,GPIO_Pin_5);  //PA5拉低,亮
    		GPIO_SetBits(GPIOB,GPIO_Pin_10);  //PB10拉高,暗
    		GPIO_SetBits(GPIOC,GPIO_Pin_14);   //PC14拉高,暗
    		Delay_ms(300);  		   //延时300ms
    	
    	    GPIO_SetBits(GPIOA,GPIO_Pin_5);  //PA5拉高,暗
    		GPIO_ResetBits(GPIOB,GPIO_Pin_10);  //PB10拉低,亮
    		GPIO_SetBits(GPIOC,GPIO_Pin_14);   //PC14拉高,暗
    		Delay_ms(300);  		   //延时300ms
    	
    	   	GPIO_SetBits(GPIOA,GPIO_Pin_5);  //PA5拉高,暗
    		GPIO_SetBits(GPIOB,GPIO_Pin_10);  //PB10拉高,暗
    		GPIO_ResetBits(GPIOC,GPIO_Pin_14);   //PC14拉低,亮
    		Delay_ms(300);  		   //延时300ms
    
    }
    }  
    
(3)观察端口波形

在没有示波器条件下,可以使用Keil的软件仿真逻辑分析仪功能观察管脚的时序波形,更方便动态跟踪调试和定位代码故障点

  • 点开魔术棒,在Target中修改晶振为8.0MHZ
    在这里插入图片描述

  • 再点开Debug,修改以下选项
    在这里插入图片描述

  • 修改完成后,点击打开调试界面,然后打开逻辑分析仪
    在这里插入图片描述

  • 在逻辑分析仪的左上角有一个Set Up选项,点击它。
    在这里插入图片描述

  • 添加引脚

    在弹出的窗口中,我们新建观察引脚。添加完成后,一定要把每个的Display Type改成比特。

    快捷方式添加引脚
    输入PORTX.xx(X为A.B…;xx为引脚号,比如:PORTA.4)然后回车。

    在这里插入图片描述

  • 之后点击左上角运行图标
    请添加图片描述

  • 得到如下波形
    在这里插入图片描述

根据观察结果我们看到,波形都是连续变化的。PA5处LED灯先点亮,经过0.3s端口处电平由低变为高同时PB10的端口电平由高变低,LED灯点亮,每次端口的低电平持续时间为0.3s。

(4)硬件实现

四、参考资料

(1) STM32固件使用手册
(2) keil仿真和使用示波器调波形

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值