飞道的博客

STM32物联网套件基础版01-点亮LED

294人阅读  评论(0)

前言

上一节,我们完成了STM32物联网套件中STM32单片机开发环境的搭建,本节我们正式学习STM32单片机,编程语言的学习,通常是从第一个"hello world"开始,而点灯实验便是单片机学习的开始。

一、基础知识

1. STM32物联网套件简介


STM32物联网套件目前有两个版本:基本版和高级版,后续会增加应用版本和语音版,核心板均采用STM32F103C8T6核心板,基础版主要元器件如下所示:

高级版版主要元器件如下所示:

STM32物联网套件致力于带领大家入门物联网,不仅是带领大家开发STM32,也一起玩转微信小程序开发、物联网服务器后台开发,真正做到了解一个物联网项目的方方面面,基于此,我们定制了一套通用的WIFI通讯协议(可以理解为类似AT指令,不过集成度更高,几条指令就可以直连接云平台),如三条指令连接腾讯云实例

后续我们会继续增加涂鸦智能、电信云、移动Onenet、阿里云等主流云平台的支持,力争做到,一套STM32代码,通过定制的WIFI模块可以连接到不同的云平台,也欢迎有产品开发需求的朋友私聊我们咨询、定制物联网方案!

2. STM32最小系统简介

一个最小的STM32系统,需要有单片机、电源电路、晶振电路、复位电路、启动电路、调试电路组成,这几部分存在就可以使STM32正常工作。

(1) STM32F103C8T6

ARM的Cortex-M3处理器是最新一代的嵌入式ARM处理器,它为实现MCU的需要提供了低成本的平台、缩减的引脚数目、降低的系统功耗,同时提供卓越的计算性能和先进的中断系统响应。

ARM的Cortex-M3是32位的RISC处理器,提供额外的代码效率,在通常8和16位系统的存储空间上发挥了ARM内核的高性能。

(2) 电源电路

和STC89C52单片机5V供电不同,STM32需要3.3V电压供电,直接输入的电压不太稳定性,需要电路稳压,同时点亮LED1,可以通过LED1的亮灭初步观察系统运行情况,正常运行情况,LED1常亮。

使用稳压芯片,将USB输入的5V电压转换为STM32需要的3.3V电压

LED1电路如下,插上Micro USB线后即可点亮

(3) 复位电路

单片机有一个RESET引脚,只需要将此引脚保持一段时间低电平即可复位STM32单片机,当按键按下瞬间,RESET电平为低电平,复位STM32单片机,之后C2开始充电,C2电源不断上升,R2两端电压不断下降,当C2两端电压达到3.3V时,充电结束,此时RESET引脚变为高电平,单片机进入正常工作状态,复位完成。

注意:51单片机是高电平复位,STM32是低电平复位

(4) 晶振电路

上图中有两个晶振,一个是8MHz,另一个是32.768KHz,8M晶振的作用是为最小系统提供最基本的时钟信号,方便倍频,一般STM32F103系列正常使用过程需要倍频到72MHz。32.768KHZ晶振经过15次分频后可以得到1HZ的频率(原因是32768 = 2^15),可以实现精准定时,用于精准计时电路,比如作为万年历。

(5) boot启动电路

启动方式如下表所示:

(5) 调试接口电路

本系列教程使用STM32F103C8T6核心板,其调试接口电路采用JLink SWD方式进行

3.LED灯发光原理

LED灯中有电流通过时候,将点亮LED灯,单片机系统中,常见的LED灯如下所示,其中长的引脚一端为正极,短的为负极。

那么问题来了,如何让LED中有电流通过呢?电流到多少才能点亮LED呢?我们先看下实际电路设计中常用的LED设计电路

上图中LED1左边接入电源正极、右边接入负极,电流方能通过点亮LED,此时LED电阻几乎为0,如果电源接反方向了,LED产生很大电阻,阻止电流通过,此时,不能LED不能点亮,一般而言LED正向接入电源,保证通过LED中的电流为20mA左右即可点亮LED。

4.设计LED驱动电路


上图中PB12端口连接单片机PB12引脚,只需要控制单片机给低电平即可点亮LED。

实物图如下:

二、实例

1. 新建工程

使用STM32CubeMX创建一个新的工程,参考上节配置方式,设置RCC和PB12 PB13 PB14引脚输出

进入Clock configuration页面,选择HSE时钟源,倍频后主时钟为72MHz

切换到Project Manager栏目,设置工程名字、工程保存目录、工具链等信息,具参数如下图所示

点击左边栏目Code Generator,然后勾选Generate peripheral initialization as a pair of ‘.c/.h’ files per peripheral,勾选此选项,外设将单独保存在一个文件中,而不是全部都在main.c中。

然后打开1.Led.uvprojx工程

打开后工程如下

可以看到多了一个gpio.c文件,main.c中MX_GPIO_Init()便是调用的gpio.c中的文件,其函数声明在gpio.h中

2. GPIO函数说明

(1) 首先查看下gpio.c中MX_GPIO_Init()函数

/** Configure pins as 
        * Analog 
        * Input 
        * Output 
        * EVENT_OUT 
        * EXTI 
*/ 
void MX_GPIO_Init(void) 
{
    
 
  GPIO_InitTypeDef GPIO_InitStruct = {
   0}; 
 
  /* GPIO Ports Clock Enable */ 
  __HAL_RCC_GPIOC_CLK_ENABLE(); 
  __HAL_RCC_GPIOD_CLK_ENABLE(); 
  __HAL_RCC_GPIOB_CLK_ENABLE(); 
  __HAL_RCC_GPIOA_CLK_ENABLE(); 
 
  /*Configure GPIO pin Output Level */ 
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); 
 
  /*Configure GPIO pin Output Level */ 
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET); 
 
  /*Configure GPIO pin : PC13 */ 
  GPIO_InitStruct.Pin = GPIO_PIN_13; 
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 
  GPIO_InitStruct.Pull = GPIO_NOPULL; 
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 
 
  /*Configure GPIO pin : PB12 */ 
  GPIO_InitStruct.Pin = GPIO_PIN_12; 
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 
  GPIO_InitStruct.Pull = GPIO_NOPULL; 
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 
}

在GPIO初始化函数中,首先使能GPIOB时钟,然后初始化PB12 PB13 PB14,初始化函数用到了GPIO_InitTypeDef定义的GPIO_InitStruct,我们接下来看看GPIO_InitTypeDef结构

typedef struct
{
   
  uint32_t Pin;       /*!< Specifies the GPIO pins to be configured.
                           This parameter can be any value of @ref GPIO_pins_define */

  uint32_t Mode;      /*!< Specifies the operating mode for the selected pins.
                           This parameter can be a value of @ref GPIO_mode_define */

  uint32_t Pull;      /*!< Specifies the Pull-up or Pull-Down activation for the selected pins.
                           This parameter can be a value of @ref GPIO_pull_define */

  uint32_t Speed;     /*!< Specifies the speed for the selected pins.
                           This parameter can be a value of @ref GPIO_speed_define */
} GPIO_InitTypeDef;

其中Pin表示需要操作的GPIO引脚,GPIO_PIN_All表示选择该端口所有引脚GPIO_PIN_0~GPIO_PIN_15

Mode 用以设置选中管脚的工作状态

Pull表示引脚下拉或上拉设置

Speed引脚驱动速率设置

3. 修改程序

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
   
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* 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();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
   
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
    HAL_Delay(1000);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
    HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
   
  RCC_OscInitTypeDef RCC_OscInitStruct = {
   0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {
   0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
   
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
   
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
   
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
   
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

三、下载运行

按照上一节方式给核心板下载程序,然后将核心板直插到底板上面,可以看到红色LED灯在交替闪烁。

四、小结

如您在使用过程中有任何问题,请加QQ群进一步交流。

QQ交流群:906015840 (备注:物联网项目交流)

源码获取:关注公众号,回复stm32_hal获取资料

硬件获取:某宝搜索小驿物联


小驿物联出品:如果决定要出发,就不要把时间浪费在犹豫上!


转载:https://blog.csdn.net/weixin_45006076/article/details/109008161
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场