由于误操作,提前发了。会持续更新
一、与编译有关
1,C++
布尔变量,只能非不能取反,否则会由一真一假变为两真一假。
2,优化问题
3,执行代码,卡在b.n 0x8000492 <__aeabi_dadd+18>,有时候是+20
把CMakeLists中的浮点fpu关了就行
4,刚初始化就卡死
改成非易失性即可,防止被编译器优化
volatile uint32_t tickstart, pll_config;
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芯片烧录区域损坏。
忙了半个多小时,才回想起似乎遇到过这种情况,但不记得怎么解决的了。查了以前的日志发现自己根本没记录下来,那么就说明解决过程应该非常简单,于是果断尝试了一下重启大法。。。果然,方向不对,一切白搭