基于stm32的keil调试
本文目标:基于stm32的keil调试
按照本文的描述,应该可以跑通实验并举一反三。
先决条件:装有编译和集成的开发环境,比如:Keil uVision5、STM32CubeMX
使用外设:GPIO
前言
对于学习一个新功能时,没能实现自己的实验现象时,我们可能会感到灰心丧气。不过,不要失望,这是一个学习新东西的正常过程。在嵌入式系统开发中,调试是一个非常重要的技能,它不仅涉及到理解代码,还需要理解硬件的工作原理。
实验目的
本文的目标是帮助你理解和使用STM32的调试功能。我将通过一个实验来展示如何使用调试接口,并利用调试代码追踪问题。
问题
假设你正在调试一个你的期望功能,但是没能实现你想实现的现象。这时候如果能追踪一下代码的执行过程就很好了。下面是我的代码片段,下载到板子后没能按照正常逻辑跑起来,我们的目标的是找到工程中代码卡死的原因。
debug
我这里是使用keil进行调试,在开始调试前,确保对应的下载器连接好,设置好对应的调试工具,这里是我使用的调试工具。
以下展示的一些图片,是我平时常用的功能。
还有在仿真时如果发现有如下没有灰色的窗口时,表明函数没有被编译进去
这个时候需要适配一下优化等级,方法如下:
就是我们在调试环节时不需要这么高的优化,后期等正式发布了在调高优化等级。选择了之后,重新编译,刚才没编译进去的现在编译进去了。
定位问题
在我的这个工程中,仿真跑起来直接进了错误,烦死。
通过前面图片的展示,打有效的断点可以帮助我们定位问题,于是简单粗暴在工程中打上断点。
明显现在卡死在SystemClock_Config()这个函数中,导致我们的代码没能跑起来。看一下这个系统配置函数做了什么,下面是现在函数的代码块。
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();
}
}
这时候我们其实有两个思路,一个是找一个自己熟悉的工程,直接把这个函数体整体替换,方便省事,毕竟是自己熟悉的工程自己有谱。一个是慢慢单步调试找到最终原因。在我展示的这个工程中,通过我一步步的观察,找到了罪魁祸首:
解决
这里我的外部时钟配置有些选项:
使用RCC_HSE_BYPASS的配置使用失败,大多工程中都是使用RCC_HSE_ON。更改过后,程序正常运行。
总结
通过这个实验,应该能够简单理解STM32的调试过程,并学会如何使用调试工具来解决问题。记住,调试是一个学习的过程,只有不断地尝试和失败,才能获得成功。希望给初学者一些启发,后续碰到有类似的问题时,可以自己通过仿真debug的方式来追踪代码,一点点的积累自己的工程经验。