STM32使用过程中的踩坑记录

发布者:reaper2009最新更新时间:2022-08-09 来源: csdn关键字:STM32  使用过程  踩坑记录 手机看文章 扫描二维码
随时随地手机看文章

1. 中断函数不要随意使用prinf()函数

记调试步进电机加速减速过程的一次大坑。


2. 使用HAL库的时候不要在中断中使用HAL_Delay()函数

HAL库的HAL_Delay()函数是通过Systick定时器的1ms中断实现的,一般情况下Systick定时器的优先级设置为最低,因此在更高优先级的中断触发后导致HAL_Delay()函数uwtick值无法更新,因此程序会卡死在HAL_Delay()函数中。


3.注意STM32库在配置串口字长时是包含校验位的字长,而一般上位机配置的串口字长是不包含校验位的。

这点在配置使用校验时是非常重要的,如果配置出错会导致通讯不正常。


4.使用不同的开发板的时候一定要注意不同板子上的晶振可能是不一样的

之前用的板子是8M的晶振,配置好了可以正常使用。后面换了板子是25M晶振的。只修改了SystemClock_Config()函数中的因子,忘记修改晶振配置的值,导致时钟频率一直不对。晶振不同时,一定要到stm32xxxx_hal_conf.h中修改HSE_VALUE为相应的晶振值


5.移植FreeRTOS,让stm32hal和freeRTOS共用SYSTICK,程序全速运行会卡死在hardfault中断,但单步调试可以运行过去

在之前的板子上可以运行,但在后面新作的板子上出现了这个问题。(这一点感觉好奇怪)

systick中断代码:


void SysTick_Handler(void)

{

 HAL_IncTick();

 #if (INCLUDE_xTaskGetSchedulerState == 1 )

  if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {

 #endif /* INCLUDE_xTaskGetSchedulerState */

  xPortSysTickHandler();

 #if (INCLUDE_xTaskGetSchedulerState == 1 )

  }

 #endif /* INCLUDE_xTaskGetSchedulerState */

}


在stm32f4xx_it.c文件中一定要包含FreeRTOS.h头文件,否则会导致上述函数中条件编译的宏不会生效,导致在还没开启任务调度时,触发SysTick中断后会直接进入xPortSysTickHandler()函数,导致触发了hardfault中断。


6. STM32F429使用TIM2和TIM5的的注意事项

TIM2和TIM5是32位定时器,TIM2和TIM5产生PWM并通过DMA传输时必须按32位传输(即DMA设置的长度位32位)且用于为输出比较寄存器赋值的数组也必须为32为的(在使用TIM2和定时器5驱动WS2812时一定要注意)。

注:移植之前的ws21812灯珠驱动程序(之前用的是TIM3属于16位寄存器),改到TIM2来驱动用逻辑分析仪一直没有测到输出波形,又测试了TIM5也是这样还以为TIM2和TIM5的PWM不能够通过DMA传输呢!这个事情告诉我们一定要认真读手册

7. STM32F429不能够通过PA1和PA2输出PWM

https://blog.csdn.net/xiaoyuanwuhui/article/details/109597401中有记录


8. STM32的部分外设在初始化初始化函数只能执行1次!!!

在使用STM32ADC外设时,红外测距模块和电流采样模块都用到了ADC,因而在两个模块分别初始化的时候调用了两次ADC初始化的函数bsp_adc1Init(),导致电流检测数据不正常(实际硬件测量没有电压,但ADC的采样值却有500多的值(实际应该在10左右))。在屏蔽掉红外测距模块的初始化函数后,数据便恢复正常了。

解决方法:仿照crazyfile代码中硬件外设初始化的方法,定义一个isInit的变量用于指示当前外设初始化函数是否执行过,如果执行过则直接跳出。


static bool isInit = false;


void bsp_adc1Init(void) {

if(isInit) {

return;

}

/* init adc module */

//...

isInit = ture;


采用上述方式,可以防止adc外设被重复初始化,因此可以避免上面出现的问题,又可以很好的保证红外测距模块和电流采样模块的独立性和完整性。


9. STM32的PWM控制开启和停止的函数在FREERTOS环境下使用时可能需要进入临界段保护

在实际的一个项目中用到了步进电机控制,在执行任务的过程中可能会不断地启停步进电机控制,而且步进电机的启动和停止控制不是在一个任务中实现的,这会导致步进电机出现丢步,从而导致电机有异响.(实际从示波器中确实可以看到约1ms的波形中断).

HAL_TIM_PWM_Start()和HAL_TIM_PWM_Stop()函数用于步进电机的启停控制.

实测发现:将上述两个函数放到taskEnter_CRITICAL()和taskEXIT_CRITICAL()之间便不会再出现上面电机异响的现象了.


10.通过cubeMX配置ADC+DMA功能时可能出现功能不正常的问题

开始先通过cubeMX配置生成了一个ADC功能测试的例程,后面为了测试ADC+DMA功能,在该工程中又增加了DMA配置,但通过该工程生成的代码就是有问题,ADC不能正确转换并更新到变量中。经排查发现是生成的代码中ADC初始化函数MX_ADC_Init()在DMA初始化函数MX_DMA_Init()之前导致的,将两个初始化函数调整下顺序功能便正常了。

分析:MX_DMA_Init()函数中主要是开启DMA时钟,MX_ADC_Init()函数中进行了DMA相关的配置,可能是由于配置DMA之前未打开DMA时钟导致的。

初始化函数的前后顺序可按照下图进行调序:

在这里插入图片描述

11.HAL_ADCEx_InjectedStop_IT(&hadc1)函数使用注意事项

在默认配置ADC规则通道DMA采样+外部触发注入模式后,并开启了外部触发注入转换和规则通道DMA转换,中间过程中想校准注入通道对应的初始值,需要将外部触发改为软件触发并采样取平均值。在修改配置之前首先要将规则通道和注入通道转换全部关闭且一定要先关闭规则通道转换再关闭注入通道转换之后再修改相应的配置。


正确顺序:


HAL_ADC_Stop_DMA(&hadc1); //

HAL_ADCEx_InjectedStop_IT(&hadc1); //关闭注入组之前必须先把规则组关闭


HAL_ADCEx_InjectedStop_IT(&hadc1);函数中有如下的注释,说明了在没有规则组转换要继续时才会关闭,上面配置的是规则组通过DMA转换,会一直转换,所以要先把规则组DMA先关闭。


/* Stop potential conversion and disable ADC peripheral                     */

/* Conditioned to:                                                          */

/* - No conversion on the other group (regular group) is intended to        */

/*   continue (injected and regular groups stop conversion and ADC disable  */

/*   are common)                                                            */

/* - In case of auto-injection mode, HAL_ADC_Stop must be used.             */ 

//翻译如下:

/* 停止电位转换并禁用 ADC 外设

  适应于:

  - 其他组(常规组)上没有转换打算继续(注入和常规组停止转换和 ADC 禁用很常见)

  - 在自动注入模式的情况下,必须使用 HAL_ADC_Stop。 */


12 记一次串口无法进入IDLE中断的问题

为某项目新作了一块板子,在移植程序的时候发现,总是无法进入串口IDLE的接收中断,换到其他串口便能够正常进入中断。经过排查最终发现是bootloader程序中也配置过串口2,但两次映射的串口2引脚不一致导致的。将boot程序中的串口2的引脚映射改为和app程序中一样的引脚映射便没有了该问题。


13 记一次粗心导致CAN通讯异常的问题

在调试新板子,只要插着驱动器的CAN通讯线,必会导致程序卡死在CAN中断中(之气前还一直认为板子程序没有跑起来,调试发现是程序一直在触发CAN中断)。调试了好长时间,中间还以为是配置双CAN通信的问题,可屏蔽掉还是不行,最终发现是开启了CAN错误中断,当时为了调试CAN2方便,将错误中断中处理的can1重新初始化函数屏蔽了,而这之前又执行了__HAL_CAN_RESET_HANDLE_STATE(&hcan1)将hcan1的State状态置为了HAL_CAN_STATE_RESET,导致一直触发CAN_FLAG_ERRI,便卡在了CAN中断函数中

导致出现问题的代码如下:


void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) {

  if(hcan->Instance == CAN1) {

    /* 记录CAN错误信息 */

    /* 处理CAN报错 */

    if(HAL_CAN_GetError(&hcan1) != HAL_CAN_ERROR_NONE) {

      HAL_CAN_ResetError(&hcan1);

    }

    __HAL_CAN_RESET_HANDLE_STATE(&hcan1); //

    /* CAN出错后重新配置CAN外设 */

    //bsp_can1Init();

  }

}


解决方法:将__HAL_CAN_RESET_HANDLE_STATE(&hcan1);也屏蔽掉,或者将can初始化函数取消注释。


关键字:STM32  使用过程  踩坑记录 引用地址:STM32使用过程中的踩坑记录

上一篇:stm32 bootloader启动正常,APP程序会在时钟配置出错原因分析
下一篇:彻底搞清printf在STM32上的使用

推荐阅读最新更新时间:2024-11-13 11:23

STM32-printf重定向到USART
在使用STM32的过程中,尤其是刚开始学习使用的时候,由于不知道自己的程序写的对不对,就经常需要一点验证的方法,点亮一个LED灯就是最简单的验证方法,但是有的时候还经常需要串口的输出来验证自己的程序是否正确,但是官方提供的函数库中用于串口发送的好像就一个USART_SendData(),通过外设USARTx发送单个数据,对于熟悉C语言的同学来说,这个函数还没有格式输出,当想要输出一个数字,或者字符串的时候,使用起来可能有点麻烦,现在有一个很好的方法就可以使用C语言中的printf()函数,而且使用方法是一样的。如何使用,很简单,我们只需要重新定向printf就可以,将它的数据用STM32的串口进行发送出去就可以了。 首先添加pr
[单片机]
STM32固件库中assert_param的作用
在学习stm32库函数过程中,笔者遇到大量的assert_param语句。经查明,assert_param的作用就是用来判断传递给函数的参数是否是有效值。 以下是从固件库中复制粘贴的: void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState) { assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { RCC- APB2ENR |
[单片机]
如何选择合适的MCU
什么是 STM32 STM32,从字面上来理解,ST 是意法半导体,M 是 Microelectronics 的缩写,32 表示 32 位,合起来理解,STM32 就是指 ST 公司开发的 32 位微控制器。在如今的 32 位控制器当中,STM32 可以说是最璀璨的新星,它受宠若娇,大受工程师和市场的青睐,无芯能出其右。 STM32 属于一个微控制器,自带了各种常用通信接口,比如 USART、I2C、SPI 等,可接非常多的传感器,可以控制很多的设备。现实生活中,我们接触到的很多电器产品都有 STM32 的身影,比如智能手环,微型四轴飞行器,平衡车、移动 POST 机,智能电饭锅,3D 打印机等等。下面我们以最近最为火爆的两个
[单片机]
如何选择合适的MCU
STM32之霍尔检测电机归位时掉电
一、简介 本文介绍如何在STM32上使用霍尔传感器模块检测电机运行位置,当电机归位时自动断开电源。 二、实验平台 库版本:STM32F10x_StdPeriph_Lib_V3.5.0 编译软件:MDK4.53 硬件平台:STM32开发板(主芯片stm32f103c8t6) 仿真器:JLINK 三、版权声明 四、实验前提 在进行本文步骤前,请先阅读并实现以下博文: 1、《STM32之系统滴答定时器》:http://blog.csdn.net/feilusia/article/details/52835711 2、《STM32之DRV8834电机驱动》:http://blog.csdn.ne
[单片机]
<font color='red'>STM32</font>之霍尔检测电机归位时掉电
STM32 NVIC中断优先级:抢占优先级&响应优先级区别
首先,对STM32中断进行分组,组0~4。同时,对每个中断设置一个抢占优先级和一个响应优先级值。 分组配置是在寄存器SCB- AIRCR中配置: 抢占优先级 & 响应优先级区别: 1. 高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。 2. 抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。 3. 抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个 先执行。 4. 如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先 执行; 等级越低,优先级越高。
[单片机]
<font color='red'>STM32</font> NVIC中断优先级:抢占优先级&响应优先级区别
STM32 TIM测 输入信号的 频率
说 不进中断 等等基本功能没实现ok的,查看: STM32 外设配置关键步骤 务必仔细瞅瞅… TIM输入捕获简介 TIM输入捕获两种模式: 1. PWM输入模式 2. 输入捕获模式 调试记录 PWM输入模式: 该模式的理解: stm32的PWM输入捕获模式 仅适用于通道1、 2 从输入捕获中断说起… 从TIM3 CH1输入信号, .............. if(TIM_GetITStatus(TIM3,TIM_IT_CC1) == SET) // { ic1 = TIM_GetCapture1(TIM3)+1; //周期 ic2 = TIM_GetCapture2(TIM3)+1; //脉冲宽度
[单片机]
<font color='red'>STM32</font> TIM测 输入信号的 频率
STM32外部晶振不起振
芯片:STM32F429 开发平台:Keil 问题: STM32外部晶振不起振,选择了内部16MHZ,从而导致延时函数、波特率、定时器等等有问题。 有源晶振和无源晶振的区别 有源晶振一般4个脚,一个电源,一个接地,一个信号输出端,一个NC(空脚)。有个点标记的为1脚,按逆时针(管脚向下)分别为2、3、4。 无源晶振有2个引脚,需要借助于外部的时钟电路(接到主IC内部的震荡电路)才能产生振荡信号,自身无法振荡. 单片机外部晶振接的是无源晶振,因此必须首先烧写程序进去,配置好相应的寄存器,晶振才会起振。如果没有烧写程序的新单片机(未配置寄存器)则不会起振。 由于我烧写过程序,并且程序在跑,只是时钟不对。因此进
[单片机]
<font color='red'>STM32</font>外部晶振不起振
如何设计一个以stm32为控制核心的数字示波器?
随着集成电路的发展和数字信号处理技术的采用,数字 示波器 已成为集显示、测量、运算、分析、记录等各种功能于一体的智能化测量仪器。数字示波器在性能上也逐渐超越模拟示波器,并有取而代之的趋势。与模拟示波器相比,数字示波器不仅具有可存储波形、体积小、功耗低,使用方便等优点,而且还具有强大的信号实时处理分析功能。因此,数字示波器的使用越来越广泛。目前我国国内自主研发的高性能数字示波器还是比较少,广泛使用的仍是国外产品。因此,有必要对高性能数字示波器进行广泛和深入研究。 本文通过采用高速高性能器件,设计了一实时采样率为60 msa/s的宽带数字示波器。 1 数字示波器的性能参数设计 数字存储示波器的指标很多,包括采样率、带宽、灵敏度
[测试测量]
如何设计一个以<font color='red'>stm32</font>为控制核心的数字示波器?
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved