TI E2E™ 设计支持论坛将于 5 月 30 日至 6 月 1 日进行维护。如果您在此期间需要技术支持,请联系 TI 的客户支持中心寻求帮助。

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.

[参考译文] TM4C123GH6PM:使用 ADC 的2个通道同时对 GPIO 模拟引脚的2个信号进行采样

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/739825/tm4c123gh6pm-sampling-2-signals-from-gpio-analog-pin-using-2-channels-of-adc-simultaneously

器件型号:TM4C123GH6PM
主题中讨论的其他器件:TM4C123

嗨!

我想在2个不同的模拟引脚(例如 PE2和 PE3)中输入2个不同的样本、然后进行经皮采样以在 UART 上打印、但我不知道如何配置 ADC。 有什么帮助? 注释代码和函数说明(例如、什么是序列发生器、如何将通道连接到 GPIO 引脚 以及如何使用 ADCSequenceStepConfigure 函数)将是极好的! (我曾尝试阅读一些论坛和 Tiva Ware 外设驱动程序的库文档、但我无法实现任何目标。 谢谢!

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

    您好!

     中有 TivaWare ADC 示例 /examples/peripherals/adc/single_ended.c。 尽管这仅采用一个模拟输入、但您可以将其扩展为采用多个通道。 我建议您先运行此示例、以了解 ADC 和 TivaWare 的工作原理、然后再扩展到多个通道。 以下代码适用于两个通道。  

    SysCtlPeripheralEnable (SYSCTL_Periph_ADC0);
    
    
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOE);
    
    GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_3 | GPIO_PIN_3);
    
    ADCSequenceConfigure (ADC0_BASE、0、ADC_TRIGGER_PROCESSOR、0);
    
    
    ADCSequenceStepConfigure (ADC0_BASE、0、0、ADC_CTL_CH0);
    
    ADCSequenceStepConfigure (ADC0_BASE、0、1、ADC_CTL_CH1 | ADC_CTL_IE |
    ADC_CTL_END);
    
    ADCSequenceEnable (ADC0_BASE、0);
    
    ADCIntClear (ADC0_BASE、0); 

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

    我还尝试从 GPIO 引脚采样2个模拟信号。 我已对 TivaWare 外设单端示例应用了您建议的更改、它似乎正在读取两个通道。

    我的问题是、我注意到一个通道似乎对另一个通道(串扰?)有很大影响。 例如、我将在通道0上读取~1500个计数、在通道1上读取~300个计数、如果通道0增加到~2500个计数(由输入的变化而产生)、则通道1将增加~100个计数、而不会改变通道1的输入。

    这是正常的吗? 是否缺少某些配置?

    谢谢、

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

    您好!

     引脚 PE3有勘误表。 请参阅下面的说明和解决方法。 如果可能、您还可以避免将 PE3用于 AIN0采样。 例如、使用 launchpad 上的 PE2和 PE1对两个模拟输入进行采样。

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

    查尔斯

    我已切换到 PE2和 PE1。 这似乎解决了我的问题、因为两个通道相互影响。 然而、尽管输入非常稳定、它们仍会波动近100个计数(我通过简单设置了几节1.5伏电池和一个分压器来查看通道如何响应)。 我应该期待不同的结果吗? 是否有必要进行硬件或软件过采样以获得更稳定的计数?

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

    您好!
    您是如何构建分压器的? 如果没有分压器、您能否馈入小于3.3V 的输入、您是否看到波动? 您 kΩ 在 ADC 输入与接地之间使用一个低值电阻器、理想情况下小于1k Ω。 请参阅 ADC 部分中的 TM4C123系统设计指南。 低电阻有助于将您的输入电压与内部采样电容器进行电荷耦合。

    www.ti.com/.../spma059.pdf

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    分压器之前由4.7kOhm 电阻器构成。 我切换到1kOhm、没有差异。 我还直接从电池向输入提供了1.5伏电压、并且仍然可以看到高达60个计数的波动。 我还加入了.47ufarad 电容器、但这似乎也没有改变结果。 还有其他建议吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    作为后续操作、当我将输入对地短路时、我会得到~30计数的波动。 如果我的硬件对64个样本进行过采样、它会稳定在大约10个计数、并在1或2个计数之间波动。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这对我来说毫无意义。 您是否有其他板可供尝试?

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

    嘿、Charles

    嗯、首先、谢谢、但我的系统中有一个问题。 我想将 CH0属性为 PE1、将 CH1属性为 PE2。 但是,当我将信号源连接到 PE3时,它也会读取。 我该怎么做才能停止读取它? 以下是我的代码:

    SysCtlPeripheralEnable (SYSCTL_Periph_ADC0);//启用 ADC0模块。
    
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOE);//在
    
    GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_2| GPIO_PIN_1)中为模拟启用 GPIOE;
    
    ADCSequenceConfigure (ADC0_BASE、3、ADC_TRIGGER_processor、0);
    
    ADCSequStepConfigure (ADC0_BASE、 3、0、ADC_CTL_CH0 | ADC_CTL_IE |
    ADC_CTL_END);
    ADCSequenceEnable (ADC0_BASE、3);
    
    ADCIntClear (ADC0_BASE、3); 

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

    首先、不能使用序列发生器3对多个通道进行采样。 这已经是错误的。 序列发生器3仅支持一个通道。  对于两个通道、您可以使用序列发生器0、1或2。 请先修复此问题、然后重试。 我认为您应该获得更好的结果。

    前面我建议您按原样尝试 TivaWare 示例。 您有机会这样做吗? 您是否正确测量了电压?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    还可以! 我要这个。 再次感谢你。 我还尝试了 TivaWare 示例。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    嘿、Charles
    我已经尝试过该示例、我已经完成了您建议的更改。 尽管如此、问题是相同的-通道相互干扰。 另一件事是、我想知道如何将通道属性分配给 GPIO 引脚、例如、如何将通道0显性地用于 PE1、将通道1显性地用于 PE2?
    非常感谢!!
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您的代码有另一个问题。 请参阅以下映射。 如果您要使用 PE2和 PE1、则它们会映射到 AIN1 (通道1)和 AIN2 (通道2)。

    AIN1 -> PE2
    AIN2 -> PE1

    假设您已经在其他任何地方更改为序列发生器0、1或2、则您应该具有如下所示的代码。 假设您使用序列发生器0、那么您将进行写入。
    ADCSequenceStepConfigure (ADC0_BASE、0、0、ADC_CTL_CH1);//将 AIN1映射到 SS0的第0步
    ADCSequenceStepConfigure (ADC0_BASE、0、1、ADC_CTL_CH2 | ADC_CTL_IE | ADC_CTL_END);//将 AIN2映射到 SS0的第1步,并使该通道成为序列发生器中的最后一步,并在序列发生器完成时产生中断
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    嘿、Charles

    我已经做了很多修改、但我的所有通道都相互干扰、即使 PE3也在这样做、尽管我不使用它。

    以下是我的代码:

    void init_adc (void)
    {
    SysCtlPeripheralEnable (SYSCTL_Periph_ADC0);//启用 ADC0模块。
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOE);//在
    GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_1)中为模拟启用 GPIOE;
    GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_2);
    ADCReferenceSet (ADC0_BASE、 ADC_REF_INT);
    ADCIntEnable (ADC0_BASE、3);
    ADCSequenceConfigure (ADC0_BASE、0、 ADC_TRIGGER_PROCESSOR, 0);
    //ADCSequenceConfigure (ui32Base、ui32SequenceNum、ui32Trigger、ui32Priority)
    //参数:
    // ui32Base 是 ADC 模块的基址。
    // ui32SequenceNum 是采样序列编号。
    // ui32Trigger 是启动采样序列的触发源;必须是
    // adc_trigger___LW_AT__∗值之一。
    // ui32Priority y 是采样序列相对于其它采样
    序列的相对优先级//序列。
    ADCSequenceStepConfigure (ADC0_BASE、0、0、ADC_CTL_CH1);//将 AIN1映射到 SS0 ADCSequenceStepConfigure 的第0步
    (ADC0_BASE、0、1、ADC_CTL_CH2 | ADC_CTL_IE |
    ADC_CTL_END);//将 AIN2映射到 SS0的第1步并生成该通道
    //序列发生器中的最后一步,也生成
    //序列发生器完成时中断
    ADCSequenceEnable (ADC0_BASE、0);
    ADCIntClear (ADC0_BASE、0);
    } 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您的序列号的第一个仍然是错误的。 您写入了 ADCIntEnable (ADC0_BASE、3)、该值应为 ADCIntEnable (ADC0_BASE、0)。

    其次、不需要 ADCReferenceSet (ADC0_BASE、ADC_REF_INT)、因为 TM4C123只有内部基准。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    还可以! 我已经更改了所有内容,但通道之间仍然存在干扰,例如,当我将任何信号源连接到 PE2或 PE1时,UART 也会读取和打印一些信号。 即使我将这些引脚接地、它仍然显示一个奇怪的方波。 我该怎么做?

    以下是我的 Get 示例代码:

    while (!ADCIntStatus (ADC0_BASE、0、false)
    {
    }
    ADCIntClear (ADC0_BASE、0);
    ADCSequenceDataGet (ADC0_BASE、0、通道1);
    while (!ADCIntStatus (ADC0_BASE、0、false)
    {
    }
    ADCIntClear (ADC0_BASE、0);
    ADCSequenceDataGet (ADC0_BASE、0、通道2);
    
    normalizedADC =((浮点)通道2)/4096.0f;
    UARTprintf ("%d\r"、normalizedADC);
    UARTprintf ("\n"); 

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

    我只是想跟进我之前的询问。 我尝试了另一个电路板、并在将我使用的 ADC 通道接地时继续获得噪声(通常每个电路板都从0跳到~ 30计数)。 注意-此板用于之前的项目中、我刚刚订购了2块新板、以查看迄今为止我使用的板是否以某种方式损坏。 当硬件对64进行过采样时、接地通道寄存器~10计数并波动~1计数。 我坚持使用硬件采样、因为我不需要采样速度超过~7800SPS (1Msps/2通道/64个样本)。

    我对我正在使用的 ADC 通道执行了"校准"(硬件对64个样本进行过采样)、方法是通过分压器为每个通道提供大约 GND、1、2和3伏信号。 我的结果表明、存在极高的线性关系、但存在轻微的偏移。 对于 PD1、我的装配线为 y = 1240.6x + 6.7236 (y 是计数、x 是电压)。 这对应于12位分辨率下3.2962伏的完整范围。 对于 PD2 y = 1240.7x + 5.473、对应于3.2970伏的完整范围。 非常接近规格!

    我现在唯一的顾虑是需要的轻微偏移以及对显著过采样的需求、这极大地降低了我的最大采样率(如果我需要提高速度)。

    供参考我使用的是通道 PD2和 PD1。 它们的干扰量似乎很小、但几乎可以忽略不计(当通过其整个范围改变替代信道时、计数小于1)。

    谢谢、

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

    我看不到您调用 ADCProcessorTrigger (ADC0_BASE、0)。 如何触发转换以开始?

    我之前问过您是否按原样尝试过 TivaWare 示例。 如果将输入连接到0V、3.3V 或1.65V、您是否获得了正确的转换数据? 你得到了什么?  

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

    嗯、 我使用计时器从另一个函数触发它。 我在一个通道中放置了一个5Hz、它与另一个通道的一些噪声混合。 另一件事是、所有模拟引脚都对信号输入做出响应、并将一些值打印到串行端口。

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

     首先、如果您已经尝试过 TivaWare 示例、您从未回答过我的问题。 我重复一遍、您是否通过 TivaWare 示例获得了正确的转换值?

    另请忽略下面勘误表中的前两个样本、并遵循解决方法建议。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    查尔斯,我一直说我试过这个例子,它运行良好。 我也会尝试此修改。 再次感谢您、您将为我提供很多帮助!
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我已将输入连接到3.3V 和0V。 它正在打印该奇怪的信号。 (我正在使用 Arduino 串行绘图机 )

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

    是的!

    这是:

    #include 
    #include 
    #include 
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/adc.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    
    #include "driverlib/rom.h"#include "driverlink/intraduateg.ide"#def/udio.idt/idr.idr.idr.idr.idr.idr.idr.idr.idr.idr.idr.idr.idr./idr.idr.idr.idr./idr.idr.idr.idr.idr.idr.idr./idr.idr.idr.idr.idr.idr.idr.idr.idr.idr.idr.
    
    
    
    
    
    
    
    
    
    
    //启用用于 UART1引脚的 GPIO 端口 A。
    // TODO:将其更改为您正在使用的 GPIO 端口。
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
    
    //
    //为端口 A0和 A1上的 UART1功能配置引脚复用。
    //如果您的器件不支持引脚复用、则无需执行此步骤。
    // TODO:更改此选项以选择您正在使用的端口/引脚。
    //
    GPIOPinConfigure (GPIO_PA0_U0RX);
    GPIOPinConfigure (GPIO_PA1_U0TX);
    
    //
    //启用 UART1,以便我们可以配置时钟。
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
    
    //为这些引脚选择替代(UART)功能。
    // TODO:更改此选项以选择您正在使用的端口/引脚。
    //
    GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);
    
    //
    //初始化控制台 I/O 的 UART
    UARTStdioConfig (0、115200、SysCtlClockGet ()/*16000000*/);
    }
    空 Timer0BIntHandler (空)
    {
    //function description ->每次中断发生
    // 中断标志被清除,以便另一个中断标志被清除
    // 直到在无限循环中达到溢出。
    // 然后、ADC 转换被触发以开始进行
    // 要在 UART 上显示的样本。
    //清除计时器中断标志。
    //
    TimerIntClear (TIMER0_BASE、TIMER_TIMB_TIMEOUT);
    //触发 ADC 转换。
    //
    //ADCProcessorTrigger (ADC0_BASE、3);
    ADCProcessorTrigger (ADC0_BASE、0);
    }
    void init_ADC (void)
    {
    SysCtlPeripheralEnable (SYSCTL_Periph_ADC0);//启用 ADC0模块。
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOD);//在
    GPIOPinTypeADC (GPIO_PORTD_BASE、GPIO_PIN_1)中为模拟启用 GPIOE;//通道6
    GPIOPinTypeADC (GPIO_PORTD_BASE、GPIO_PIN_2);//通道5
    //CINT_ADC0 (ADCINT
    )基址;ADC0_ADCINT (ADC0)基址 0);
    ADCSequenceConfigure (ADC0_BASE、0、ADC_TRIGGER_PROCESSOR、0);
    //ADCSequenceConfigure (ui32Base、ui32SequenceNum、ui32Trigger、ui32Priority)
    //参数:
    // ui32Base 是 ADC 模块的基址。
    // ui32SequenceNum 是采样序列编号。
    // ui32Trigger 是启动采样序列的触发源;必须是
    // adc_trigger___LW_AT__∗值之一。
    // ui32Priority y 是采样序列相对于其它采样
    序列的相对优先级//序列。
    ADCSequenceStepConfigure (ADC0_BASE、0、0、ADC_CTL_CH5);//将 AIN5映射到 SS0 ADCSequenceStepConfigure 的第0步
    (ADC0_BASE、0、1、ADC_CTL_CH6 | ADC_CTL_IE |
    ADC_CTL_END);//将 AIN6映射到 SS0的第1步并生成该通道
    //序列发生器中的最后一步,也生成
    //序列发生器完成时中断
    ADCSequenceEnable (ADC0_BASE、0);
    ADCIntClear (ADC0_BASE、0);
    }
    
    int main (void)
    {
    //该数组用于存储从 ADC FIFO 读取的数据。 它
    //必须与正在使用的序列发生器的 FIFO 一样大。 此示例
    //使用 FIFO 深度为1的序列3。 如果是另一个序列
    //与更深的 FIFO 一起使用,则必须更改数组大小。
    
    uint32_t channel1;//通道0数组
    uint32_t channel2;//通道1数组
    
    //变量->uint32_t
    ui32PrevCount = 0;
    //---
    //初始配置->
    SysCtlClockSet (SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_OSC_main |
    SYSCTL_XTAL_16MHz);//将时钟设置为直接从外部晶振/振荡器运行。
    ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOC);//为 LED 启用 GPIOC
    ROM_SysCtlPeripheralEnable (SYSCTL_Periph_TIMER0);//启用 Timer0
    ROM_SysCtlDelay (1);
    //---------------
    //GPIO 配置->
    ROM_GPIOPinTypeGPIOOutput (GPIO_PORTC_BASE、GPIO_PIN_5);//将 PC5配置为输出
    ROM_GPIOPinTypeGPIOOutput (GPIO_PORTC_BASE、GPIO_PIN_4);//将 PC4配置为输出
    ROM_GPIOPinTypeGPIOOutput (GPIO_PORTC_BASE、GPIO_PIN_6);//将 PC4配置为输出
    ROM_GPIOTypeGPIOOutput (GPIO_PORTC_BASE、GPIO_PIN_6)---
    
    //Timer Settings -->
    
    InitConsole();//UART 配置
    //5-配置计时器
    //将 Timer0B 配置为16位周期性计时器-->一直计数到65536
    //
    //向量表
    中的注册 timer0B 处理程序 IntRegister (INT_TIMER0B、Timer0BIntHandler);
    //在控制台上显示设置。
    //
    TimerConfigure (TIMER0_BASE、TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_PERIODICASE);
    //
    ! 重要
    说明//将 Timer0B 加载值设置为1ms。
    TimerLoadSet (TIMER0_BASE、TIMER_B、SysCtlClockGet ()/ 1000);//将 clok 除以1000次
    // 即:160000 Hz;
    //启用处理器中断。
    //
    IntMasterEnable();
    //
    //将 Timer0B 中断配置为计时器超时。
    //
    TimerIntEnable (TIMER0_BASE、TIMER_TIMB_TIMEOUT);
    //
    //在处理器(NVIC)上启用 Timer0B 中断。
    //
    IntEnable (INT_TIMER0B);
    //
    //初始化中断计数器。
    //
    G_ui32Counter = 0;
    //
    //启用 Timer0B。
    //
    TimerEnable (TIMER0_BASE,TIMER_B);
    
    //---------------
    //ADC 设置-->
    
    init_adc ();
    
    //---------------
    //Variables ->
    
    
    float normalizedADC;
    
    while (1)
    {//
    等待转换完成。
    
    //ADC0
    while (!ADCIntStatus (ADC0_BASE、0、false)//如果样本准备就绪,则让 UART 显示值
    {
    }
    ADCIntClear (ADC0_BASE、0);
    ADCSequenceDataGet (ADC0_BASE、0、通道1);
    while (!ADCIntStatus (ADC0_BASE、0、false)//如果样本准备就绪,则 UART 显示值
    {
    }
    ADCIntClear (ADC0_BASE、0);
    ADCSequenceDataGet (ADC0_BASE、0、通道2);
    
    normalizedADC =((float)通道2)/4096.0f;
    UARTprintf ("%d\r"、 normalizedADC);
    UARTprintf ("\n");
    }
    } 

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

    您需要使用 SysCtlClockSet (SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_MAIN|SYSCTAL_XTAL_16MHz)将时钟设置为80MHz。 PLL VCO 输出为200MHz、您需要进行2.5分频才能达到80MHz。 您正在将器件配置为以200MHz 的频率运行、并除以1。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    还可以! 但是,为什么需要它呢?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    如果您阅读数据表、则 TM4C123的额定工作频率仅为最大80MHz。 当您将时钟配置为以200MHz 运行时、它超出规格。 不保证任何工作。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    还可以! 我已经更改了、PD1和 PD2之间不会相互干扰、但 PE3是、即使它未配置。 另一件事是,我以前所显示的奇怪的噪音仍然存在。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    如何使用 PE3? 您是将 PE3用作 ADC 的 AIN0输入、还是将 PE3用作 GPIO 并查看干扰? 在我先前的答复中,我给出了以下勘误表。 在使用其他 AINx 通道时、实施权变措施以减轻干扰或不要使用 PE3。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    嘿、Charles!
    我从头开始使用新代码并使用示例开始、然后我按照您对我说的所有步骤操作、现在一切都正常。 非常感谢、如果没有您的帮助、我将无法做到这一点。

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

    您好、Bruno、

    您是否会介意分享您工作的代码? 我的问题仍然存在、我想进行比较。

    谢谢!

    Ken

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

    大家好、

    当然! (请随时向我询问任何内容)。以下内容:

    //
    // Bruno Ribeiro Chaves
    //巴西- Minas Gerais / Belo Horizonte
    //@brunorchoraves1//
    project.c -配置 ADC0和 UART 以显示样片
    //
    //*********
    
    #include 
    #include 
    #include 
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/adc.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/rom.h"
    #include "driverlib/driverlib/trune.h"#include "driverlib/trunicl"#include "driverlib/drivers.idio"#include "driverlib/try"#include "driverlib.mdio.idio.h
    
    
    
    
    
    
    //
    //如果驱动程序库遇到错误,则调用的错误例程。
    ////
    *****************
    #ifdef debug
    void
    __error__(char *pcFilename、uint32_t ui32Line)
    {
    #endif
    
    
    static volatile uint32_t g_ui32Counter = 0;//计时器计数器变量
    
    void InitConsole (void)
    {
    //
    //启用用于 UART1引脚的 GPIO 端口 A。
    // TODO:将其更改为您正在使用的 GPIO 端口。
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
    
    //
    //为端口 A0和 A1上的 UART1功能配置引脚复用。
    //如果您的器件不支持引脚复用、则无需执行此步骤。
    // TODO:更改此选项以选择您正在使用的端口/引脚。
    //
    GPIOPinConfigure (GPIO_PA0_U0RX);
    GPIOPinConfigure (GPIO_PA1_U0TX);
    //启用 UART1,以便我们可以配置时钟。
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
    //使用内部16MHz 振荡器作为 UART 时钟源。
    GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);
    
    //
    //初始化控制台 I/O 的 UART
    //
    ///UARTConfigSetExpClk (UART0_BASE、SysCtlClockGet ()、115200、
    // (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
    // UART_CONFIG_PAR_NONE));
    
    UARTStdioConfig (0、115200、SysCtlClockGet ()/*16000000*/);
    }
    空 Timer0BIntHandler (空)
    {
    //
    //清除计时器中断标志。
    //
    TimerIntClear (TIMER0_BASE、TIMER_TIMB_TIMEOUT);
    
    //触发 ADC 转换。
    //
    ADCProcessorTrigger (ADC0_BASE、0);
    }
    
    int main (void)
    {
    
    //初始配置
    SysCtlClockSet (SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
    SYSCTL_XTAL_16MHz);//将时钟设置为直接从外部晶振/振荡器运行。
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOD);//为中的模拟启用 GPIOD
    ROM_SysCtlPeripheralEnable (SYSCTL_Periph_TIMER0);//启用 Timer0
    ROM_SysCtlDelay (1);
    
    //向量表
    中的寄存器 timer0B 处理程序 IntRegister (INT_TIMER0B、Timer0BIntHandler);
    InitConsole ();//UART 配置
    TimerConfigure (TIMER0_BASE、TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_PERIODICRAY);
    TimerLoadSet (TIMER0_BASE、TIMER_B、SysCtlClockGet ()/ 1000);
    IntMasterEnable();
    TimerIntEnable (TIMER0_BASE、TIMER_TIMB_TIMEOUT);
    IntEnable (INT_TIMER0B);
    G_ui32Counter = 0;
    
    TimerEnable (TIMER0_BASE,TIMER_B);
    //---------------
    //GPIO 配置-->
    
    GPIOPinTypeADC (GPIO_PORTD_base、GPIO_PIN_0|GPIO_PIN_1);//将 PE2配置为模数输入
    
    SysCtlPeripheralEnable (SYSCTL_Periph_ADC0);//启用 ADC0模块。
    
    ADCSequenceConfigure (ADC0_BASE、0、ADC_TRIGGER_processor、0);
    ADCSequStepConfigure (ADC0_BASE、 0、0、ADC_CTL_CH6 /*| ADC_CTL_IE |
    ADC_CTL_END_/);
    ADCSequenceStepConfigure (ADC0_BASE、0、1、ADC_CTL_CH7 | ADC_CTL_IE |
    ADC_CTL_END);
    
    ADCSequenceEnable (ADC0_BASE、0);
    
    ADCIntClear (ADC0_BASE,0);
    //---------------
    //Variables -->
    
    uint32_t CHANNELS[8];//ADC 数组->大小与 FIFO 深度相同
    uint32_t ui32PrevCount = 0;//计时器
    uint32_t PD0;
    uint32_t PD1;
    
    while (1)
    {
    while (!ADCIntStatus (ADC0_BASE、0、false)){}//如果样本准备就绪、则让 UART 显示值
    、而(!ADCIntStatus (ADC0_BASE、0、false)){}//如果样本准备就绪、则让 UART 显示值
    ADCIntClear (ADC0_BASE、0);
    ADCSequenceDataGet (ADC0_BASE、0、CHANNELS);
    PD0=通道[1];
    PD1 =通道[0];
    
    
    UARTprintf ("%4D\r"、PD0);
    UARTprintf ("\n");
    ui32PrevCount = g_ui32Counter;//!important
    
    }
    } 

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

    非常感谢! 遗憾的是、在您设置 ADC 的方式方面、我没有看到任何重大差异。  由于某种原因、当我扫描一个通道(PD_2)时、我会得到我期望的值、但当我扫描两个通道(PD_2和 PD_1)时、PD_2的值完全不同。

    我尝试使用这两个通道测量有刷直流电机的电流和电压、以便能够估算电机的功耗。

    我附上了我的代码、希望有人能够提供帮助。

    #include //std INT (uint8_t、uint16_t 等)
    #include "driverlib/adc.h"
    #include "driverlib/pwm.h"
    #include "driverlib/QEI.h"
    #include "driverlib/sysctl.h"
    #include "usbprint.h"

    //
    // ADC 样本数(在微控制器上运行 RAM 之前~最大值)
    //需要为串行打印语句保留一定数量的 RAM
    //否则打印语句失败。
    //
    #define NUM_SAples 3000

    //
    // 20kHz 信号的时钟节拍数(时钟以80MHz -> 4000节拍运行)
    //
    #define PWM_PERIOD_80KHZ F_CPU / 80000 //(80MHz/80000 -> 1000个周期)
    #define PWM_PERIOD_40kHz F_CPU / 40000 //(80MHz/40000 -> 2000个周期)
    #define PWM_PERIOD_20kHz F_CPU / 20000 //(80MHz / 20000 -> 4000个周期)
    #define PWM_PERIOD_10kHz F_CPU / 10000 //(80MHz/10000 -> 8000个周期)
    #define PWM_PERIOD_5kHz F_CPU / 5000 //(80MHz/5000 -> 16000个周期)
    #define PWM_PERIOD_2kHz F_CPU / 2000 //(80MHz/2000 -> 40000个周期)

    //
    //指定捕捉每个编码器速度值的速度(以秒为单位)
    //针对编码器的 TIMESTEP
    //
    //编码器为12位分辨率,因此每转有4096个计数。
    //齿轮箱的减排量为~9.96154:1(35*37)/(13*10)。
    //电机转轴应以~25Hz 的频率运行。
    //
    #define ENC_TIMESTEP_S 0.001

    //
    //全局变量:
    //

    //
    //为 CH4的单端 ADC 结果分配时间(微秒)
    //(PD_3)(12位 ADC 计数)、CH5上的单端 ADC 结果
    //(PD_2)(12位 ADC 计数)和正交编码器结果(节拍率
    //编码器时间步长)。
    //
    uint32_t ADC_TIME_BUFFER[NUM_SAMESS]={0};
    uint16_t ADC_CH5_buffer[NUM_Samples]={0};
    uint16_t ADC_CH6_buffer[NUM_SAMESS]={0};
    uint16_t QE_buffer[NUM_SAMESS]={0};

    uint16_t ui16StepDelay_ms = 500;
    uint16_t ui16PWMDutyCycle = PWM_PERIOD_20kHz/100;

    const int ledPin = blue_LED;//PF_2

    //
    //
    //此函数将 UART0设置为用于控制台显示信息
    //因为示例正在运行。
    //
    //
    空 initConsole (空)

    //
    //初始化控制台 I/O 的串行端口
    //
    Serial.begin(115200);

    //
    //
    //此函数将 LED 引脚设置为用于显示状态信息
    //作为示例运行的用户。
    //
    //
    空 initLED (空)

    //为输出配置 LED 引脚
    引脚模式(ledPin、输出);

    //
    //
    //此函数设置用于捕获读数的 ADC
    //
    //
    void initadc (void)

    //
    //必须启用 ADC0外设才能使用。
    //

    //电机电流传感器 PD_2 (AIN5)
    //电机电压传感器 PD_1 (AIN6)

    SysCtlPeripheralEnable (SYSCTL_Periph_ADC0);

    //
    //对于此示例,ADC0与端口 E7/E6上的 AIN0/1一起使用。
    //您使用的实际端口和引脚可能有所不同,请参阅
    //数据表以了解更多信息。 需要启用 GPIO 端口 E
    //因此可以使用这些引脚。
    // TODO:将其更改为您正在使用的 GPIO 端口。
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOD);

    //
    //为这些引脚选择模拟 ADC 功能。
    //请查阅数据表以查看每个引脚分配的函数。
    // TODO:更改此选项以选择您正在使用的端口/引脚。
    //
    GPIOPinTypeADC (GPIO_PORTD_base、GPIO_PIN_2 | GPIO_PIN_1);
    //GPIOPinTypeADC (GPIO_PORTD_BASE、GPIO_PIN_2);

    //
    //配置前需要禁用 ADC
    //
    ADCSequenceDisable (ADC0_BASE、2);

    //
    //使用处理器信号触发器启用采样序列2。 序列2
    当处理器发送信号启动时、//将执行最多4个样本
    //转换。 每个 ADC 模块有4个可编程序列、序列0
    //至序列3。 此示例任意使用序列2。
    //
    ADCSequenceConfigure (ADC0_BASE、2、ADC_TRIGGER_PROCESSOR、0);

    //
    //设置触发器和序列开始之间的相位延迟
    //如果触发在上升沿上的时间稍有不同,则会发生这种情况
    //可以降低 ADC 信号中的噪声
    //
    //ADCPhaseDelaySet (ADC0_BASE、ADC_PHASE_0);

    //
    //在序列2上配置步骤0和步骤1。 对中的通道0 (ADC_CTL_CH0)进行采样
    //差分模式(ADC_CTL_D)并配置中断标志
    //(ADC_CTL_IE)将在采样完成时置1。 告诉 ADC 逻辑
    //这是序列2上的最后一次转换(ADC_CTL_END)。 序列
    // 3只有一个可编程步骤。 序列1和2有4个步骤、和
    //序列0有8个可编程步骤。 因为我们正在进行两次转换
    //使用序列2,我们将仅配置步骤0和步骤1。 了解详情
    //有关 ADC 序列和步骤的信息、请参阅数据表。
    //
    ADCSequenceStepConfigure (ADC0_BASE、2、0、ADC_CTL_CH5 /*| ADC_CTL_IE /*| ADC_CTL_END*/);
    ADCSequenceStepConfigure (ADC0_BASE、2、1、ADC_CTL_CH6 | ADC_CTL_IE | ADC_CTL_END);

    //
    //配置 ADC 的硬件过采样因子
    //
    //ADCHardwareOversampleConfigure (ADC0_BASE、64);

    //
    //由于采样序列2现在已配置,因此必须将其启用。
    //
    ADCSequenceEnable (ADC0_BASE、2);

    //
    //清除中断状态标志。 这样做是为了确保
    //中断标志在我们进行采样之前被清除。
    //
    ADCIntClear (ADC0_BASE、2);


    //
    //
    //此函数设置用于电机控制的 PWM
    //
    //
    void initPWM (void)

    //
    //设置 PWM 模块
    // Tiva Launchpad 有两个 PWM 模块(0和1)。 模块1涵盖 LED 引脚。
    //必须启用 PWM0外设才能使用。
    //

    //在 PB_4上驱动脉宽调制信号
    SysCtlPeripheralEnable (SYSCTL_Periph_PWM0);

    //
    //对于这个示例、PWM0与 PortB 引脚6一起使用。 实际端口
    //和使用的引脚可能在您的器件上有所不同、请参阅的数据表
    //更多信息。 GPIO 端口 B 需要启用、以便可以启用这些引脚
    //已使用。
    // TODO:将其更改为您正在使用的 GPIO 端口。
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);

    //
    //配置 GPIO 引脚复用以选择这些引脚的 PWM 功能。
    //此步骤选择可用于这些引脚的替代功能。
    //如果您的器件支持 GPIO 引脚功能多路复用、这是必需的。
    //请查阅数据表以查看每个引脚分配的函数。
    // TODO:更改此选项以选择您正在使用的端口/引脚。
    //
    GPIOPinConfigure (GPIO_PB4_M0PWM2);

    //
    //在引脚 PB6和 PB7上为 PWM 功能配置 GPIO 引脚。 请参阅
    //数据表以查看每个引脚分配的函数。
    // TODO:更改此选项以选择您正在使用的端口/引脚。
    //
    GPIOPinTypePWM (GPIO_PORTB_BASE、GPIO_PIN_4);

    //
    //配置 PWM 选项
    //
    PWMGenConfigure (PWM0_BASE、PWM_GEN_1、PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

    //
    //启用 ADC 的触发器
    //
    //PWMGenIntTrigEnable (PWM0_BASE、PWM_GEN_1、PWM_TR_CNT_LOAD);

    //
    //将 PWM 周期设置为20kHz (电机驱动器的最大设置)
    //
    PWMGenPeriodSet (PWM0_BASE、PWM_GEN_1、PWM_PERIOD_20kHz);

    //
    //将 PWM 占空比设置为1%
    //
    PWMPulseWidthSet (PWM0_BASE、PWM_OUT_2、PWM_PERIOD_20kHz/100);

    //
    //启用 PWM0输出信号上的死区生成。 PWM 位0
    //(PD0)将具有25%的占空比(在上面设置)、而 PWM 位1将具有该占空比
    //占空比为75%。 这些信号之间将有10us 的间隙
    //上升沿和下降沿。 这意味着、在 PWM 位1变为高电平之前、
    // PWM 位0至少已处于低电平160个周期(或10us)、也是如此
    //在 PWM 位0变为高电平之前。 死区发生器允许您指定
    // PWM 之前"死区"延迟的宽度、以 PWM 时钟周期为单位
    //信号在 PWM 信号下降后变为高电平。 在本示例中、我们
    //将在的上升沿和下降沿使用160个周期(或10us)
    // PD0。 有关死区的更多信息、请参阅数据表
    //生成。
    //
    //PWMDeadBandEnable (PWM0_BASE、PWM_GEN_1、160、160);

    //
    //启用 PWM 发生器
    //
    PWMGenEnable (PWM0_BASE、PWM_GEN_1);

    //
    //打开输出引脚
    //
    PWMOutputState (PWM0_BASE、PWM_OUT_2_BIT、TRUE);

    //
    //
    //此函数设置用于测量电机转速的 QEI
    //
    //
    空 initQEI (空)

    //
    //设置 QEI 模块
    // Tiva Launchpad 有两个 QEI 模块(0和1)。 模块0涵盖 LED 引脚。
    //必须启用 QEI1外设才能使用。
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_QEI1);

    //
    //对于此示例、QEI1与端口 C 引脚5和6一起使用。 实际端口
    //和使用的引脚可能在您的器件上有所不同、请参阅的数据表
    //更多信息。 GPIO 端口 C 需要启用、以便可以启用这些引脚
    //已使用。
    // TODO:将其更改为您正在使用的 GPIO 端口。
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOC);

    //
    //配置 GPIO 引脚复用以选择这些引脚的 PWM 功能。
    //此步骤选择可用于这些引脚的替代功能。
    //如果您的器件支持 GPIO 引脚功能多路复用、这是必需的。
    //请查阅数据表以查看每个引脚分配的函数。
    // TODO:更改此选项以选择您正在使用的端口/引脚。
    //
    GPIOPinConfigure (GPIO_PC5_PHA1);//GPIO_PC5_PHA1
    GPIOPinConfigure (GPIO_PC6_PHB1);//GPIO_PC6_PHB1

    //
    //在引脚 PB6和 PB7上为 PWM 功能配置 GPIO 引脚。 请参阅
    //数据表以查看每个引脚分配的函数。
    // TODO:更改此选项以选择您正在使用的端口/引脚。
    //
    GPIOPinTypeQEI (GPIO_PORTC_BASE、GPIO_PIN_5 | GPIO_PIN_6);

    //
    // nEncoderTimerPeriod:用于配置 QEI (用于测量速度的时钟节拍数)
    //
    uint32_t nEncoderTimerPeriod_tick = F_CPU * ENC_TIMERSTEP_S;// 8000000000*0.001=80000

    //
    //配置和启用 QEI
    //
    QEIConfigure (QEI1_base、(QEI_CONFIG_CAPTURE_A_B | QEI_CONFIG_NO_RESET | QEI_CONFIG_QUIPOTIVATE | QEI_CONFIG_NO_SWaP)、UINT32_MAX);

    //
    //
    //
    QEIVelocityConfigure (QEI1_base、QEI_VELDIV_1、nEncoderTimerPeriod_tick);//除以时钟速度以获取计数/秒

    //
    //
    //
    QEIEnable (QEI1_BASE);

    //
    //
    //
    QEIVelocityEnable (QEI1_base);


    //
    //
    //此函数以毫秒延迟使 LED 闪烁多次
    //之间。
    //
    //
    空 blinkLED (uint32_t ui32Times、uint32_t ui32Milliseconds)

    //
    //闪烁 LED
    //
    digitalWrite (ledPin、low);
    for (int i = 0;i < ui32Times;i++){
    digitalWrite (ledPin、HIGH);
    延迟(ui32毫秒);
    digitalWrite (ledPin、low);
    延迟(ui32毫秒);

    //
    //
    //此函数触发 ADC 转换并将 ADC 读数存储在中
    //无符号整数的数组。
    //
    //
    空 readadc (uint32_t * pui32ADCValues)

    //
    //触发 ADC 转换。
    //
    ADCProcessorTrigger (ADC0_BASE、2);

    //
    //等待转换完成。
    //
    while (!ADCIntStatus (ADC0_BASE、2、false))

    //
    //清除 ADC 中断标志。
    //
    ADCIntClear (ADC0_BASE、2);

    //
    //读取 ADC 值。
    //
    ADCSequenceDataGet (ADC0_BASE、2、pui32ADCValues);

    //
    //
    //此函数记录 ADC 读数并将其存储在预分配的中
    //缓冲器。
    //
    //
    空记录 RawReadings (bool bRunMotorStepInput)

    uint32_t pui32ADCValues[4];

    //
    //确定电机是否使用 STEP 输入运行
    //对循环进行单独处理,以最大限度地提高循环内的速度/最大程度地减少计算
    //
    if (bRunMotorStepInput){
    //
    //设置脉宽占空比
    //
    PWMPulseWidthSet (PWM0_BASE、PWM_OUT_2、ui16PWMDutyCycle、tick);
    延迟(ui16StepDelay_ms);//记录值之前的可选延迟

    for (int i = 0;i < NUM_SAples;i++){
    //
    //读取 ADC 值
    //
    readadc (pui32ADCValues);

    //
    //存储时间和 ADC 值
    //
    adc_time_buffer[i]=微秒();
    ADC_CH5_buffer[i]=(uint16_t) pui32ADCValues[0];
    ADC_CH6_buffer[i]=(uint16_t) pui32ADCValues[1];

    //
    //如果电机正在运行,记录正交编码器值
    //
    if (bRunMotorStepInput){QE_buffer[i]=(uint16_t) QEIVelocityGet (QEI1_base);}

    //
    //将脉宽占空比设置为1%
    //
    if (bRunMotorStepInput){PWMPulseWidthSet (PWM0_BASE、PWM_OUT_2、PWM_PERIOD_20kHz/100);}

    //
    //
    //此函数通过发送存储在缓冲区中的 ADC 值
    //由 MATLAB 进行附加后处理的串行端口。
    //
    //
    空 sendRawReadings (bool bIncludeQE)

    if (bIncludeQE){
    for (int i = 0;i < NUM_SAples;i++){
    //
    //打印时间(微秒)、CH5 (计数)、CH6 (计数)和
    // QE (每个时间步长的节拍数)
    //
    USBprintf ("%.4U、%.4U、%.4U、%.4u)\n\r\n、adc_time_buffer[i]、adc_ch5_buffer[i]、
    ADC_CH6_buffer[i]、QE_buffer[i]);


    }否则{
    for (int i = 0;i < NUM_SAples;i++){
    //
    //打印时间(微秒)、CH5 (计数)和 CH6 (计数)
    //
    USBprintf ("%.4U、%.4U、%.4U、0\n\r\n、ADC_TIME_BUFFER[i]、ADC_CH5_buffer[i]、
    ADC_CH6_buffer[i]);

    延迟(5);

    //
    //打印字符以指示数据结束
    //
    USBprintf ("e\n\r");

    //
    //
    //此函数通过发送存储在缓冲区中的 ADC 值
    //由 MATLAB 进行附加后处理的串行端口。
    //
    //
    void sendRawReadingsLive (uint32_t ui32计数)

    uint32_t pui32ADCValues[2];
    uint32_t 总和[3];
    uint32_t ui32StartTime = micros ();

    //
    //设置脉宽占空比
    //
    PWMPulseWidthSet (PWM0_BASE、PWM_OUT_2、ui16PWMDutyCycle、tick);

    总和[0]=0;
    总和[1]=0;
    总和[2]=0;
    延迟(ui16StepDelay_ms);

    对于(int i = 0;i < ui32Counts;i++){
    //
    //读取 ADC 值
    //
    readadc (pui32ADCValues);

    总和[0]+=(uint16_t) pui32ADCValues[0];//电机电流计数
    总和[1]+=(uint16_t) pui32ADCValues[1];//电机电压计数
    总和[2]+=(uint16_t) QEIVelocityGet (QEI1_base);

    //
    //打印时间(微秒)、CH0 (计数)、CH1 (计数)和
    // QE (每个时间步长的节拍数)
    //
    //打印超过244个计数的总和
    //
    if (i % 244 ==243){
    USBprintf ("%.5U、%.6U、%.6U、%.3U\n\r\n、micros ()-ui32StartTime、sum[0]、
    总和[1]、总和[2]);
    总和[0]=0;
    总和[1]=0;
    总和[2]=0;

    //
    //打印字符以指示数据结束
    //
    USBprintf ("e\n\r");

    //
    //将脉宽占空比设置为1%
    //
    PWMPulseWidthSet (PWM0_BASE、PWM_OUT_2、PWM_PERIOD_20kHz/100);


    //
    //
    // setup()在微控制器上电开始时运行一次
    //
    //
    void setup(){
    //
    //"大多数 ADC 控制逻辑以16MHz 的 ADC 时钟速率运行。 。
    //内部 ADC 分频器自动配置为16MHz 运行
    //当系统 XTAL 与 PLL 一起选择时由硬件选择。'
    //
    SysCtlClockSet (SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
    SYSCTL_XTAL_16MHz);

    //
    //初始化所有必要的模块
    //
    initConsole();
    initLED();
    initadC();
    initPWM();
    initQEI();

    //
    //指示初始化完成
    //
    黑色 LED (3、200);

    //
    //等待串行终端
    //
    延迟(1000);

    //
    //显示菜单
    //
    displayMenu();

    //
    //
    // loop()在设置后立即连续运行
    //
    //
    void loop(){
    //
    //改为使用串行事件
    //

    //
    //
    //只要有新数据出现,就会发生串行事件
    //硬件串行 RX。 此例程在每个例程之间运行
    // time loop()运行,因此使用循环内的延迟可以延迟
    //响应。 可能有多个字节的数据可用。
    //
    //
    void serialEvent()

    while (Serial.available ())

    //解析串行数据
    开关(Serial.Read())

    案例77:案例109://'m'或'm'被按下以查看菜单
    displayMenu();
    中断;
    判例76:判例108://'l'或'l'被按下以运行电机(打印输出不带缓冲器)
    黑色 LED (3、200);
    延迟(1000);
    digitalWrite (ledPin、HIGH);
    sendRawReadingsLive (Serial.parseInt());
    digitalWrite (ledPin、low);
    中断;
    案例67:案例99://'c'或"C"被按下以校准 ADC
    BlinkLED (3、200);//指示 ADC 校准开始
    延迟(1000);//延迟一秒
    digitalWrite (ledPin、HIGH);
    记录读数(false);
    sendRawReadings (假);
    digitalWrite (ledPin、low);
    中断;
    案例68:案例100://'d'或'D'被按下以更改延迟
    闪烁 LED (3、200);//指示开始
    ui16StepDelay_ms = Serial.parseInt();
    中断;
    案例83:案例115:按下了//"S"或"S"以运行电机(打印输出带有缓冲器)
    BlinkLED (3、200);//指示阶跃输入的开始
    延迟(1000);//延迟一秒
    digitalWrite (ledPin、HIGH);
    RecordRawReadings (真);
    sendRawReadings (真);
    digitalWrite (ledPin、low);
    中断;
    案例82:案例114://'r'或'r'被按下以运行电机(不打印输出)
    闪烁 LED (3、200);//指示开始
    延迟(1000);//延迟一秒
    digitalWrite (ledPin、HIGH);//打开 LED
    //
    //将脉宽占空比设置为所需的量
    //
    PWMPulseWidthSet (PWM0_BASE、PWM_OUT_2、ui16PWMDutyCycle、tick);
    //
    //等待所需的量(毫秒)
    //
    延迟(Serial.parseInt());
    //
    //将脉宽占空比设置回1%
    //
    PWMPulseWidthSet (PWM0_BASE、PWM_OUT_2、PWM_PERIOD_20kHz/100);
    digitalWrite (ledPin、low);//关闭 LED
    中断;
    案例80:案例112://'p'或'p'被按下以改变 PWM 占空比
    黑色 LED (3、200);
    ui16PWMDutyCycle = Serial.parseInt();
    中断;
    判例81:判例113://'q'或'q'被按下以退出程序
    //清理
    USBprintStr ("程序结束。");
    while (1){continue;}
    中断;

    delayMicroseconds (100);//等待足够的时间使新的串行数据可用

    空显示菜单(空)

    //控制器菜单
    USBprintStr ("Pololu 电机校准菜单:\n\n");
    USBprintStr ("c -发送 ADC 信号\n"\});
    USBprintStr ("d -更改阶跃延迟(ms)\n"\};
    USBprintStr ("l -运行电机(非缓冲打印输出)\n\n"\};
    USBprintStr ("m -显示菜单\n\r\n);
    USBprintStr ("p -更改 PWM 占空比(节拍数)\n"\};
    USBprintStr ("s -运行电机(缓冲打印输出)\n"\};
    USBprintStr ("r -运行电机(无打印输出)\n"\};
    USBprintStr ("q - Quit\n"r);

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

    您好、

    我认为你遇到的问题与我遇到的问题相同。 您为 pui32ADCValues[2]提供了错误的大小。

    由于您使用的是序列发生器2、因此它需要一个由4个位置组成的数组"pui32ADCValues[4]"、一旦此序列发生器选择了 FIFO 的 DE 深度、在本例中也是4。 然后、您必须将以下内容放置:

    while (!ADCIntStatus (ADC0_BASE、2、false))

    }您使用的信道数量相同。 因此、如果您仅使用两个通道、就会出现这种情况:

    int main ()
    {
    uint32_t pui32ADCValues[4];
    uint32_t PD1;
    uint32_t PD2;
    
    while (1)
    {
    while (!ADCIntStatus (ADC0_BASE、2、false))
    {
    }
    while (!ADCIntStatus (ADC0_BASE、2、false))
    {
    }
    ADCIntClear (ADC0_BASE、2);
    ADCSequenceDataGet (ADC0_BASE、2、pui32ADC0Value);
    
    PD1= pui32ADC0Value[0];
    PD2= pui32ADC0Value[1];
    }
    

    此外、您的代码太多、请尝试将其删除一段时间、 然后首先修复此 ADC 问题。 另一件事是查看通道是否配置正确,一旦使用 PD1和 PD2,则必须分别使用通道 CH6和 CH5。

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

    感谢您的建议!

    但结果仍然相同。

    基本上、我注意到一个通道仍然受到另一个通道的影响。 下面是我已经处理过的几种情形:

    通道1、通道2

    GND、GND -当两者都接地时、它们都寄存器中的值约为0 (良好)

    GND、1.5V -当应用此值时、CH1寄存器大约为10个计数、CH2寄存器大约为2000 (即 CH1被 CH2上拉)

    GND、3V -当应用此值时、CH1寄存器大约20次计数、CH2寄存器大约4000次(即 CH1被进一步上拉、似乎与 CH2具有线性关系)

    我注意到、当不进行硬件过采样时、这种关系要强得多、因此采样通道之间似乎需要稳定时间。 我尝试以极快的速度(每通道500kSPS)进行采样。 基本上、当硬件采样被启用并且大(64)时、它需要64个 CH1采样将其放置在 FIFO 插槽1中、然后将64个 CH2采样放置到 FIFO 插槽2中、因此后64个采样是整个64微秒后的结果。 (这都是假设我正确理解)。 这就是我认为需要进行某种稳定时间的原因。 随着我减少硬件采样、从而缩短采样 CH1和 CH2之间的时间、情况变得更糟。

    我知道在用于输入多路复用的其他 ADC 芯片上、需要一些时间来切换通道、我想知道这种情况是否也是这样?

    另外、我查看了 TM4C123GH6PM 数据表的 ADC 部分、并注意到了关于抖动位的部分(第806页)。 想知道是否需要设置该参数? 我尝试设置它、但似乎没有改变。

    最后、我想知道此应用是否需要更实质性的上拉或下拉电阻器? 我对这件事不是很了解、只是想猜测我可以做些什么来解决这个问题。

    再次感谢您的见解! 我希望有人能够引导我朝着正确的方向前进。