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.

[参考译文] CCS/TM4C123GH6PM:ADC 无法正常工作

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/588895/ccs-tm4c123gh6pm-adc-not-functioning

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

工具/软件:Code Composer Studio

大家好! 我尝试为 Tiva 计算 ADC、但我不熟悉 TivaWare (我实际上只熟悉 MSP430)。

无论如何、现在我的程序卡在等待 ADC 转换完成的 while 循环中(即 while (!ADCIntStatus (ADC0_BASE、0、false){})。 它肯定会卡在那里、因为我在 ADC 操作前后切换蓝色 LED、但它实际上绝不会第二次切换。

此外、如果您有时间、请也查看代码的 UART 部分。 这是优先级#2、但也不起作用。

非常感谢!!!

请查看我的以下代码、了解我要忽略的内容:

#include 
#include 
#include 
#include "driverlib/adc.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"







#include "driverlib/rom.h"#include "hw_intrinc/包含"#driver.h"#driverintrinc/包含"hw_intrinc/包含"#driverlib.h"#driverintrinc/包含"hw_intrinc/包含"#driverlib.h"#driverintrinc/包含"hw_intrinc/包含#def"#driverintrinc/包含"hw_intrintrinc/包含#def"#driverlib.hw_hw_intrintrintrintrinc/包含#def"#def"#def"#include"#def"hw_intrinc.h"#def"hw_intrinc #




//
//配置 ADC 及其引脚。
////
*****************
void
ConfigureADC (void)
{
//---- ADC 设置---
///----------------------------
//
//启用外设 ADC0并复位以应用
//
SysCtlPeripheralEnable (SYSCTL_Periph_ADC0);
SysCtlPeripheralReset (SYSCTL_Periph_ADC0);

//
//禁用 ADC0序列发生器0并重新配置 ADC0序列发生器
//
ADCSequenceDisable (ADC0_BASE、0);
ADCSequenceConfigure (ADC0_BASE、0、ADC_TRIGGER_PROCESSOR、0);
ADCSequenceStepConfigure (ADC0_BASE、0、0、ADC_CTL_TS /* AIN0*/| ADC_CTL_IE | ADC_CTL_END);

//
//启用 GPIO 端口 E 并将引脚3设置为 ADC 类型
//
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOE);
GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_3);

//
//为 ADC0 SS0启用中断
//
ADCIntEnable (ADC0_BASE、0);
}

//*********
//
//配置 UART 及其引脚。 这必须在 UARTprintf()之前调用。
////
*****************
void
ConfigureUART (void)
{
//---- UART 设置---
///----------------------------
//
//启用 GPIO 和 UART 1外设
//
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);
SysCtlDelay(3);
SysCtlPeripheralEnable (SYSCTL_Periph_UART1);
SysCtlDelay(3);

//
//为 UART 模式配置 GPIO 引脚
//
GPIOPinConfigure (GPIO_PB1_U1TX);
GPIOPinTypeUART (GPIO_PORTB_BASE、GPIO_PIN_1);

//
//使用内部16MHz 振荡器作为 UART 时钟源。
//
UARTClockSourceSet (UART1_base、UART_CLOCK_PIOSC);

//
//初始化 UART (端口、波特率、时钟源)
//
UARTStdioConfig (0、9600、16000000);
}


int main (void){
uint32_t 结果;
易失性字符电压;
//
//时钟设置为40MHz
//
SysCtlClockSet (SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHz);

SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);
GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_2);

ConfigureADC();
ConfigureUART();

IntMasterEnable();

UARTprintf ("Hello、world!\n");

while (1)
{
//
//打开蓝色 LED。
//
GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、GPIO_PIN_2);

//
//延迟一位。
//
SysCtlDelay (SysCtlClockGet ()/ 10 / 3);

///-------- ADC --------------
//
//请求 ADC 转换
//
ADCProcessorTrigger (ADC0_BASE、0);

//
//清除 ADC0序列发生器3的中断标志
//
ADCIntClear (ADC0_BASE、0);

//
//等待转换完成
//
while (!ADCIntStatus (ADC0_BASE、0、false)){}//这是程序冻结的位置!!!

//---- 处理数据---
//
//读取数据并转换
//
ADCSequenceDataGet (ADC0_BASE、0、结果);
电压=结果*0.000805664;

//
//关闭蓝色 LED。
//
GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、0);

//
//延迟一位。
//
SysCtlDelay (SysCtlClockGet ()/ 10 / 3);
}
}

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

    [引用 USER="Cole Mowrer">无论如何、我的程序现在卡在等待 ADC 转换完成(即 while (!ADCIntStatus (ADC0_BASE、0、false){})的 while 循环中。通过调用 ADCIntEnable ()和 IntMasterEnable ()代码、已发布的代码启用 ADC 中断、但在处理程序中没有显示中断。 如果您尚未安装中断处理程序,则程序将在 CCS 提供的 tm4c123gh6m_startup_ccs.c 文件中的 IntDefaultHandler()中的无限循环中结束。 程序冻结后,如果暂停调试器,我希望程序卡在 IntDefaultHandler()函数中。

    TivaWare_C_Series-2.1.4.178\examples\boards\ek-tm4c123gxl\USB_dev_gamepad\USB_dev_gamepad.c 显示 ADCIntStatus()可在 main ()函数中轮询,而无需启用 ADC 中断。 即,如果您删除对 ADCIntEnable()和 IntMasterEnable()的调用,我希望程序将不再冻结。

    此外,为了避免竞争条件,对 ADCIntClear ()的调用应移至等待 ADCIntStatus ()返回 true 的循环之后,该循环与 USB_dev_gamepad.c 示例中的代码行。

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

    因此我进行了更改以反映 gamepad.c 示例,并且删除了 ADCIntEnable()和 IntMasterEnable(),并移动了 ADCIntClear ()。 但是,现在程序卡在 FaultISR()中。

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

    [引用 user="Cole Mowrer">但是,现在程序卡在 FaultISR ()中。运行代码时,我能够重复它卡在 FaultISR 中的问题。 根据 StellarisRegistered微控制器软件故障诊断中的建议 ,发现总线故障访问地址0x40038000 (即 ADC0 ADC 活动采样序列发生器寄存器)。 ConfigureADC() 函数的开头为:

    //
    //启用外设 ADC0并复位以应用
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_ADC0);
    SysCtlPeripheralReset (SYSCTL_Periph_ADC0);
    
    //
    //禁用 ADC0序列发生器0并重新配置 ADC0序列发生器
    //
    ADCSequenceDisable (ADC0_BASE、0); 

    其中第一个 ADC0寄存  器尝试由 ADCSequenceDisable()函数访问,是发生总线故障的 ADC 活动采样序列发生器寄存器。

    在 Tiva 部件上、数据表提到、在外设准备好被访问之前、当外设被启用或复位时、可能会有延迟。 在外设就绪前尝试访问外设会导致总线故障。 通过将 ConfigureADC 函数更改为等待 ADC0外设变为就绪停止、程序卡在故障 ISR 中:

    //
    //启用外设 ADC0并复位以应用
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_ADC0);
    while (!SysCtlPeripheralReady (SYSCTL_Periph_ADC0))
    {
    }
    SysCtlPeripheralReset (SYSCTL_Periph_ADC0);
    while (!SysCtlPeripheralReady (SYSCTL_Periph_ADC0))
    {
    } 

    请注意、数据表中未指定外设准备就绪的实际延迟、因此很难知道程序是否会遇到故障。 为了保持稳健性、在第一次尝试访问外设之前、应该使用 while (!SysCtlPeripheralReady())循环。

    已停止程序卡在 FAULTISR 中、然后该程序卡在等待 ADC 转换完成时。 意识到程序缺少对 ADCSequenceEnable()的调用来启用 ADC 序列发生器。 在将 ADCSequenceEnable (ADC0_BASE,0)调用添加到 ConfigureADC()之后,程序现在已成功运行。 完整代码为:

    #include 
    #include 
    #include 
    #include "driverlib/adc.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    
    
    
    
    
    
    
    #include "driverlib/rom.h"#include "hw_intrinc/包含"#driver.h"#driverintrinc/包含"hw_intrinc/包含"#driverlib.h"#driverintrinc/包含"hw_intrinc/包含"#driverlib.h"#driverintrinc/包含"hw_intrinc/包含#def"#driverintrinc/包含"hw_intrintrinc/包含#def"#driverlib.hw_hw_intrintrintrintrinc/包含#def"#def"#def"#include"#def"hw_intrinc.h"#def"hw_intrinc #
    
    
    
    
    //
    //配置 ADC 及其引脚。
    ////
    *****************
    void
    ConfigureADC (void)
    {
    //---- ADC 设置---
    ///----------------------------
    //
    //启用外设 ADC0并复位以应用
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_ADC0);
    while (!SysCtlPeripheralReady (SYSCTL_Periph_ADC0))
    {
    }
    SysCtlPeripheralReset (SYSCTL_Periph_ADC0);
    while (!SysCtlPeripheralReady (SYSCTL_Periph_ADC0))
    {
    }
    
    //
    //禁用 ADC0序列发生器0并重新配置 ADC0序列发生器
    //
    ADCSequenceDisable (ADC0_BASE、0);
    ADCSequenceConfigure (ADC0_BASE、0、ADC_TRIGGER_PROCESSOR、0);
    ADCSequenceStepConfigure (ADC0_BASE、0、0、ADC_CTL_TS /* AIN0*/| ADC_CTL_IE | ADC_CTL_END);
    
    //
    //启用序列,但尚未启动。
    //
    ADCSequenceEnable (ADC0_BASE、0);
    
    //
    //启用 GPIO 端口 E 并将引脚3设置为 ADC 类型
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOE);
    GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_3);
    }
    
    //*********
    //
    //配置 UART 及其引脚。 这必须在 UARTprintf()之前调用。
    ////
    *****************
    void
    ConfigureUART (void)
    {
    //---- UART 设置---
    ///----------------------------
    //
    //启用 GPIO 和 UART 1外设
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);
    SysCtlDelay(3);
    SysCtlPeripheralEnable (SYSCTL_Periph_UART1);
    SysCtlDelay(3);
    
    //
    //为 UART 模式配置 GPIO 引脚
    //
    GPIOPinConfigure (GPIO_PB1_U1TX);
    GPIOPinTypeUART (GPIO_PORTB_BASE、GPIO_PIN_1);
    
    //
    //使用内部16MHz 振荡器作为 UART 时钟源。
    //
    UARTClockSourceSet (UART1_base、UART_CLOCK_PIOSC);
    
    //
    //初始化 UART (端口、波特率、时钟源)
    //
    UARTStdioConfig (0、9600、16000000);
    }
    
    
    int main (void){
    uint32_t 结果;
    易失性浮动电压;
    //
    //时钟设置为40MHz
    //
    SysCtlClockSet (SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHz);
    
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);
    GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_2);
    
    ConfigureADC();
    ConfigureUART();
    
    UARTprintf ("Hello、world!\n");
    
    while (1)
    {
    //
    //打开蓝色 LED。
    //
    GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、GPIO_PIN_2);
    
    //
    //延迟一位。
    //
    SysCtlDelay (SysCtlClockGet ()/ 10 / 3);
    
    ///-------- ADC --------------
    //
    //请求 ADC 转换
    //
    ADCProcessorTrigger (ADC0_BASE、0);
    
    //
    //等待转换完成
    //
    while (!ADCIntStatus (ADC0_BASE、0、false))
    {
    }
    
    //
    //清除 ADC0序列发生器3的中断标志
    //
    ADCIntClear (ADC0_BASE、0);
    
    //---- 处理数据---
    //
    //读取数据并转换
    //
    ADCSequenceDataGet (ADC0_BASE、0、结果);
    电压=结果*0.000805664;
    
    //
    //关闭蓝色 LED。
    //
    GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、0);
    
    //
    //延迟一位。
    //
    SysCtlDelay (SysCtlClockGet ()/ 10 / 3);
    }
    }
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    非常感谢! 它现在似乎正在工作...直到我拧上其他东西。 哈哈
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    切斯特、

    超出预期-再一次-很棒的工作!   必须要注意!   (多个龙-按顺序到达-全部为中和(&描述得很好...)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    切斯特、
    非常感谢您提供的帮助!!!