STM32入门教程(一):使用标准库函数实现流水灯效果

一、实验原理

1.STM32VET6简介

STM32F103VET6是一款由意法半导体公司(ST)推出的基于Cortex-M3内核的32位微控制器,硬件采用LQFP48封装,属于ST公司微控制器中的STM32系列。

1.1 简要说明:

该款芯片 为 100引脚 , 512KFlash 64kSRAM LQFP 封装 32位 Cortex内核

内核 Cortex-M3
Flash 512K×8bit
SRAM 64K×8bit
GPIO 80个
ADC 12位 ADC 三路 共有 16个通道
CPU 72MHz
通讯方式 两个SPI,两个I2C,五个USART, 一个USB,一个CAN通信,一个SDIO
Timer 4个通用定时器 ,两个高级定时器,两个基本定时器

1.2 STM32各GPIO口介绍

GPIO分为七个部分:
1、保护二极管及上、下拉电阻:保护二级管可以防止引脚外部过高或过低的电压输入
2、P-MOS 管和N-MOS 管:控制推挽输出和开漏输出
3、输出数据寄存器:由输出数据寄存器GPIOX_ODR
4、复用功能输出:STM32 的其它片上外设对GPIO 引脚进行控制
5、输入数据寄存器:存储输入数据寄存器GPIOx_IDR
6、复用功能输入:GPIO 引脚的信号传输到STM32 其它片上外设
7、模拟输入输出:用于ADC 采集电压的输入通道
(原文链接:https://blog.csdn.net/xiaoxiaodawei/article/details/105834406)

二、实验步骤

1.时钟使能

流水灯操作的引脚位于GPIO端口,由下图可知AHB总线包含RCC时钟控制,GPIO是属于APB2的。需要使用的端口的复位和时间控制受RCC控制

2.寄存器地址设置

1. 设置亮灯的高电平输出

2. 设置灭灯的低电平输出

3. 反转输出电平

3.延时函数

        程序执行指令的速度是很快的,若需要将灯的亮灭以及颜色的切换让人眼可观就需要设置延时函数。延时函数的延时时间跟stm32的晶振频率有关,程序执行指令需要一定时间,以此可以设计一个简单的延时函数。

        而这种死循环方式的延时函数是没办法精确控制延时时间长短, 只是大概的延时时间,所以基本上都是通过不断修改输入参数大小然后下载到开发板上看实验效果。

static void Delay(uint32_t time)
{
  uint32_t i,j;

  for(i=0;i<time;++i)
  {
    for(j=0;j<10000;++j)
    {       
      //空循环        
    }
  }
}

三、实操代码

程序分为3个文件:bsp_led.c、bsp_led.h、main.c

1.bsp_led.c


/* 包含头文件 ----------------------------------------------------------------*/
#include "bsp/led/bsp_led.h"
/**
  * 函数功能: 板载LED灯IO引脚初始化.
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:使用宏定义方法代替具体引脚号,方便程序移植,只要简单修改bsp_led.h
  *           文件相关宏定义就可以方便修改引脚。
  */
void LED_GPIO_Init(void)
{
  /* 定义IO硬件初始化结构体变量 */
  GPIO_InitTypeDef GPIO_InitStructure;
	
  /* 使能(开启)LED引脚对应IO端口时钟 */  
  RCC_APB2PeriphClockCmd(LED1_RCC_CLOCKGPIO|LED2_RCC_CLOCKGPIO |LED3_RCC_CLOCKGPIO , ENABLE);
  
  /* 设定LED对应引脚IO最大操作速度 :GPIO_Speed_50MHz */
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  /* 设定LED对应引脚IO为输出模式 */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
	
  /* 设定LED1对应引脚IO编号 */
  GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN; 
  /* 初始化LED1对应引脚IO */
  GPIO_Init(LED1_GPIO, &GPIO_InitStructure);
 
  /* 设定LED2对应引脚IO编号 */
  GPIO_InitStructure.GPIO_Pin = LED2_GPIO_PIN;  
  /* 初始化LED2对应引脚IO */
  GPIO_Init(LED2_GPIO, &GPIO_InitStructure);

  /* 设定LED3对应引脚IO编号 */
  GPIO_InitStructure.GPIO_Pin = LED3_GPIO_PIN;  
  /* 初始化LED3对应引脚IO */
  GPIO_Init(LED3_GPIO, &GPIO_InitStructure);

}

2.bsp_led.h

#ifndef __BSP_LED_H__
#define __BSP_LED_H__

/* 包含头文件 ----------------------------------------------------------------*/
#include <stm32f10x.h>

/* 类型定义 ------------------------------------------------------------------*/
typedef enum
{
  LED_OFF = 0,
  LED_ON,
}LEDState_TypeDef;
#define IS_LED_STATE(STATE)           (((STATE) == LED_OFF) || ((STATE) == LED_ON))

/* 宏定义 --------------------------------------------------------------------*/
#define LED1                          (uint8_t)0x01
#define LED2                          (uint8_t)0x02
#define LED3                          (uint8_t)0x04
#define IS_LED_TYPEDEF(LED)           (((LED) == LED1) || ((LED) == LED2) || ((LED) == LED3))

/*
 * 以下宏定义内容跟开发板硬件息息相关,需要查看开发板电路原理图才能正确编写。
 */

#define LED1_RCC_CLOCKGPIO            RCC_APB2Periph_GPIOA
#define LED1_GPIO_PIN                 GPIO_Pin_8
#define LED1_GPIO                     GPIOA


#define LED2_RCC_CLOCKGPIO            RCC_APB2Periph_GPIOA
#define LED2_GPIO_PIN                 GPIO_Pin_11
#define LED2_GPIO                     GPIOA


#define LED3_RCC_CLOCKGPIO            RCC_APB2Periph_GPIOA
#define LED3_GPIO_PIN                 GPIO_Pin_12
#define LED3_GPIO                     GPIOA

#if 1         /* 直接操作寄存器方法 */

#define LED1_ON                      {LED1_GPIO->BRR=LED1_GPIO_PIN;}   //输出高电平
#define LED1_OFF                       {LED1_GPIO->BSRR=LED1_GPIO_PIN;}    //输出低电平
#define LED1_TOGGLE                   {LED1_GPIO->ODR ^=LED1_GPIO_PIN;}  //输出反转

#define LED2_ON                      {LED2_GPIO->BRR=LED2_GPIO_PIN;}   //输出高电平
#define LED2_OFF                       {LED2_GPIO->BSRR=LED2_GPIO_PIN;}    //输出低电平
#define LED2_TOGGLE                   {LED2_GPIO->ODR ^=LED2_GPIO_PIN;}  //输出反转

#define LED3_ON                      {LED3_GPIO->BRR=LED3_GPIO_PIN;}   //输出高电平
#define LED3_OFF                       {LED3_GPIO->BSRR=LED3_GPIO_PIN;}    //输出低电平
#define LED3_TOGGLE                   {LED3_GPIO->ODR ^=LED3_GPIO_PIN;}  //输出反转

#endif


/* 扩展变量 ------------------------------------------------------------------*/
/* 函数声明 ------------------------------------------------------------------*/
void LED_GPIO_Init(void);
#endif  // __BSP_LED_H__


3.main.c

/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f10x.h"
#include "bsp/led/bsp_led.h"

static void Delay(uint32_t time);

/* 函数体 --------------------------------------------------------------------*/

int main(void)
{
  uint8_t count=0;

  /* 初始化板载LED灯,该函数定义在bsp_led.c文件中,在bsp_led.h声明所以需要包括该头文件 */
  LED_GPIO_Init();  
  
  /* 无限循环 */
  while (1)
  {

    switch(count)
    {
      /* 使用宏定义方法控制LED灯 */
      case 0:           
		LED1_OFF;
        LED2_OFF;
        LED3_OFF;
        break;
      case 1:           
	    LED1_ON;
        break;
      case 2:
		LED1_OFF;
        LED2_ON;
        break;
      case 3:                       
        LED2_OFF;
        LED3_ON;
        break;
      case 4:
        LED3_OFF;
        LED2_ON;
        break;
      case 5:
        LED2_OFF;
        LED1_ON; 
        break;
      case 6:
        LED1_ON;
        LED2_ON;
        LED3_ON;
        break;
    }    
    /* 延时一段时间 */
    Delay(1000);
    
    /* 计数增加1 */
    count++;
    /* 重新开始计数 */
    if(count==7)count=0;
  }
}


static void Delay(uint32_t time)
{
  uint32_t i,j;

  for(i=0;i<time;++i)
  {
    for(j=0;j<10000;++j)
    {       
      //空循环        
    }
  }
}

四、实验效果

流水灯

五、实验总结

通过这次利用STM32VET6进行流水灯实验以及撰写博客文章,对STM32中的GPIO初始化有了更深的体会。

作者:是覆盖对于变化

物联沃分享整理
物联沃-IOTWORD物联网 » STM32入门教程(一):使用标准库函数实现流水灯效果

发表评论