stm32f103c8t6黑色核心板外部中断和定时器控制LED
1.0前言
千里之行始于足下🚗🚓🚕,接下来我们将*学习stm32黑色核心板 GPIO 输入输出信号,采用简单的按键输入通过外部中断或定时器来控制输出LED的亮灭!*
- 外部中断控制🌛
- 定时器控制LED🌞
2.0示例详解
本次分为两次实验,代号分别为🌛和🌞
2.1硬软件选择
硬件平台 | 软件平台 | |
---|---|---|
黑色核心板 | 1块 | keil v5 |
LED | 2颗 | stm32cubemx |
自复位按键 | 1颗 | |
面包板 | 1块 | |
220Ω电阻 | 2颗 | |
杜邦线 | 若干 |
keil v5安装教程:https://www.bilibili.com/video/BV1q4411d7RX?p=1
stm32cubemx:https://www.bilibili.com/video/BV1q4411d7RX?p=2
2.2实验原理
🌛
使用stm32cubemx 工具自动产生的配置工程,使用KEIL5编译代码。将PA0引脚设置成输入引脚,程序得到PA0引脚的(按键操作)输入状态,并根据其输入电平的高低来控制PC13输出,来控制LED,实现按一次LED亮,再按一下,LED灭的功能。
本示例所用的最小系统板原理图:
按键控制LED原理图
注意:此图LED灯引脚接反了,需要对调一下
🌞
3.0操作流程
3.1新建STM32 Cube MX工程
🌛
- 双击桌面STM32CubeMX工具,然后在CubeMX中菜单 File中点New Project ;
- 在新弹出的界面中的搜索框中输入 “stm32f103c8” ,并双击右侧栏中列出的STM32F103C8选用该芯片;
- 弹出如下图所示界面,至此工程创建完成!!!😀😀😀接下是就是配置工程;
3.2配置工程
- 配置系统伏仿真调试接口, 在System Core 目录下单击SYS选项,将其中的Debug选项选为Serial Wire, 此时PA13 PA14引脚会被占用,配置图如下:
- 配置系统时钟源,在System Core 目录下单击RCC选项,将其中的High Speed Clock( HSE )选项选为Crystal/ceramic resona…, 此时PD0 PD1引脚会被占用,配置图如下:
- 配置GPIO PA0 为GPIO _Input及 PC13 为GPIO _Output引脚,详细配置如下;
- 配置系统时钟树,将工程界面切换到Clock Configureation 界面,完成如下配置。
- 配置代码生成,工程界面切换到Project Manager 界面,在界面左侧单击Project项,将其设置成如下图所示( 本人设置工程路径在C:\Users\Asus\Documents\STM32_examplel目录,工程名为LED_key, 开发环境为 MDK-ARM v5 )。
- 在界面左侧单击Code Generator项,将其设置成如下图所示( 只拷贝所需文件到工程,为每个接口生成独立的初始化头文件和源文件,将所有未使用的引脚设为模拟输入)。
- 生成代码,单击工程界面中”GENERATE TOOL” 开始生成代码,代码生成后弹出是否打开工程对话框,单击“Open Project”打开创建的工程,即配置工程完成接下来是keil v5开发和调试。
3.3keil v5开发
- 修改部分代码,在代码工程(MDK/keil)中的 main.c 中 man函数中如下红框中代码(本人采用汉化背景美化可参照):
框框代码如下(复制粘贴即可)
/* USER CODE BEGIN 0 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin==GPIO_PIN_0)
{
HAL_Delay(500);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
}
HAL_Delay(200);//阻塞式防抖
}
/* USER CODE END 0 */
- 检查程序正确无误,编译该工程,烧录代码。所有准备工作已经配置完成,进入调试环节,核心板启动方式和排针对应如下:
BOOT0 | BOOT1 | MODE |
---|---|---|
0 | X | FLASH |
1 | 1 | SRAM |
1 | 0 | ISP |
-
BOOT0-0和 BOOT1-X 默认是 flash 的启动方式;
-
硬件接线
-
所有准备工作就绪,实现了按一下按键(PA0引脚由高变低一次),LED输出PC13状态实现一次反转,见演示视频。
🌞
Clock configuratio🚲GPIO🚲tim2🚲tim3🚲project
STM32CubeMX参照上配置
keil5参数修改有两处,第一处main.c中开启定时器(位置在while(1)上面)并添加主控程序;
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 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 "tim.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();
MX_TIM2_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
// HAL_TIM_Base_Start_IT(&htim2);
// HAL_TIM_Base_Start_IT(&htim3); 开启定时器
HAL_TIM_Base_Start(&htim2);
HAL_TIM_Base_Start(&htim3);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) //主程序控制
{
/* USER CODE END WHILE */
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_12);
HAL_Delay(2000);
/* 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_ON;
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_MUL4;
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_1) != 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 */
__disable_irq();
while (1)
{
}
/* 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,
ex: 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****/
第二处tim.c中添加定时器回调函数处理
/**
******************************************************************************
* @file tim.c
* @brief This file provides code for the configuration
* of the TIM instances.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 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
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "tim.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
/* TIM2 init function */
void MX_TIM2_Init(void)
{
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM2_Init 1 */
/* USER CODE END TIM2_Init 1 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 31999;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 999;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM2_Init 2 */
/* USER CODE END TIM2_Init 2 */
}
/* TIM3 init function */
void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 31999;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 499;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspInit 0 */
/* USER CODE END TIM2_MspInit 0 */
/* TIM2 clock enable */
__HAL_RCC_TIM2_CLK_ENABLE();
/* TIM2 interrupt Init */
HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
/* USER CODE BEGIN TIM2_MspInit 1 */
/* USER CODE END TIM2_MspInit 1 */
}
else if(tim_baseHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspInit 0 */
/* USER CODE END TIM3_MspInit 0 */
/* TIM3 clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
/* TIM3 interrupt Init */
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_MspInit 1 */
/* USER CODE END TIM3_MspInit 1 */
}
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspDeInit 0 */
/* USER CODE END TIM2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM2_CLK_DISABLE();
/* TIM2 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM2_IRQn);
/* USER CODE BEGIN TIM2_MspDeInit 1 */
/* USER CODE END TIM2_MspDeInit 1 */
}
else if(tim_baseHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspDeInit 0 */
/* USER CODE END TIM3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM3_CLK_DISABLE();
/* TIM3 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_MspDeInit 1 */
/* USER CODE END TIM3_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 *///定时器回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //定时器回调函数
{
if(htim->Instance==TIM2)
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
}
if(htim->Instance==TIM3)
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);
}
}
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
此程序自动运行,可见延时触发和定时器触发两者区别,前者与主程序紧密相关实时控制,后者无关独立运行
见效果。
- 接线图
- 定时器和延时触发视频
4.0 总结
- 本篇学习stm32黑色核心板 GPIO 输入输出信号,采用stm32cubemx和keil v5组合开发,前者涉及到外部中断触发LED,后者通过基本定时器中断和延时分别控制LED。。主要难度在控制原理以及项目移植开发,非常值得新手一试!!!😃😃😃
- 在以后的博文中我们将学会用stm32常用传感器和执行器,从而实现对外部世界进行感知,充分认识这个有机与无机的环境,科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。
- 本人工程文件
- 参考文献:STM32的中断系统与外部中断基础; STM32的定时器开发基础