![shequ.stmicroelectronics.cn](./template/st_v1/static/img/logo2.png)
1、 2、芯片STM32F103C8T6。 3、程序意图:(1)用TIM4产生1ms定时,在其TIM4_IRQHandler()中计数并设置70ms、500ms等定时器标记。(2)在main()的死循环子函数中,每70ms,读取编码器数值并显示在LCD上;每500ms,读取ADC数值并显示在LCD上,同时为了方便观察,闪烁LED灯。 4、故障现象:刚开始运行,正常,LED灯闪正常;一阵子后,LED灯不闪,“死机”了。 5、用debug方式运行,复现“死机”后,按Stop,cpu模式为Handler,异常中断号为46(TIM4),程序在0000 125A到0000 12A6之间循环, 访问内存地址2000 0032到2000 0035。 查map文件,并正常运行时,单步跟踪,2000 0032到2000 0035 对应 g_10msOK到g_500msOK; 正常运行时,单步跟踪,0800 125A到0800 12A6,是while(1){}中判断g_10msOK到g_500msOK的地方。 猜测,Thread模式时,地址是0800 125A,切换到Handler模式后,地址是0000 125A。 说明,“死机”后,while(1){}中判断是否70ms、500ms的代码还一直在跑,只是70ms、500ms的标记一直为0,所以没有执行点灯。 死机后,在TIM4_IRQHandler()加断点,并不触发。为什么? |
HAL库,驱动步进电机不转
HRTIM的互补模式下,无法实现下管峰值电流保护
STM32F407 用定时器控制SPI传输的相关问题
STM32f1内存映射问题
FLASH的地址怎么选择呢?
如何使用定时器在任意IO输出PWM
stm32f103c8t6检测正交编码器一样的配置用TIM3正常输出计数,用TIM2一直输出01
stm32定时器编码器模式可以做输出吗
stm32f103ze完整电路原理图下载。
关于STM32的PWM占空比设置
[md]SV,PendSV,SysTick系统自动设置其使能且优先级为0s0。 我自己的代码,优先级组2,USART1为3s3,TIM4为0s3,EXTI9_5_IRQn为1s1,EXTI15_10_IRQn为1s1。 TIM4中断程序中,更新70ms变量标记;EXTI中断程序中,更新编码器数值;main中,读取70ms变量标记值和编码器数值。都只是变量读写,没有看出死锁。 死马当活马医,尝试把上面几个中断的优先级统一设为0s0,居然不死机了! 再试,优先级统一设为1s0,还是死机。 再试,我虽然USART1、EXTI设置有使能中断,但没插串口、没插编码器,不会有中断吧?打断点,确实没有USART1、EXTI的中断,只有TIM4中断在跑。 中断的优先级统一设为0s0不死机,设为1s0会死机,这是为什么呢?
另外,TIM4这边只是看中断出门了没。我还查看NVIC这边,看中断进门了没。如上,中断使能ISER0、中断活动IABR0都是对的,说明NVIC对TIM4中断,是允许进门的,并且正在响应处理(活动)中。
sw.rar是我的代码工程压缩包,有7M多,怎么上传不了吗?
你可以借助断点看看是否落在那个Hardfault中断里了。
重点检查哪些地方涉及数组访问的,看看有无可能发生越界的情形,当然这也是常发生问题的地方。
再就是有无可能堆栈溢出了,尤其中断嵌套较多时。
再者,我也查看了中断向量表,TIM4是46号异常,对应向量表地址0000 00B8存放的入口地址是0800 3EAD,也就是TIM4_IRQHandler()的地址。说明向量表没有破坏。
根据《权威指南》说的,中断的活动状态寄存器IABR是硬件自动维护的,执行了ISR的第一条指令,活动状态置1,到ISR返回时,活动状态清0。我这里观察到活动状态为1,说明ISR没返回?但是单步跟踪,执行的是main()里面的while(1){}循环。这就怪了?
但是这里也有一个线索:死机后,stop,单步执行,执行代码地址是0000 125A;正常时,单步执行,执行代码地址是0800 125A。实际对应就是main()里面while(1){}判断70ms、500ms标志的代码。这部分代码应该是thread模式执行的,怎么到了handler模式?
1、供电和时钟目前看不是主因。因为我对软件做些改动的话,就不会出现死机。 2、在HardFault、MemManageFault、BusFault、UsageFault都加了断点,出现死机时,没有进入这些Fault,而且这些Fault的相关寄存器,也看起来是正常的。 3、我只用了TIM4和USART1这2个中断,而且TIM4优先级高。不应有嵌套的情况。
void TIM4_IRQHandler(void)
{
i70msCnt++;
if (i70msCnt == 70)
{
i70msCnt = 0;
g_70msOK = 1;
}
i500msCnt++;
if (i500msCnt == 500)
{
i500msCnt = 0;
g_500msOK = 1;
}
}
main()
{
while(1)
{
if (g_70msOK == 1)
{
g_70msOK = 0;
Timer_70ms_Proc();
}
if (g_500msOK == 1)
{
g_500msOK = 0;
Timer_500ms_Proc();
}
}
}
卧槽,这论坛,贴代码格式都很难,发压缩包又上不去。是程序猿论坛吗?
问题目前的小结: 1、死机时,TIM4相关寄存器正常,并置位了中断标记。NVIC允许TIM4中断进门,且表示TIM4正在处理中(活动状态置1)。 2、但是stop后单步跟踪,实际代码执行的是main() while(1){}的。这部分代码正常执行时是thread模式的,但现在是handler模式。 3、查看向量表,TIM4异常向量位置所放的地址就是TIM4_IRQHandler()地址,向量表没有被破坏。 4、所以,本应是执行TIM4_IRQHandler()的,怎么实际执行main() while(1){}?
[md]核心就是:死机后,stop并单步执行,看到是handler模式,且表示正在处理TIM4中断,中断向量表也没有被破坏,按理应执行TIM4_IRQHandler(),但执行代码实际对应的是main() while(1){},这是怎么回事啊?
[md]不用着急。
看看你到底开启了哪些中断,看看是否有在中断里需被使用的变量,因为中断优先级方面的原因导致变量信息的获取出现死锁。
比方,在中断A里调用B延时服务函数,B服务函数又需用到另一定时中断,可该定时中断优先级又低于A的,这时就会出现死锁。
还有,对于那些在中断和主程序里都使用的变量,记得加上volatile。