BUG_STM32开发_琐碎问题

由于误操作,提前发了。会持续更新

一、与编译有关

1,C++

布尔变量,只能非不能取反,否则会由一真一假变为两真一假。

2,优化问题

1c4ee54d82b64b74a88a32bc70159c01.png96ccebb871f0483fb7cc413741c5902e.png

3,执行代码,卡在b.n 0x8000492 <__aeabi_dadd+18>,有时候是+20

把CMakeLists中的浮点fpu关了就行

f5ff402818214d869c348b649433805f.png

4,刚初始化就卡死

改成非易失性即可,防止被编译器优化

volatile uint32_t tickstart, pll_config;

74051b4b2bc54ece9c7f642e9b153ed9.png

5,十分隐晦的C/C++混编问题

错误如下

 代码如下

#ifndef _My_KEY_H_
#define _My_KEY_H_

#ifdef __cplusplus
extern "C"
{
#endif

#include "stm32f4xx.h"
/*KEY引脚定义
//KEY_S1      PF8
//KEY_S2      PF9
//KEY_S3      PF10
*/
#define KEY_S1_READ() GPIO_ReadInputDataBit(GPIOF, GPIO_Pin_8)
#define KEY_S2_READ() GPIO_ReadInputDataBit(GPIOF, GPIO_Pin_9)
#define KEY_S3_READ() GPIO_ReadInputDataBit(GPIOF, GPIO_Pin_10)

void KEYGpio_Init(void);
uint8_t newKeyScan(void);

#ifdef __cpluscplus
}
#endif
#endif

在C++文件中包含C头文件,本来是不应该有任何错误的。

结果是最后的宏定义拼写错了

#ifdef __cplusplus
}
#endif
#endif

6,过度使用inline

        由于这个inline只是提示编译器使用内联,所以如果你直接大把大把地把函数定义为内联,那么调用内联的地方会报错。因为编译器不打算展开成内联了

error: 'StorageManage_M25P16_EraseAll' was not declared in this scope; 
did you mean 'StorageManage_M25P16_Index_StartAddr'? 
36 | StorageManage_M25P16_EraseAll(); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | StorageManage_M25P16_Index_StartAddr 

7,error: #include nested depth 200 exceeds maximum of 200 (use -fmax-include-depth=DEPTH to increase the maximum)

头文件递归包含导致的错误,其实就是头文件自己包含自己,使用C99标准时好像没有报这个错

8,找不到g++编译器

在配置交叉编译工具链时,明明安装了g++却找不到,可能是安装了多个版本的交叉编译工具链。配置环境变量时最好只用一个版本的交叉编译工具链,否则容易出现找不到的问题。

二、与单片机有关

 1,定时器调不了频率

下面代码曾是从STM32CubeMX里整理的,测试语音播放时才发现时钟频率怎么都调不了


    TIM_MasterConfigTypeDef sMasterConfig = {0};

    htim6.Instance = TIM6;
    htim6.Init.Prescaler = psc;
    htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim6.Init.Period = arr;
    htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    HAL_TIM_Base_Init(&htim6);

    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
    HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig);

    __HAL_RCC_TIM6_CLK_ENABLE();
    HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 6, 0);
    HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);

把时钟激活调前就行了

    __HAL_RCC_TIM6_CLK_ENABLE();
    TIM_MasterConfigTypeDef sMasterConfig = {0};

    htim6.Instance = TIM6;
    htim6.Init.Prescaler = psc;
    htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim6.Init.Period = arr;
    htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    HAL_TIM_Base_Init(&htim6);

    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
    HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig);


    HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 6, 0);
    HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);

2,DAC输出电压与值成“负比例”

        开启输出缓存后输入的数据为补码形式,不开则输入正常数值即可(本设备stm32f407是这样,其它设备不清楚)。这是在使用wav文件中PCM数据时遇到的,由于PCM数据为补码形式存在,使用DAC输出时要开启输出缓存,同时输出缓存可以提升音质。

3,RTOS环境下使用SPI_FLASH的擦除不等待

原因,时间片调度引起的,需要在这个地方加个临界区保护代码。

inline void SPI_FLASH_WaitForWriteEnd()        // 等待写完成
{
    uint8_t FLASH_Status;
    SPI_FLASH_CS_LOW();
    SPI_FLASH_SendByte(ReadStatusReg); /* 发送 读状态寄存器 命令 */
    do
    {
        taskENTER_CRITICAL();//记得引入头文件task.h和FreeRTOS.h
        FLASH_Status = SPI_FLASH_SendByte(Dummy_Byte);
        taskEXIT_CRITICAL();

    } while (FLASH_Status & WIP_Flag);// 检测BUSY位是否为0,0表示已完成不忙
    SPI_FLASH_CS_HIGH();
}

4,卡死在configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );

        单片机日常犯抽,检查多次,明明外部中断中断优先级配置没有问题,但是依旧会卡死在这,而且获取的优先级和我配置中的不同就挺诡异。

        把这句直接注释掉之后就能正常运行了,What can I say ?

5,配置好FSMC后,LCD没有任何反应

        LCD的背光引脚忘了初始化

6,按键外部中断无反应

初学者最容易忽视上下拉模式,由于按键一般都是接个上拉电阻,所以上下拉模式要选择上拉,不然GPIO引脚一直为低电平,自然就无法产生下降沿

GPIO_InitStruct.Pull = GPIO_PULLUP;

7,初始化UART时,触摸屏不能使用

        诸如此类,多半是引脚配错了,这会导致其他功能异常

8,多线按键中断卡住

        当你开启了8和9的外部中断,那么就得在这里同时把8和9给清除了,当然也可以自己改一下HAL_GPIO_EXTI_IRQHandler。如果只写HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8);那么另一个引脚由于没有清除中断线则会导致外部中断一直触发。

        至于这几个引脚怎么区分,可以通过IDR或者别的什么方法。

void EXTI9_5_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8|GPIO_PIN_9);
}

可以用这个HAL_GPIO_EXTI_IRQHandler,也可以直接把里面的清除标志位什么的拿出来

void EXTI9_5_IRQHandler(void)
{
    if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_8)!= RESET)
    {
        HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8);
    }
    else if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_9)!= RESET)
    {
        HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9);
    }
}

9

9,初始化外设后等待读取卡住

        具体事例是,对DHT11初始化后,读取第一个字节就发生了问题,可是时序、引脚、连线等等配置都没有出现问题,但是一烧录完后就会出现卡死的现象,而且使用keil时会出现,使用CLion则不会出现。

        后来再仔细排查中发现,使用keil烧录时,不知道是不是因为配置的原因,烧录后本该初始化的引脚在烧录过程前后或者启动调试时,配置的引脚在没有初始化、程序还没运行时就会出现电平乱跳的情况,CLion则不会出现。正是这个原因,导致烧录过程前后,DHT11误接了“开始信号”然后输出,等到烧录完成后,经由真正的初始化和开始信号后,准备读取数据时,就会导致无法给出预期的响应,从而造成卡死现象。

解决:        先拔下相应外设,然后启动调试,并设置断点到对应功能函数的执行的地方,让程序运行到此处。之后再插上外设,移除断点,并开始运行。

        其实,在那个功能函数运行之前,加个延时就可以了。

10,程序卡在taskSELECT_HIGHEST_PRIORITY_TASK(); 

        如果优先级配置正确的话,有可能是你在临界区里使用与FreeRTOS中断有关的东西,比如osDelay

11,osDelayUntil不能正常阻塞

        找了许久没有找到原因,最后在正点原子论坛里找到了。osDelayUntil不能直接像osDelay那样使用,而是需要以下面这种形式

uin32_t pxPreviousWakeTime = xTaskGetTickCount();
 xx;
 xx;
 xxxxx;
osDelayUntil(pxPreviousWakeTime+100);

同时需要包含两个头文件,顺序不能反

#include "FreeRTOS.h"
#include "task.h"

12,RT-Thread移植时启动文件出现 thumb conditional instruction should be in IT block

CMakeLists里的 开启浮点运算注释掉

如果你没注释掉FPU,并且开启了下面的soft模式,则会出现 千行报错

正确的配置应为

同时也要注意,如果你使用的是GCC编译器,那么就需要改一下启动文件

//修改前:
  bl  SystemInit
  bl  main

//修改后:
  bl  SystemInit
  bl  entry            /* 修改此处,由 main 改为 entry */

13,RT-Thread线程创建后无法进入

线程优先级项默认为8个,如果你创建的线程优先级大于这个就会导致无法启动线程。可以到rtconfig.h里修改

#define RT_THREAD_PRIORITY_MAX  32

14,GDB调试Connection Timeout,并且ST-Link的灯变绿

        重启一下电脑电脑就行了。情况十分离谱,这是我第二次中招了,第一次花了一下午。这一次,各种查资料、各种方面去猜测,使用ST官方调试工具没问题,OpenOCD烧录也没问题,但GDB调试就超时。一开始把重点放在代码上,以为是代码相关的原因,甚至怀疑是不是stm32芯片烧录区域损坏。

        忙了半个多小时,才回想起似乎遇到过这种情况,但不记得怎么解决的了。查了以前的日志发现自己根本没记录下来,那么就说明解决过程应该非常简单,于是果断尝试了一下重启大法。。。果然,方向不对,一切白搭

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值