ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

实验1-流水灯控制实验

实验1-流水灯控制实验 文章目录前言一、标准外设库工程项目创建与配置过程1.构建本地文件夹结构2.提取并放入库文件3.在mdk5中配置工程二、标准外设库版本 C 语言代码实现1.main.c三、Keil 软件仿真逻辑分析仪观测时序与周期分析1.无示波器下使用 Keil 软件仿真2.仿真波形分析四、HAL库 外部中断控制流水灯启停1.STM32CubeMX 硬件与中断配置详细步骤2.hal库版本 C 语言代码3.面包板硬件接线与实验现象五、总结前言对于刚接触 STM32 的开发者来说点亮一盏 LED 灯往往是梦开始的地方。但要想真正搞懂底层的 GPIO 控制、软件延时的时序以及进阶的外部中断EXTI机制我们需要对基础的“流水灯”进行深度挖掘。故本次实验为两小节分别是用标准库和hal库点亮流水灯。一、标准外设库工程项目创建与配置过程1.构建本地文件夹结构在电脑上新建一个项目文件夹例如 STM32_LED_Blink_Lib并在其中创建以下 4 个子文件夹USER存放用户代码main.c, stm32f10x_it.c, stm32f10x_conf.h。CORE存放内核及启动文件core_cm3.c, core_cm3.h, startup_stm32f10x_md.s。FWLIB存放标准外设库的源码src文件夹放 .c 文件inc文件夹放 .h 文件。OBJ存放编译过程中生成的中间文件和最终的 .hex 烧录文件2.提取并放入库文件从 ST 官方下载标准固件库压缩包如 STM32F10x_StdPeriph_Lib_V3.6.0将以下文件拷贝到对应文件夹将 Libraries\STM32F10x_StdPeriph_Driver 下的 inc 和 src 复制到 FWLIB。将 Libraries\CMSIS\CM3\CoreSupport 下的文件复制到 CORE。将 Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm\startup_stm32f10x_md.s 复制到 COREC8T6属于中容量产品选 md。将 Project\STM32F10x_StdPeriph_Template 下的 main.c, stm32f10x_it.c, stm32f10x_conf.h 复制到 USER。3.在mdk5中配置工程打开 Keil点击 Project - New uVision Project将工程保存在 USER 文件夹下选择芯片型号 STM32F103C8。点击 Manage Project Items品字形图标建立对应的虚拟目录USER, CORE, FWLIB。将刚才文件夹中的文件分别添加到这些虚拟目录中。注意 FWLIB 中添加 src 下的所有 .c 文件或仅添加用到的如 stm32f10x_gpio.c, stm32f10x_rcc.c 等。点击魔术棒 Options for TargetOutput 选项卡勾选 Create HEX File并将输出路径选择为 OBJ 文件夹。C/C 选项卡在 Define 栏填入全局宏定义USE_STDPERIPH_DRIVER, STM32F10X_MD。C/C 选项卡在 Include Paths 中将 USER、CORE、FWLIB/inc 文件夹的路径全部添加进去确保编译器能找到头文件。二、标准外设库版本 C 语言代码实现1.main.c#includestm32f10x.h// 包含STM32标准外设库头文件/* 软件延时函数参数 t 决定延时长度 */voidDelay_ms(volatileuint32_tt){volatileuint32_ti;while(t--){// 在72MHz主频下循环约8000次大致为1ms实际受编译器优化影响for(i0;i8000;i);}}/* GPIO 初始化配置函数 */voidLED_GPIO_Config(void){GPIO_InitTypeDef GPIO_InitStructure;// 定义GPIO配置结构体// 1. 开启 GPIOA, GPIOB, GPIOC 的 APB2 外设时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);// 2. 配置通用推挽输出50MHzGPIO_InitStructure.GPIO_ModeGPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;// 初始化 PA4 (黄灯)GPIO_InitStructure.GPIO_PinGPIO_Pin_4;GPIO_Init(GPIOA,GPIO_InitStructure);// 初始化 PB0 (绿灯)GPIO_InitStructure.GPIO_PinGPIO_Pin_0;GPIO_Init(GPIOB,GPIO_InitStructure);// 初始化 PC13 (板载红灯)GPIO_InitStructure.GPIO_PinGPIO_Pin_13;GPIO_Init(GPIOC,GPIO_InitStructure);// 3. 初始状态全灭 (高电平熄灭)GPIO_SetBits(GPIOA,GPIO_Pin_4);GPIO_SetBits(GPIOB,GPIO_Pin_0);GPIO_SetBits(GPIOC,GPIO_Pin_13);}intmain(void){// 初始化系统时钟为72MHz (启动文件中默认会调用SystemInit此处为显式调用保障)SystemInit();// 初始化LED管脚LED_GPIO_Config();while(1){// 状态1红灯(PC13)亮黄灯(PA4)灭绿灯(PB0)灭GPIO_ResetBits(GPIOC,GPIO_Pin_13);// PC13 低电平点亮GPIO_SetBits(GPIOA,GPIO_Pin_4);GPIO_SetBits(GPIOB,GPIO_Pin_0);Delay_ms(1000);// 延时约1秒// 状态2黄灯(PA4)亮红灯(PC13)灭绿灯(PB0)灭GPIO_SetBits(GPIOC,GPIO_Pin_13);GPIO_ResetBits(GPIOA,GPIO_Pin_4);// PA4 低电平点亮GPIO_SetBits(GPIOB,GPIO_Pin_0);Delay_ms(1000);// 状态3绿灯(PB0)亮红灯(PC13)灭黄灯(PA4)灭GPIO_SetBits(GPIOC,GPIO_Pin_13);GPIO_SetBits(GPIOA,GPIO_Pin_4);GPIO_ResetBits(GPIOB,GPIO_Pin_0);// PB0 低电平点亮Delay_ms(1000);}}三、Keil 软件仿真逻辑分析仪观测时序与周期分析1.无示波器下使用 Keil 软件仿真1配置仿真环境 点击魔术棒 Options for Target进入 Debug 选项卡勾选左侧的 Use Simulator使用软件仿真。2修改仿真参数 在 Debug 界面左下方将 Dialog DLL 改为 DARMSTM.DLLParameter 改为 -pSTM32F103C8这一步非常关键否则无法捕捉硬件管脚状态。3进入调试模式 点击菜单栏的 Debug - Start/Stop Debug Session (或按 Ctrl F5) 启动调试。4打开逻辑分析仪 点击菜单栏 View - Analysis Windows - Logic Analyzer 打开逻辑分析仪窗口。5添加观测管脚在逻辑分析仪窗口点击左上角的 Setup 按钮。点击新建Insert输入管脚名PORTA.4回车。然后在下方 Display Type 选为 Bit。颜色可以设为黄色。同样方法添加 PORTB.0设为绿色和 PORTC.13设为红色。6运行并观察波形点击 Run (F5) 运行程序。此时会看到三种颜色的波形在逻辑分析仪中持续滚动刷新。等待几秒后点击 Stop 暂停运行。7测量周期在波形图上滚动鼠标滚轮放大波形直到能清晰看到高低电平的跳变沿。将鼠标放在 PORTC.13 的一个下降沿灯亮的时刻点击左键标记一条参考线。将鼠标移动到该波形的上升沿灯灭的时刻界面上会显示 Delta: X.XXX s或者 ms。2.仿真波形分析下图为该实验中产生得到的仿真波形观察上述 Keil 逻辑分析仪仿真波形图可以得出以下结论图中成功捕获了三个通道的波形红色、绿色、蓝色线从左侧的配置可以看出它们分别对应代码中设置的 (PORTA 0x00000010) 4即 PA4、PORTB.0PB0和 (PORTC 0x00002000) 13PC13管脚。三个波形清晰地展示出了三个串口间的高低电平的关系当一个灯从高电平转入低电平时其他两个串口同时进入高电平三者完全错开符合流水灯轮流点亮的特性。根据上方的时间轴网格设定为 0.5s。仔细观察可以看到每一个管脚维持低电平或高电平的宽度刚好占据了两个网格这意味着实际的高低电平转换周期约为 1秒这直接证明了代码中底部的 Delay_ms 函数在当前编译环境下传入参数 1000 时确实达到了预期的 1 秒精确延时效果。四、HAL库 外部中断控制流水灯启停本次实验转用 STM32CubeMX HAL 库来实现1.STM32CubeMX 硬件与中断配置详细步骤进入stm官网下载STM32CubeMX。STM32CubeMX下载打开软件1新建与选型打开 CubeMX搜索并选择 STM32F103C8Tx。2核心配置点击 System Core - SYS务必将 Debug 设置为 Serial Wire⚠️ 如果忘记设置 Debug 为 Serial Wire不仅无法使用调试功能代码下载一次后芯片会被直接锁死导致 ST-Link 无法再次识别3时钟配置RCC 中将 HSE 配置为 Crystal/Ceramic Resonator。然后在顶部的 Clock Configuration 树形图中直接在 HCLK 框输入 72 并回车软件会自动配置好锁相环PLL。4GPIO 配置在芯片引脚图上左键点击 PC13、PA4、PB0配置为 GPIO_Output。点击 PB1配置为 GPIO_EXTI1外部中断。进入左侧 GPIO 详细设置面板将 PB1 设为 Pull-up内部上拉触发模式选为 Falling edge trigger下降沿触发。5中断配置进入 System Core - NVIC勾选 EXTI line1 interrupt 开启中断。6生成工程路径纯英文IDE 选择 MDK-ARM。2.hal库版本 C 语言代码/* USER CODE BEGIN Header *//** ****************************************************************************** * file : main.c * brief : Main program body ****************************************************************************** * attention * * Copyright (c) 2026 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 ------------------------------------------------------------------*/#includemain.h#includegpio.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 BEGIN PV */volatileuint8_tis_paused0;// 运行状态标志位0表示运行1表示暂停/* USER CODE END PV *//* USER CODE BEGIN PFP */voidSmart_Delay(uint32_tms);// 声明智能延时函数/* USER CODE END PFP *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/voidSystemClock_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 */intmain(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){// 状态1红灯(PC13)亮黄(PA4)、绿(PB0)灭 (低电平点亮)HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);Smart_Delay(1000);// 状态2黄灯(PA4)亮红(PC13)、绿(PB0)灭HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);Smart_Delay(1000);// 状态3绿灯(PB0)亮红(PC13)、黄(PA4)灭HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);Smart_Delay(1000);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */}/** * brief System Clock Configuration * retval None */voidSystemClock_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.OscillatorTypeRCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEStateRCC_HSE_ON;RCC_OscInitStruct.HSEPredivValueRCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIStateRCC_HSI_ON;RCC_OscInitStruct.PLL.PLLStateRCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSourceRCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMULRCC_PLL_MUL9;if(HAL_RCC_OscConfig(RCC_OscInitStruct)!HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks */RCC_ClkInitStruct.ClockTypeRCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSourceRCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDividerRCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDividerRCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDividerRCC_HCLK_DIV1;if(HAL_RCC_ClockConfig(RCC_ClkInitStruct,FLASH_LATENCY_2)!HAL_OK){Error_Handler();}}/* USER CODE BEGIN 4 */// 智能延时函数在延时期间不断检测暂停标志位voidSmart_Delay(uint32_tms){uint32_tstart_timeHAL_GetTick();while((HAL_GetTick()-start_time)ms){while(is_paused1){// 如果处于暂停状态就在此处死循环等待实现灯光定格HAL_Delay(10);}}}// 外部中断回调函数按键按下时自动触发voidHAL_GPIO_EXTI_Callback(uint16_tGPIO_Pin){// 判断是否为 PB1 触发的中断if(GPIO_PinGPIO_PIN_1){// 简单软件防抖for(volatileinti0;i10000;i);// 确认管脚确实为低电平按键被按下if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)GPIO_PIN_RESET){// 翻转状态暂停/恢复is_paused!is_paused;}}}/* USER CODE END 4 *//** * brief This function is executed in case of error occurrence. * retval None */voidError_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 */}#ifdefUSE_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 */voidassert_failed(uint8_t*file,uint32_tline){/* 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 */3.面包板硬件接线与实验现象因为我们在软件中开启了 PB1 的“内部上拉”这就省去了外部接电阻的麻烦。按键接法按键一端连接 STM32 的 PB1 管脚另一端直接连接到面包板上的 GND与 STM32 共地。当按键未按下时引脚被内部拉高至 3.3V按下瞬间引脚直接接地变为 0V产生一个“下降沿”立刻触发硬件中断。实验现象总结程序运行后红、黄、绿三灯以 1 秒为间隔依次轮流闪烁。当按下按键时程序进入 exti回调函数翻转了暂停标志位智能延时函数检测到该标志位变为 1陷入原地等待循环流水灯定格在当前亮起的灯上。再次按下按键标志位清零流水灯从暂停处无缝恢复闪烁。五、总结在实验一中我们使用标准外设库手动搭建工程、配置结构体、填写宏定义。这个过程虽然繁琐但极其锻炼我们对 STM32 物理文件结构和外设底层逻辑的理解。而在实验二中切换到 HAL 库与 STM32CubeMX 后图形化界面的“一键生成”让我们深刻感受到了现代嵌入式开发的便捷。对于学习者而言“用标准库打基础用 HAL 库做项目” 是非常科学的进阶路线。
返回列表