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 读取数据

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1208546/tm4c123gh6pm-cannot-get-reading-from-adc

器件型号:TM4C123GH6PM
主题中讨论的其他器件: EK-TM4C123GXL

您好!

我正在使用 TM4C123GH6PM launchpad 读取模拟输入并转换为数字。  

在设置中、使用 ADC0、AIN0 (PE3)是模拟电压输入。 我使用修整将1.3V 输入到 PE3。

我使用的 IDE 是 IAR Arm 9.32.1。

我按照 TM4C123GH6PM 微控制器数据表的说明、首先初始化 ADC 模块、配置采样序列发生器、然后进入无限 while 循环、以对电压输入进行采样。

在调试过程中、我检查了每个寄存器设置、它们都被设置为编码。 遗憾的是、输出始终为0x0dcd、没有转换任何数据。

有人能帮我检查一下我是否犯了一些错误吗?  

谢谢!

具体代码如下:

#include
#include "lm4f120h5qr.h"

int main()

unsigned int volatile ADC_value = 0;

// ADC 频率初始化
SYSCTL_RCC_R &=~(SYSCTL_RCC_PWRDN);// PLL 断电
ADC0_CC_R |= ADC_CC_CS_PIOSC;//设置时钟源:PIOSC
SYSCTL_RCC_R |= SYSCTL_RCC_PWRDN;// PLL 上电

// ADC 模块初始化
SYSCTL_RCGCADC_R |= SYSCTL_RCGCADC_R0;//启用 ADC0时钟门控
SYSCTL_RCGCGPIO_R |= SYSCTL_RCGCGPIO_R4;//启用 GPIO 端口 E 运行模式时钟门控
GPIO_Porte _ DIR_R &=~(1U << 3);//将 PE3设置为输入
GPIO_Porte AFSEL_R |=(1U << 3);//将 PE3功能设置为外设信号
GPIO_Porte _den_R &=~(1U << 3);//禁用 PE3的数字功能
GPIO_Porte AMSEL_R |=(1U << 3);//启用 PE3模拟功能

// ADC 采样序列发生器配置
ADC0_ACTSS_R &&~(ADC_ACTSS_ASEN3);// ADC0 SS3已禁用
ADC0_EMUX_R |= ADC_EMUX_EM3_ALWAYS;//将 ADC0 SS3 TRIGGER 设置为始终(连续采样)
ADC0_SSMUH3_R &&~(ADC_SSMUH3_MUX0_M);// ADC SS3首次采样输入选择
ADC0_SSCTL3_R |= ADC_SSCTL3_IE0 | ADC_SSCTL3_END0;//第1个采样是序列末端并设置 IE 标志
ADC0_IM_R |= ADC_IM_MASK3;// SS3中断发送到中断控制器
ADC0_ACTSS_R |= ADC_ACTSS_ASEN3;// ADC SS3已启用

while (1){
ADC0_PSSI_R |= ADC_PSSI_SS3;//开始采样序列发生器3采样
while (((ADC0_RIS_R 和 ADC_RIS_INR3)= 0);//等待采样完成
ADC_VALUE = ADC0_SSFIFO3_R 和0xFFF;//从 FIFO3读取转换值
ADC0_ISC_R |= ADC_ISC_IN3;// SS3中断状态和清除
}
}

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

    您好!

     首先、请参阅 https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/695568/faq-faqs-for-tm4c-arm-cortex-m4f-microcontrollers 上的常见问题4。 基本来说、我们不支持 DRM 风格的编码。 TivaWare 提供了一套丰富的 API 和示例、可简化软件开发。 有一个示例可以满足您的需求。 您可以参考 C:\ti\TivaWare_C_Series-2.2.0.295\examples\peripherals\adc\single_end.c 中的示例 如果您必须使用 DRM 编码风格、那么您可以在 C:\ti\TivaWare_C_Series-2.2.0.295\driverlib\adc.c 中参考如何使用 DRM 进行编码的 ADC 驱动程序。 API 在应用代码和硬件之间创建一个抽象级别。 您可以从 https://www.ti.com/tool/SW-TM4C 下载 TivaWare。  

     我建议您首先运行 TivaWare 示例并记录所有 ADC0和 GPIOE 寄存器设置、然后与您自己的代码进行比较。 它将帮助您进行调试、以了解代码中哪些寄存器的设置与示例不同。 这可能提供一种线索。  

     下面是使用 ADC0在 PE3上采样数据的示例代码。  

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include "driverlib/adc.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    
    //*****************************************************************************
    //
    //! \addtogroup adc_examples_list
    //! <h1>Single Ended ADC (single_ended)</h1>
    //!
    //! This example shows how to setup ADC0 as a single ended input and take a
    //! single sample on AIN0/PE3.
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - ADC0 peripheral
    //! - GPIO Port E peripheral (for AIN0 pin)
    //! - AIN0 - PE3
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example.  These are not required for operation of the
    //! ADC.
    //! - UART0 peripheral
    //! - GPIO Port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - None.
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
        //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
    
        //
        // Enable UART0 so that we can configure the clock.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Use the internal 16MHz oscillator as the UART clock source.
        //
        UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    
        //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, 16000000);
    }
    
    //*****************************************************************************
    //
    // Configure ADC0 for a single-ended input and a single sample.  Once the
    // sample is ready, an interrupt flag will be set.  Using a polling method,
    // the data will be read then displayed on the console via UART0.
    //
    //*****************************************************************************
    int
    main(void)
    {
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        uint32_t ui32SysClock;
    #endif
    
        //
        // This array is used for storing the data read from the ADC FIFO. It
        // must be as large as the FIFO for the sequencer in use.  This example
        // uses sequence 3 which has a FIFO depth of 1.  If another sequence
        // was used with a deeper FIFO, then the array size must be changed.
        //
        uint32_t pui32ADC0Value[1];
    
        //
        // Set the clocking to run at 20 MHz (200 MHz / 10) using the PLL.  When
        // using the ADC, you must either use the PLL or supply a 16 MHz clock
        // source.
        // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
        // crystal on your board.
        //
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        //
        // Note: SYSCTL_CFG_VCO_240 is a new setting provided in TivaWare 2.2.x and
        // later to better reflect the actual VCO speed due to SYSCTL#22.
        //
        ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                           SYSCTL_OSC_MAIN |
                                           SYSCTL_USE_PLL |
                                           SYSCTL_CFG_VCO_240), 20000000);
    #else
        SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);
    #endif
    
        //
        // Set up the serial console to use for displaying messages.  This is
        // just for this example program and is not needed for ADC operation.
        //
        InitConsole();
    
        //
        // Display the setup on the console.
        //
        UARTprintf("ADC ->\n");
        UARTprintf("  Type: Single Ended\n");
        UARTprintf("  Samples: One\n");
        UARTprintf("  Update Rate: 250ms\n");
        UARTprintf("  Input Pin: AIN0/PE3\n\n");
    
        //
        // The ADC0 peripheral must be enabled for use.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    
        //
        // For this example ADC0 is used with AIN0 on port E7.
        // The actual port and pins used may be different on your part, consult
        // the data sheet for more information.  GPIO port E needs to be enabled
        // so these pins can be used.
        // TODO: change this to whichever GPIO port you are using.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    
        //
        // Select the analog ADC function for these pins.
        // Consult the data sheet to see which functions are allocated per pin.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
    
        //
        // Enable sample sequence 3 with a processor signal trigger.  Sequence 3
        // will do a single sample when the processor sends a signal to start the
        // conversion.  Each ADC module has 4 programmable sequences, sequence 0
        // to sequence 3.  This example is arbitrarily using sequence 3.
        //
        ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);
    
        //
        // Configure step 0 on sequence 3.  Sample channel 0 (ADC_CTL_CH0) in
        // single-ended mode (default) and configure the interrupt flag
        // (ADC_CTL_IE) to be set when the sample is done.  Tell the ADC logic
        // that this is the last conversion on sequence 3 (ADC_CTL_END).  Sequence
        // 3 has only one programmable step.  Sequence 1 and 2 have 4 steps, and
        // sequence 0 has 8 programmable steps.  Since we are only doing a single
        // conversion using sequence 3 we will only configure step 0.  For more
        // information on the ADC sequences and steps, reference the datasheet.
        //
        ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 | ADC_CTL_IE |
                                 ADC_CTL_END);
    
        //
        // Since sample sequence 3 is now configured, it must be enabled.
        //
        ADCSequenceEnable(ADC0_BASE, 3);
    
        //
        // Clear the interrupt status flag.  This is done to make sure the
        // interrupt flag is cleared before we sample.
        //
        ADCIntClear(ADC0_BASE, 3);
    
        //
        // Sample AIN0 forever.  Display the value on the console.
        //
        while(1)
        {
            //
            // Trigger the ADC conversion.
            //
            ADCProcessorTrigger(ADC0_BASE, 3);
    
            //
            // Wait for conversion to be completed.
            //
            while(!ADCIntStatus(ADC0_BASE, 3, false))
            {
            }
    
            //
            // Clear the ADC interrupt flag.
            //
            ADCIntClear(ADC0_BASE, 3);
    
            //
            // Read ADC Value.
            //
            ADCSequenceDataGet(ADC0_BASE, 3, pui32ADC0Value);
    
            //
            // Display the AIN0 (PE3) digital value on the console.
            //
            UARTprintf("AIN0 = %4d\r", pui32ADC0Value[0]);
    
            //
            // This function provides a means of generating a constant length
            // delay.  The function delay (in cycles) = 3 * parameter.  Delay
            // 250ms arbitrarily.
            //
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
            SysCtlDelay(ui32SysClock / 12);
    #else
            SysCtlDelay(SysCtlClockGet() / 12);
    #endif
        }
    }
    

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

    尊敬的 Charles:

    感谢您的答复。

    我不喜欢 DRM 编码风格、我曾尝试复制示例来运行、不幸的是、有很多"无定义"错误。 即使我复制了中的 include 文件并添加到工程中、仍然无法正常工作。 按照一些视频教程、 我按照数据表说明使用最简单的编码方法直接操作专用寄存器。

    今天、我安装了 TivaWare、并尝试从 TivaWare 运行示例。 在 IAR 中使用示例代码的手册太简单了、我不能按照其中的说明进行操作。

    我复制了 project0文件、将其打开、构建、出现错误。

    我对 MCU 编码很陌生、您能不能从一开始就告诉我使用 IAR 中的 TivaWare 示例代码的步骤。

    非常感谢!

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

    尊敬的 Kailiang:

     我不熟悉 IAR、但它应该与 CCS 类似、允许您直接导入示例。 在 CCS 中、只需将一个项目"导入"到您的工作区。 请参阅下面的 CCS IDE 信息。  

      

     C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c123gxl 下有一组 TivaWare 工程。

     我建议您导入一个简单的示例、如 hello。 当您获得 hello 示例运行后、只需将 hello.c 替换为 C:\ti\TivaWare_C_Series-2.2.0.295\examples\peripherals\adc\single_end.c、然后重新编译工程。 从现有 TivaWare 示例开始是开始软件开发的最快方法。 它将为您节省很多时间。 如果您不迫切需要使用 DRM、那么我将建议您使用 TivaWare 外设驱动程序进行软件开发。 TivaWare 外设驱动程序已经过验证并已被客户广泛使用。  

      

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

    尊敬的 Charles:

    感谢您的建议。  

    我将尝试 CCS 并导入示例。