STM32——LED控制

1、Keil uVision4 MDK-ARM 设置

当前 ST 公司正在力推STM32Cube(HAL & LL)固件库,但是出于使用习惯,这里依然选择了STM32 Standard Peripheral Libraries标准固件库来编写实验代码,新建一个stm 工程文件夹,并添加CMSIS、Lib、Startup、User四个子文件夹。
  A、将STM32F10x_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x目录下的stm32f10x.h、system_stm32f10x.c、system_stm32f10x.h三个文件,以及STM32F10x_V3.5.0\Libraries\CMSIS\CM3\CoreSupport目录下的所有文件复制到刚才新建的CMSIS目录下;
  B、然后进入STM32F10x_V3.5.0\ Libraries\ CMSIS\CM3 \DeviceSupport \ST\ ST M32 F10x\startup\arm目录将所有文件复制到刚才新建的Startup目录;
  C、接下来再将STM32F10x_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver目录下的src和inc两个子文件夹拷贝到刚才新建的Lib目录;
  D、最后将STM32F10x_V3.5.0\Project\STM32F10x_StdPeriph_Template目录下的main.c、stm32f10x_conf.h、stm32f10x_it.c、stm32f10x_it.h四个文件拷贝至刚才新建的User目录;
  E、完成 STM32 官方标准库文件的拷贝与复制之后,还需要对 Keil uVision 进行相应设置。首先新建一个【New uVision Project】,将CMSIS目录下的 2 个.c文件全部添加至 Keil uVision 项目的CMSIS组,然后将Lib\src目录下的所有文件添加至Lib组,将Startup目录下的startup_stm32f10x_md.s汇编文件添加至Startup组,最后将User下的 2 个.c文件添加至User组,最后保存退出,然后在【C/C++】选项卡下的【 Prepro cessor Symbols】 内的【Define】输入框内填入USE_STDPERIPH_ DRIVER, STM32F10X_ MD。最后点击【Include Paths】左侧的添加按钮,把刚才新建的那些文件夹逐一选入。
 STM32——LED控制_第1张图片
STM32——LED控制_第2张图片
STM32——LED控制_第3张图片
官方库文件添加完毕之后,还需要新建Basic和Hardware两个目录来放置开发人员编写的代码,同样按照以上步骤将其添加至 Keil uVision 开发环境当中,至此项目中所有目录的功能说明如下:
CMSIS:内核驱动程序;
Lib:内部功能基本函数库;
Startup:汇编编写的启动程序;
User:用户主函数以及其它用户程序;
Basic:内部功能驱动函数;
Hardware:外部硬件驱动函数;
也可加入.txt作为增加程序的说明使用。

接下来进一步对 Keil uVision 进行一些初始化的设置,这里首先设置【Target】选项卡下面的外部晶振频率为8.0 MHz,然后勾选【Output】选项卡下的Create HEX File。

2、点亮LED

作为一个无51经验的菜鸟,直接上手STM32确实感到很吃力,各种教程都是把点灯作为实操单片机的第一步也是最简单的一步。实现这一功能也是初步学习配置GPIO,下面就库函数详细说明如何实现这一功能。以洋桃电子开发板为例,所控的两个LED灯与GPIOB_Pin0与Pin1引脚连接,LED1灭,LED2亮。

/*GPIO初始化*/
void GPIO_Configuration(void)

{
      GPIO_InitTypeDef GPIO_InitStructure;  //定义一结构体函数

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;

      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

      GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/* 配置系统时钟,使能各外设时钟*/

  #include "stm32f10x.h"
 void RCC_Configuration(void)

{

       SystemInit(); 

       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB

                           | RCC_APB2Periph_GPIOC, ENABLE );
}
/* main函数*/
int main(void)
{ 
       Init_All_Periph();
       while(1)
      {

           GPIO_ResetBits(GPIOB, GPIO_Pin_0);
		   GPIO_SetBits(GPIOB, GPIO_Pin_1);

	  }
}

以上为对LED亮灭的基础控制。
下面就实现多种LED功能示例介绍:(.h文件为方便程序编写的声明,在添加文件中加入.h文件,编译一下即可编写)
main.c

/** User/main.c */
#include "delay.h"
#include "led.h"
#include "stm32f10x.h"
#include "sys.h"

int main(void) {
  RCC_Configuration(); // 时钟设置
  LED_Init();

  while (1) {
    /** 方式 1
      typedef enum {
        Bit_RESET = 0,
        Bit_SET
      } BitAction; // 位于 stm32f10x_gpio.h
    */
    GPIO_WriteBit(LEDPORT, LED1, (BitAction)(1)); // LED1 输出高电平 1

    delay_us(50000);                              // 延时 1 秒
    GPIO_WriteBit(LEDPORT, LED1, (BitAction)(0)); // LED1 输出低电平 0
    delay_us(50000);                              // 延时 1 秒

    /** 方式 2 */
    GPIO_WriteBit(LEDPORT, LED1, (BitAction)(1 - GPIO_ReadOutputDataBit(LEDPORT, LED1))); // 取反 LED1
    delay_ms(500);                                                                        // 延时 1 秒

    /** 方式 3 */
    GPIO_SetBits(LEDPORT, LED1);   // LED 置为高电平 1
    delay_s(1);                    // 延时 1 秒
    GPIO_ResetBits(LEDPORT, LED1); // LED 重置为低电平 0
    delay_s(1);                    // 延时 1 秒

    /** 方式 4 */
    GPIO_Write(LEDPORT, 0x0001); // 将 32 位状态值写入整组 GPIO
    delay_s(2);                  // 延时 1 秒
    GPIO_Write(LEDPORT, 0x0000); // 将 32 位状态值写入整组 GPIO
    delay_s(2);                  // 延时 1 秒
  }
}

LED.h 声明头文件

/** Hardware/LED/led.h */

#ifndef __LED_H
#define __LED_H
#include "sys.h"

/*
  // 通过 PXout() 函数直接操作 GPIO 底层寄存器
  #define LED1 PBout(0) // 直接操作 PB0,使用方式:LED1 = 0
  #define LED2 PBout(1) // 直接操作 PB1,使用方式:LED2 = 1
*/

#define LEDPORT GPIOB   // 定义 GPIOB
#define LED1 GPIO_Pin_0 // 定义 GPIO_Pin_0
#define LED2 GPIO_Pin_1 // 定义 GPIO_Pin_1

void LED_Init(void); // 初始化

#endif

delay.h

/** Basic/delay/delay.h */
#ifndef __DELAY_H
#define __DELAY_H
#include "sys.h"

void delay_s(u16 s);
void delay_ms(u16 ms);
void delay_us(u32 us);
#endif

LED.c 四种控制程序

/** Hardware/LED/led.c */
#include "led.h"

/*  LED 初始化函数 */
void LED_Init(void) {
  /*
    typedef struct {
      uint16_t GPIO_Pin;            // GPIO 编号
      GPIOSpeed_TypeDef GPIO_Speed; // GPIO 速度
      GPIOMode_TypeDef GPIO_Mode;   // GPIO 模式
    } GPIO_InitTypeDef;
  */
  GPIO_InitTypeDef GPIO_InitStructure; // GPIO 初始化参数结构体的声明

  /* AHB 外设时钟使能 */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);

  /* GPIO 初始化参数结构体 */
  GPIO_InitStructure.GPIO_Pin = LED1 | LED2; // 选择 GPIO 编号(0~15 / all)

  /*
    GPIO_Mode_AIN 模拟输入       GPIO_Mode_IN_FLOATING 浮空输入     GPIO_Mode_IPD 下拉输入
    GPIO_Mode_IPU 上拉输入       GPIO_Mode_Out_PP 推挽输出          GPIO_Mode_Out_OD 开漏输出
    GPIO_Mode_AF_PP 复用推挽输出  GPIO_Mode_AF_OD 复用开漏输出
  */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  // 选择 GPIO 工作模式为推挽输出

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 设置 GPIO 接口速度(2MHz / 10MHz / 50MHz)

  GPIO_Init(LEDPORT, &GPIO_InitStructure); // 运行 GPIO 初始化库函数,将设置写入寄存器
}

delay.c 延时函数模板,s/ms/μs

/** Basic/delay/delay.c
 * 基于系统时基定时器SysTick的延时函数,出于性能考量,采用了寄存器操作实现,并未使用库函数。
 * */
#include "delay.h"

#define AHB_INPUT 72 // RCC 里设置的 AHB 时钟频率,单位为 MHz

/* 微秒 us 级延时,参数最大值为 233015 */
void delay_us(u32 uS) {
  SysTick->LOAD = AHB_INPUT * uS;        // 计数器重装初值,当前频率为 72MHz,即 72 次为 1us
  SysTick->VAL = 0x00;                   // 定时器计数器清零
  SysTick->CTRL = 0x00000005;            // 时钟源 HCLK,打开定时器
  while (!(SysTick->CTRL & 0x00010000)); // 等待计数值归 0
  SysTick->CTRL = 0x00000004;            // 关闭定时器
}

/* 毫秒 ms 级延时,参数最大值为 65535 */
void delay_ms(u16 ms) {
  while (ms-- != 0) {
    delay_us(1000); // 调用 1000us 延时函数
  }
}

/* 秒 s 级延时,参数最大值为 65535 */
void delay_s(u16 s) {
  while (s-- != 0) {
    delay_ms(1000); // 调用 1000ms 延时函数
  }
}

3、LED 呼吸灯

这里涉及视觉中帧的概念,通过调整LED灯中一周期高低电平的占空比(即一周期内高低电平所占的时间)来实现对LED灯亮度的控制。同时通过for循环来控制亮度变化的速率。其他与上雷同,仅改变主程序:
mian.c

/** User/main.c */

#include "delay.h"
#include "led.h"
#include "stm32f10x.h"
#include "sys.h"

int main(void) {
  /* 变量定义 */
  u8 MENU;
  u16 t, i;

  /* 初始化程序 */
  RCC_Configuration(); // 时钟设置
  LED_Init();
  MENU = 0; // 设置初始值
  t = 1;

  while (1) {
    /* 变亮循环 */
    if (MENU == 0) {
      for (i = 0; i < 10; i++) {
        GPIO_WriteBit(LEDPORT, LED1, (BitAction)(1)); // LED1 输出高电平 1
        delay_us(t);                                  // 延时
        GPIO_WriteBit(LEDPORT, LED1, (BitAction)(0)); // LED1 输出低电平 0
        delay_us(501 - t);                            // 延时
      }
      t++;
      if (t == 500) {
        MENU = 1;                                     // 切换至变暗循环
      }
    }

    /* 变暗循环 */
    if (MENU == 1) {
      for (i = 0; i < 10; i++) {
        GPIO_WriteBit(LEDPORT, LED1, (BitAction)(1)); // LED1 输出高电平 1
        delay_us(t);                                  // 延时
        GPIO_WriteBit(LEDPORT, LED1, (BitAction)(0)); // LED1 输出低电平 0
        delay_us(501 - t);                            // 延时
      }
      t--;
      if (t == 1) {
        MENU = 0;                                     // 切换至变亮循环
      }
    }
  }
}

你可能感兴趣的:(stm32)