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.
工具/软件:Code Composer Studio
豪迪!
我正在尝试配置 Tiva TM4C23G 微控制器以1MHz 的频率收集电压样本。 我需要使用 ADC 对任意时间发生的脉冲进行采样、并将数据存储到后续存储中
分析。 但是、需要在后台由硬件尽可能处理采样、以便为其他任务释放 CPU。
此外、最好在脉冲发生之前有一种方法来获得多个数据点。
我目前认为、这可以通过使用计时器中断触发 ADC 采样并配置 UDMA 来收集样本来实现。 ADC 中断可以检测到该脉冲、
这将调用函数进行数据分析、或通过 UART 传输数据以在其他位置进行处理。 但我不确定如何配置 ADC 以如此高的速率进行采样、因此我完全不熟悉
UDMA。 有人能给我讲些什么吗? 简单的示例代码也会非常有用。
提前感谢您!
Derek Janak59.
Howdy Ralph、
感谢您的回答。 很抱歉、我的回复很晚;我更改了电子邮件、但在访问 E2E 帐户时遇到问题。
我一直在解决这个问题、我似乎让 uDMA 工作。 我似乎还实现了所需的1MSPS 采样率。 该代码适用于连续采样情况、但我现在正在尝试使用外部 GPIO 触发器触发1024个采样。 但是、我的 ADC 中断无法清除时、似乎存在问题。
我正在通过由引脚 B4生成的外部中断触发 ADC。 我删除了代码中与 UDMA 和采样相关的所有部分、我只关注 ADC 中断。 在引脚第一次触发中断后、该函数似乎会卡在中断中、并且中断标志将不会清除(ADCIntStatus 返回1)。 下面是相关代码:
void ADC0IntHandler() { uint32_t status; STATUS = ADCIntStatus (ADC0_BASE、0、TRUE); ADCIntClear (ADC0_BASE、0); //我尝试这样做是为了确保有足够的周期来清除中断标志。 SysCtlDelay (16000000u / 3U); } void ConfigureADC (void) { ADCSequenceConfigure (ADC0_BASE、0、ADC_TRIGGER_EXTERNAL、0); GPIOADCTriggerEnable (GPIO_PORTB_BASE、GPIO_PIN_4); ADCSequenceStepConfigure (ADC0_BASE、0、0、ADC_CTL_CH0); ADCSequenceStepConfigure (ADC0_BASE、0、1、ADC_CTL_CH1); ADCSequenceStepConfigure (ADC0_BASE、0、2、ADC_CTL_CH2); ADCSequenceStepConfigure (ADC0_BASE、0、9、ADC_CTL_CH3); ADCSequenceStepConfigure (ADC0_BASE、0、4、ADC_CTL_CH4); ADCSequenceStepConfigure (ADC0_BASE、0、5、ADC_CTL_CH5); ADCSequenceStepConfigure (ADC0_BASE、0、6、ADC_CTL_CH6); ADCSequenceStepConfigure (ADC0_BASE、0、7、ADC_CTL_CH7 |ADC_CTL_IE | ADC_CTL_END); ADCSequenceEnable (ADC0_BASE、0); ADCIntClear (ADC0_BASE、0); } void ConfigureInterrupts (void) { IntMasterEnable(); GPIOPadConfigSet (GPIO_PORTB_BASE、GPIO_PIN_4、GPIO_Strength _2mA、GPIO_PIN_TYPE_STD_WPD); GPIOIntTypeSet (GPIO_PORTB_BASE、GPIO_PIN_4、GPIO_FALLING_EDGE); ADCIntEnable (ADC0_BASE、0); ADCIntRegister (ADC0_BASE、0、ADC0IntHandler); } int main (void) { //将时钟设置为直接从晶体运行。 SysCtlClockSet (SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHz); //初始化并设置端口 PortFunctionInit(); ConfigureADC(); ConfigureInterrupts(); //在计时器运行时永久循环。 while (1) { 状态= ADCIntStatus (ADC0_BASE、0、TRUE); } }
尊敬的 Derek:
我缺少一些仍然像 PortFunctionInit 函数和用于 GPIO 触发器的 ISR 这样的信息、如果我也看不到这些信息、我很难获得完整的图片。
例如、似乎所有 SysCtlPeripheralEnable 都不存在、但我无法判断它们是否位于 PortFunctionInit 函数中。
此外、不确定这是否有帮助、但 E2E 上的其他人发布了 GPIO 触发 ADC 的代码: https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/430355/1543938#1543938
[引用 user="Derek Janak59">我将通过引脚 B4生成的外部中断触发 ADC。 在引脚第一次触发中断后、该函数似乎卡在中断中、并且中断标志将不会清除(ADCIntStatus 返回1)。[/quot]
这是一个"纯粹的"割道-但可能证明是一个"合理的"割道。 (有一个希望)
未提供任何证据表明您 的"PB4 GPIO 中断"已创建 、然后被处理-并被清除! 实际上、您已经很好地处理 了"ADC0的中断处理程序"、但 对于 PB4的 GPIO 来说、这不是! 虽然"未知"(至少不清楚)、但如果此类 PB4中断被证明是有用的(或必需的)-您在 ADC0中断中的"进入"、 然后"离开失败"-(可能)表示 (某些)中断之间的链接... (我注意到,没有其他"合理"的理论得到发展!)
为了进一步 "促进我的理论"-我在 TM4C123手册中介绍了这个"摘要": (注意: 下面是真实副本:)
10.2.2.1 ADC 触发源
'任何 GPIO 管脚都可以通过 GPIO ADC 控制 (GPIOADCCTL)寄存器配置为 ADC 的外部触发。 如果 GPIO 被配置为非屏蔽中断管脚( GPIOIM 中相应的位被置位)、 并且该端口产生中断、 那么触发信号就会发送到 ADC。
如果 ADC 事件多路复用器选择(ADCEMUX)寄存 器配置为使用外部触发器、则启动 ADC 转换。 见833页。"
实际上、您已经利用了"PB4 的"ADC 触发能力" (以及良好的触发能力)、但 "可能 无法解释" 没有 "PB4的处理程序及其服务!" (也许...) (注意:割道边南悬挂-吹硬启动板...)
由于这是一个由 TI 运营的论坛、我必须谨慎对待我所说的内容-我曾因 TI 员工表示不同意而受到警告。
因此,我建议你回到我先前建议的内容:这些词是仔细选择的。 阅读线路之间的内容、倾听未说的内容。
如果您幸运、一些 TI 员工可能会为您提供以1Msps 运行 ADC 的简短代码、以便您进行实验。
祝你好运。
海报 Danny (未解决)-最近的帖子-关注问题。
"降低 MCU 运行速度"的建议-"简化任务成功"-绝不会贬损(任何)供应商! 相反、这是一种长期、高度成功且众所周知的"诊断技术"、我知道这是一种"标准操作程序"、在全球的大公司和小公司都是如此。
丹尼(最近一次)的写作背景不清楚。 我撰写这篇文章是为了确保"高度正确和适当"的诊断方法(减慢 MCU 执行速度) 不会被(不公平)拒绝...
尊敬的 Derek:
进一步查看您的代码、我想知道此调用是否需要从 ConfigureADC 函数转移到 ConfigureInterrupts 函数。 ConfigureInterrupts 函数用于设置 GPIO 引脚类型、我想知道这是否会导致冲突。 现在、我在您的实现中看到的主要区别是、示例代码(假定)的作用是函数调用的顺序。
GPIOADCTriggerEnable (GPIO_PORTB_BASE、GPIO_PIN_4);
不过、我同意 Danny 和 CB1的看法、即立即将其设置为1MHz 采样并不是最佳方法。 我建议使用较低的速率、让我们确保您可以正确地整体触发 ADC、然后您可以提高速度。
我将尝试运行您的代码和我在明天之前引用的示例的精简版本、以查看其他可能发生的情况。
Howdy All、
我之前曾尝试通过包括延迟、while 循环以及其他代码来减慢 ISR 的执行速度。 问题不在于 ISR 的执行速度。 此外、这个问题与使 ISR 运行得更快无关;它是为了尝试清除中断标志。
重申一下:以1MSPS 的速率运行 ADC 不再是一个问题; 它正在清除外部引脚中断、这会导致困难。 此外、我已经能够验证 PB4只能看到一个边沿。 请通读我之前的帖子、了解我已经尝试了哪些解决方案;我收到的许多建议与上面列出的我自己的调试尝试没有什么不同。
下面是先前请求的 PortFunctionInit()代码:
void PortFunctionInit(void){ // //启用外设时钟 // SysCtlPeripheralEnable (SYSCTL_Periph_ADC0); SysCtlPeripheralEnable (SYSCTL_Periph_ADC1); SysCtlPeripheralEnable (SYSCTL_Periph_UART0); SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA); SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB); SysCtlPeripheralEnable (SYSCTL_Periph_GPIOC); SysCtlPeripheralEnable (SYSCTL_Periph_GPIOD); SysCtlPeripheralEnable (SYSCTL_Periph_GPIOE); SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF); // // ADC AIN2的使能引脚 PE1 // GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_1); // // ADC AIN3的使能引脚 PE0 // GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_0); // // ADC AIN4的使能引脚 PD3 // GPIOPinTypeADC (GPIO_PORTD_BASE、GPIO_PIN_3); // // ADC AIN8的使能引脚 PE5 // GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_5); // // ADC AIN10的使能引脚 PB4 // GPIOPinTypeADC (GPIO_PORTB_BASE、GPIO_PIN_4); // // ADC AIN6的使能引脚 PD1 // GPIOPinTypeADC (GPIO_PORTD_BASE、GPIO_PIN_1); // // ADC AIN1的使能引脚 PE2 // GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_2); // // ADC AIN11的使能引脚 PB5 // GPIOPinTypeADC (GPIO_PORTB_BASE、GPIO_PIN_5); // // ADC AIN7的使能引脚 PD0 // GPIOPinTypeADC (GPIO_PORTD_BASE、GPIO_PIN_0); // // ADC AIN5的使能引脚 PD2 // GPIOPinTypeADC (GPIO_PORTD_BASE、GPIO_PIN_2); // // ADC AIN0的使能引脚 PE3 // GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_3); // // ADC AIN9的使能引脚 PE4 // GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_4); // //为 GPIOInput 启用引脚 PC5 // GPIOPinTypeGPIOInput (GPIO_PORTC_BASE、GPIO_PIN_5); // // GPIOOutput 的使能引脚 PF1 // GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_1); // // GPIOOutput 的使能引脚 PF3 // GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_3); // //为 GPIOOutput 启用引脚 PF2 // GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_2); // // UART0 U0RX 的使能引脚 PA0 // GPIOPinConfigure (GPIO_PA0_U0RX); GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0); // // UART0 U0TX 的使能引脚 PA1 // GPIOPinConfigure (GPIO_PA1_U0TX); GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_1); }
感谢大家的帮助!
此致、
Derek
[引用 user="Derek Janak59"]请通读我之前的帖子,了解我已经尝试了哪些解决方案;我收到的许多建议与我自己的建议没有什么不同
您是否可以考虑以下事项:
我不相信这里的人会要求您" 降低 仅 ISR 的执行速度"-相反- 降低整个 MCU 的代码执行速度 (通过系统时钟设置) 影响(大部分)一切的因素、以及(几个)在这里的经验、相信 (可能)会证明是有启发性的。 (当前 (其他)"尝试" 尚未成功-因此此请求...)
尊敬的 Derek:
感谢您的分享、我能够运行您的代码、我想我已经解决了这个问题。
对于中断启用、您似乎需要另一个看起来不存在的 API 调用:
IntEnable (INT_ADC0SS0);
我在中添加了该值后、看起来 INT 会成功清除。