This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] EK-TM4C1294XL:ADC -中断和程序被卡住

Guru**** 2325040 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/588816/ek-tm4c1294xl-adc---interrupts-and-program-stuck

器件型号:EK-TM4C1294XL

大家好、

我将面临一个有关 ADC 的奇怪问题。 我想尽快转换温度传感器的 X 倍(在将来它将是一个模拟信号)。 因此、我启用 ADC、使用 ADC 处理程序和中断将结果放入全局变量中、我想等待我的 X 样本。 但是、即使完成了样本、我也无法使用循环来等待 X 样本的末尾。 我不明白为什么代码在采样结束后卡住。

实际上、如果我将行放在while(adc_seq < 1000{}主代码的末尾以等待采样结束、那么代码就会卡住。 如果我不使用该行、则它可以正常工作。 我必须确保在开始剩余代码之前完成 X 个样本、因此我必须等待。 有人有想法吗?

提前感谢

静态 int adc_seq = 0;
静态 uint32_t adc_data[1000];

void adC0seq3_Handler (void){
uint32_t ADC0Value[1];
ADCSequenceDataGet (ADC0_BASE、3、ADC0Value);//检索值。
ADC_DATA[ADC_SEQ]=(1475 -((2475 * ADC0Value[0]))/4096)/10;//数据表中的公式 VNREF 0和 VREFP 3.3全部*10以避免小数。
if (ADC_SEQ < 1000){// ADC 必须仍然工作
ADC_SEQ++;
ADCIntClear (ADC0_BASE、3);
}
否则{//在1000个样本后禁用 ADC
ADCSequenceDisable (ADC0_BASE、3);
}
}

void InitConvertADC (void){
SysCtlPeripheralEnable (SYSCTL_Periph_ADC0);//启用 ADC0。
while (!SysCtlPeripheralReady (SYSCTL_Periph_ADC0)){}//等待 ADC0就绪。
ADCSequenceDisable (ADC0_BASE,3);//序列发生器必须在 ADC0的 config:SS3之前被禁用
ADCIntDisable (ADC0_BASE、3);//禁用 ADC0中断
IntDisable (INT_ADC0SS3_TM4C129);//禁用 ADC0序列3的中断功能
ADCClockConfigSet (ADC0_BASE、ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_FULL、1);
ADCSequenceConfigure (ADC0_BASE、3、ADC_TRIGGER_AUSE、0);//使用 ADC0、 采样序列发生器3始终触发
ADCSequenceStepConfigure (ADC0_BASE、3、0、ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END);
ADCIntClear (ADC0_BASE、3);//清除中断标志。
IntEnable (INT_ADC0SS3_TM4C129);//启用中断功能。
ADCIntEnable (ADC0_BASE、3);//启用序列发生器中断。
ADCSequenceEnable (ADC0_BASE、3);//启用序列发生器 ADC0 seq3.
}

int main (void)
{
while (ADC_SEQ < 1000){
ADC_DATA[ADC_SEQ]= 0;
ADC_SEQ++;
}
ADC_SEQ = 0;//复位 ADC_SEQ

BoardInit();//初始化板。
CONsComInit();//通过 UART0初始化与计算机的通信。

UARTprintf ("\033[2J\033[H");
UARTprintf ("test\n\n");//打印横幅

InitConvertADC(); //开始转换
while (ADC_Seq < 1000{} //如果使用此行,则代码被卡住,我再也不会走远了。 如果未使用、则可以正常工作。
UARTprintf ("\n 模数转换现已完成\n");

} 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用用户="Nicolas Demonty"]

    if (ADC_SEQ < 1000){// ADC 必须仍然工作

    ADC_SEQ++;

    ADCIntClear (ADC0_BASE、3);}[/引述]

    该代码最终不会(提前)将"ADC_SEQ"更改为"1000?"   当 ADC_SEQ = 999时、该值将递增。

    然后-当您雇用:

    while (ADC_Seq < 1000{}

    当 ADC_SEQ 等于1000时、该"while"循环不再为真。   

    您不应该"监控"ADC_Seq -以便您知道您的程序正在正确处理该变量吗?   在您的帖子中、不会出现此类提及。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    我同意 CB1关于您在中断例程中的代码。 但我还有其他一些观察结果:您应该清除 if-else 块之外的 ADC 中断-只清除 if 子句中的中断、而不清除其他中的中断;当代码执行 else 子句时、中断不会被清除、并且可能导致重新进入中断、并在输入到输出之间旋转。

    此外、您的程序结构不好:

    1. ADC_DATA 数组的初始化代码可以更简单地编写为:static uint32_t adc_data[1000]=0;编译器将根据需要初始化数组。
    2. 您在最后一行之后退出程序、就像在 PC 程序中一样-这种情况并非如此、您没有操作系统、因此您必须在结尾处有一个表达式:while (1){} 否则、这将导致故障。
    3. 您的转换不需要达到最高速率-从控制 ADC 转换的计时器开始、在开始时使用较低的速率、直到您的程序"工作"、然后您可以提高速率。 在实践中、模拟信号的采样频率应略高于最高频率分量的2倍(例如4x...5x)、且带宽受限。 也取决于您对该信号执行的操作。

     

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    高 CB1、高 Petrei、

    感谢您花时间回答问题。 下面是有关我要做什么、要避免什么以及我已经测试过什么的更多问题。

    实际上、在全速率采样时、所有1000个中断的发生速度都比之后代码的执行速度快、但如果我降低采样率、我恐怕会在两个采样之间执行下一个代码。 在执行下一个代码之前、我确实需要100%地确保完成1000个采样。 这就是我需要等待 ADC_SEQ 达到1000的原因。

    要回答有关 ADC_Seq 的注释,有两种情形:

    1、采样速度快、中断发生速度快、不会在1000个采样之前到达 while (ADC_SEQ < 1000)行。 如果 ADC_Seq 等于1000、则不满足"while"、因此应跳过它并执行最后一个 UARTPrint 命令。 这种情况就是我的程序中发生的情况。 我是说 ADC_Seq 达到1000、但"while"似乎会阻止程序、而我的最后一个 UARTPrint 从未完成。

    采样太慢、我们在两个中断之间达到 while (ADC_SEQ < 1000)。 然后、它应该在一个环路中等待所有中断完成。 我的计划中目前尚未满足这种情况。

    我想提出以下几点:

    -我通过在 ADC 处理程序"IF"条件中显示所有 ADC_Seq 值进行了测试、直到999

    -我还通过在 ADC 处理程序"else"条件下显示 ADC_Seq 进行了测试、它是1000、这是正确的。

    -我必须确认(因为我不记得)、但是如果我只是在"while (ADC_Seq <1000)"等待循环中添加一个 UARTPrint、那么它就可以工作了。

    可能是我错了、但我感觉我们在 ADC_SEQ = 0时进入了循环、并且在循环检查下一次 ADC_SEQ 由于所有中断而变为1000之前进入了循环。 我很难解释我的意思,但我认为在以下情况下会有问题:

    1. ADC_SEQ =0:进入 while 循环
    完成1000个中断并禁用采样

    ADC_SEQ = 1000、while 处于不相干状态。

    在进行1000次采样后、确定 ADC_Seq 为1000。 ADC 处理程序中的"else"条件完成。 但该"while"循环就像卡滞。

    kr

    Nicolas

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您-感谢您的回复和详细信息。

    现在-我特别喜欢朋友 Petrei's、"guidance #3"、它非常同意"kis"。 他建议您:"在您将所有元素"混合"之前、请单独缓慢、简化并测试/验证程序的每个元素(部分)。

    另请注意-使用 UART 会始终给程序增加大量的时间延迟-并且可能会中断(任何/所有)需要"合理快速且完整"执行的例程。

    我是否可以建议 LED 闪烁替代 UART 的使用-至少直到您的程序按需要执行...
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="Nicolas Demonty"]static int ADC_Seq = 0;[/quot]如果 ADC_Seq 由中断例程写入、并在主函数的 while 循环上进行轮询、则应将变量声明为 volatile。 即使用:

    静态易失性 int ADC_SEQ = 0; 

    否则、编译器优化器可能会将以下内容转换为无限循环、因为它可能会得出结论:在 while 循环之外不会更改 ADC_Seq:

    while (ADC_Seq < 1000{} //如果使用此行,则代码被卡住,我再也不会走远了。 如果未使用、则可以正常工作。 

    [此外、发布代码中的上述 while 循环看起来无效 C、因为缺少右括号]

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、

    感谢您的提示和解决方案。 明天我会试着回来。

    对于缺少的括号、我在论坛帖子中复制了代码时、这是一个拼写错误。

    谢谢

    Nicolas