STM32单片机 超入门项目:流水灯(不同闪烁模式和速度) 您所在的位置:网站首页 stm32f103rct6流水灯程序流程图 STM32单片机 超入门项目:流水灯(不同闪烁模式和速度)

STM32单片机 超入门项目:流水灯(不同闪烁模式和速度)

2024-07-05 10:52| 来源: 网络整理| 查看: 265

文章目录 前言一、电路原理图二、硬件准备三、单片机配置四、代码编写

前言

流水灯通过交替闪烁实现灯光流动的效果,本篇将分析如何采用STM32单片机实现流水灯。 在这里插入图片描述

一、电路原理图

在这里插入图片描述

二、硬件准备

STM32单片机(STM32F103RCT6)、发光二极管4(我用的是七彩快闪,用红绿蓝LDE自行搭配也可)、1k电阻4、面包板飞线等自备。

三、单片机配置

打开STM32CubeMX,选择型号STM32F103RCT6,配置调试器Pinout&Configuration->SYS->No Debug换为Serial Wire,如果不替换第一次烧录后会屏蔽烧录功能。 设置时钟源Pinout&Configuration->RCC->HSE Disable换为Crystal/Ceramic Resonator。 配置时钟树,Clock Configuration->HCLK设置为72MHz,回车,点击OK令CubeMX自动调整配置。 配置引脚,见下图,点击引脚即可配置,我们只需配置PA1 ~ PA4,PC12,PC13引脚,其余是上述步骤自动配置的。注意,我的最小系统板PC12,PC13接的是按键,可根据自己的系统板原理图自行调整引脚,并修改代码。PA1 ~ PA4均为推挽输出(默认)不用更改,推挽输出和开漏输出的区别参考这篇博客。 使能中断Pinout&Configuration->NVIC->EXTI那一行勾上。 最后使用Keil IDE的话Project Manager->Toolchain IDE改为MDK_ARM,其他IDE自行更改,Project Manager->Project Name输入工程名,点击右上角生成代码。 在这里插入图片描述

我的stm32最小系统板原理图如下,注意按键对应的引脚 在这里插入图片描述

四、代码编写 /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2023 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.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); static void MX_GPIO_Init(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ uint8_t mode=0,speed=0,flag=0; uint16_t delay_time=0; void light(uint16_t,uint16_t,uint16_t,uint16_t); /* 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) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ //设置延时时间 switch(speed) { case 0:delay_time=100;break; case 1:delay_time=1000;break; case 2:delay_time=2000;break; } switch(mode) { case 0://四个灯依次点亮 { light(GPIO_PIN_RESET,GPIO_PIN_SET,GPIO_PIN_SET,GPIO_PIN_SET); if(flag==1) {flag=0;break;}HAL_Delay(delay_time); light(GPIO_PIN_SET,GPIO_PIN_RESET,GPIO_PIN_SET,GPIO_PIN_SET); if(flag==1) {flag=0;break;}HAL_Delay(delay_time); light(GPIO_PIN_SET,GPIO_PIN_SET,GPIO_PIN_RESET,GPIO_PIN_SET); if(flag==1) {flag=0;break;}HAL_Delay(delay_time); light(GPIO_PIN_SET,GPIO_PIN_SET,GPIO_PIN_SET,GPIO_PIN_RESET); if(flag==1) {flag=0;break;}HAL_Delay(delay_time); break; } case 1://四个灯两两点亮 { light(GPIO_PIN_RESET,GPIO_PIN_RESET,GPIO_PIN_SET,GPIO_PIN_SET); if(flag==1) {flag=0;break;}HAL_Delay(delay_time); light(GPIO_PIN_SET,GPIO_PIN_SET,GPIO_PIN_RESET,GPIO_PIN_RESET); if(flag==1) {flag=0;break;}HAL_Delay(delay_time); break; } case 2://四个灯同时亮灭 { light(GPIO_PIN_RESET,GPIO_PIN_RESET,GPIO_PIN_RESET,GPIO_PIN_RESET); if(flag==1) {flag=0;break;}HAL_Delay(delay_time); light(GPIO_PIN_SET,GPIO_PIN_SET,GPIO_PIN_SET,GPIO_PIN_SET); if(flag==1) {flag=0;break;}HAL_Delay(delay_time); break; } } } /* 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_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(); } } /** * @brief GPIO Initialization Function * @param None * @retval None */ static 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_GPIOA_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4, GPIO_PIN_RESET); /*Configure GPIO pins : PC13 PC12 */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /*Configure GPIO pins : PA1 PA2 PA3 PA4 */ GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* EXTI interrupt init*/ HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); } /* USER CODE BEGIN 4 */ //按键,外部中断 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin==GPIO_PIN_13) { mode=(mode+1)%3; flag=1; } else if(GPIO_Pin==GPIO_PIN_12) { speed=(speed+1)%3; flag=1; } } //点灯 void light(uint16_t s1,uint16_t s2,uint16_t s3,uint16_t s4) { HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,s1); HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,s2); HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,s3); HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,s4); } /* 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 */

user code 0、while(1)、user code4为编写代码部分,代码整体思路: 通过外部中断,在按键按下时单片机将执行相应中断回调函数(改变流水灯模式mode和速度speed),这里模式和速度我各设置了三种,所以回调函数中mode=(mode+1)%3不难理解哈~另外点灯这一步我是在while(1)里面实现的,回调函数中不易写太多代码。外部中断参考这篇博客。

由于按下按键要等这一轮流水灯结束才能生效,我在代码中加入了if(flag==1) {flag=0;break;}来提前结束这一轮while循环,就可以即时生效了。

另外注意的一点是我的系统板按键并联了电容防抖,如果没有则需代码解决,参考这篇博客。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有