程序写好后发现有一定几率上电后看门狗复位,然后屏蔽看门狗,用定时器控制灯闪烁作为指示,主循环里串口每隔一秒输出一句话;
发现有一定几率主循环里不走,但定时器控制的灯正常闪烁。程序不知道停在哪里了。
然后把主循环里的语句逐句屏蔽掉,最后发现可能是ADC这部分的问题。
ADC这里是这样实现的,只用了STM32的1个ADC引脚,用多路模拟开关来切换外部多个输入信号。
之前ADC的DMA传输就没搞明白,在主循环外开启DMA后,发现读写spi flash异常慢,后来关掉ADC的DMA后正常了。
于是不敢一直开启DMA,而是在主循环里进行ADC读取前开启DMA,读取后再关闭DMA。
请教下大家,问题可能出在哪里?到底程序停在了哪里?
- void GetAdcValue(void)
- {
- uint8_t i, j;
- ADC_ChannelConfTypeDef sConfig;
- sConfig.Channel = ADC_CHANNEL_8;
- sConfig.Rank = ADC_REGULAR_RANK_1;
- sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
- if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
- _Error_Handler(__FILE__, __LINE__);
- HAL_ADC_Start_DMA(&hadc1, (uint32_t *)(&adc_Xin_value[0]), 1);
- for(i = 0; i < 8; i++)
- {
- CD4051_XIN(i);
- adcCompletFlag = 0;
- HAL_Delay(1);
- // if (1 == adcCompletFlag)
- adcXinVoltage[i] = adc_Xin_value[0]*2500/4095;
- //HAL_IWDG_Refresh(&hiwdg);
- }
- sConfig.Channel = ADC_CHANNEL_9;
- if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
- _Error_Handler(__FILE__, __LINE__);
- for(i = 0; i < 8; i++)
- {
- CD4051_XIN(i);
- adcCompletFlag = 0;
- HAL_Delay(1);
- // if (1 == adcCompletFlag)
- adcXinVoltage[i+8] = adc_Xin_value[0]*2500/4095;
- //HAL_IWDG_Refresh(&hiwdg);
- }
- HAL_ADC_Stop_DMA(&hadc1);
- }
复制代码
|
开DMA后,主循环是会变慢。
因为DMA和系统总线是复用的,只不过DMA最大能占到二分之一的带宽,至少要给系统留二分之一的带宽。具体DMA带宽分配,是内核仲裁的,外界干涉不了。
评分
查看全部评分
是这个原因吗?必须等EOC标志才能读吗?
我在主循环前开启ADC的DMA功能后,其后的读取spi flash芯片的执行速度,就非常慢了。
所以我现在在主循环里的需要读取adc值时才开启ADC的DMA传输功能,读取完后再关闭。
没想到有几率上电卡死。
那么,我现在的情况应该适用于在主循环里反复开启观点ADC的DMA吧。
能否帮分析下我的程序卡死的情况?
慢慢排查吧。
双以往经验来看,你的问题并不是出在你以为会有问题的地方。
你说的主循环里不走,那么程序进没进去主循环呢?如果进了主循环,而不走的话,看看哪块有死循环,而没有超时退出机制;如果都没进主循环,那么在前面排查。
仿真调试,多个LED灯指示程序运行的不同位置,串口打印等,都是调试手段。
屏蔽掉大部分功能,现在只剩adc部分和串口和定时器了。串口只是用来定时输出信息看主循环有没有死掉,定时器...
定时器没有把定时中断里的所有语句都屏蔽掉,这么说也有可能是定时器中断的问题。不过定时器中断里只是累加一个变量,然后通过这个变量除10、100、1000来得到其它时间基准。主要是定时中断里控制的led灯能正常反转,所以觉得定时器出问题的可能性也不大。
我还是怀疑是反复开启关闭dma造成的。