stm32呼吸灯程序_STM32裸机开发基础篇02点亮LED

前言 8152cd0219b92d6a23ba968f60e85c12.png

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

基础知识

1. STM32最小系统简介

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

(1) STM32F103C8T6

e294a5165f621b7c718f10c6c5d24107.png

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电压

2df2acd4a5ae179bec794e3d38ab2b8d.png

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

adf907d629c35f0f5b06b8441caaee5b.png

(3) 复位电路

859b0f9e8503961f51c8080e89e6fffd.png

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

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

(4) 晶振电路

6aaadea682fa07b201df8e1898b4b5a4.png

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

(5) boot启动电路

a955e7c457f2e71ca8d5f0a3ad554112.png

启动方式如下表所示:

BOOT0

BOOT1

启动方式

0

x

从主闪存存储器启动

1

0

从系统存储器启动

1

1

从内置SRAM启动

(6) 调试接口电路

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

e5f493af8d059f6e52faa0e4c0aa04b3.png

2.LED灯发光原理

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

372f9d587994db5b6f7564be85c224b2.png

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

5168485f572b7c51b3013d35afa34373.png

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

3.查看开发底板LED部分原理图

f419ba041baf0386651405ccbb3c6542.png

上图中led_wifi led_red led_green分别连接单片机PB12 PB13 PB14引脚,只需要控制单片机给低电平即可点亮LED。

开发板实物图如下:

17562c60dbdb8e302367a5a4a29405bc.png

实例

1. 新建工程

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

caa2177b14dbda2c475c5166ae747e45.png

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

a69791b233b028d3b81f961e4a400e28.png

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

ec1ff4a2842ab9e7c681eedde663afa6.png

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

3a8e89cf3293b880f4a0604bbbd301b4.png

然后打开02Led.uvprojx工程

e299919af8b1a71e5e808cdd5b08f2d3.png

打开后工程如下

78d62f924e937b72140a4c84dc949603.png

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

8c9bbbca59bf9c5b04eaa353a6649c7d.png

2. GPIO函数说明

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

void MX_GPIO_Init(void){  GPIO_InitTypeDef GPIO_InitStruct = {0};  /* GPIO Ports Clock Enable */  __HAL_RCC_GPIOD_CLK_ENABLE();  __HAL_RCC_GPIOB_CLK_ENABLE();  /*Configure GPIO pin Output Level */  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14, GPIO_PIN_RESET);  /*Configure GPIO pins : PB12 PB13 PB14 */  GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14;  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 用以设置选中管脚的工作状态

Mode

描述

GPIO_MODE_INPUT

输入模式

GPIO_MODE_OUTPUT_PP

推挽输出

GPIO_MODE_OUTPUT_OD

开漏输出

GPIO_MODE_AF_PP

复用开漏输出

GPIO_MODE_AF_OD

复用推挽输出

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

Pull

描述

GPIO_NOPULL

引脚悬空

GPIO_PULLUP

引脚上拉

GPIO_PULLDOWN

引脚下拉

Speed引脚驱动速率设置

Speed

描述

GPIO_SPEED_FREQ_LOW

低速输出

GPIO_SPEED_FREQ_MEDIUM

中速输出

GPIO_SPEED_FREQ_HIGH

高速输出

3. 修改程序

/* USER CODE BEGIN Header *//**  ******************************************************************************  * @file           : main.c  * @brief          : Main program body  ******************************************************************************  * @attention  *  * 

© Copyright (c) 2020 STMicroelectronics.
* All rights reserved. * * 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 *//* 一个__NOP()为1/72us */void delay_us(uint32_t time){ uint32_t i=0; for(i=0;i__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP(); __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP(); __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP(); __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP(); __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();        }}void delay_ms(uint16_t time){ delay_us(time*1000);}/* 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_13|GPIO_PIN_14,GPIO_PIN_SET); delay_ms(1000); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14, GPIO_PIN_RESET); delay_ms(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灯在交替闪烁。

d6f7c881459339abb47974497650c249.png

小结

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

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

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

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

PCB开源:https://lceda.cn/solitary_sand/51-dan-pian-ji-wu-lian-wang-kai-fa-ban_base

一叶孤沙出品:一沙一世界,一叶一菩提

c1d771ced9b79c4895f74bf19406a8bb.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值