LPC1769 ADC Read

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

LPC1769 ADC Read

2,089 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rattus on Thu Aug 11 06:25:32 MST 2011
Hi - I'm having problems reading adc channels other than 0 - they hang in the ADC_ChannelGetStatus loop for channels 1-7; doesn't mater which one. The channels are being initialized identically, I'm making my conversions the same way (and individually - not burst mode), and as far as I can tell, the initialization is being performed correctly.

        PinCfg.Funcnum = 1;
        PinCfg.OpenDrain = 0;
        PinCfg.Pinmode = 0;
        PinCfg.Pinnum = 23;
        PinCfg.Portnum = 0;
        PINSEL_ConfigPin(&PinCfg);
...etc.

        ADC_Init(LPC_ADC, 1000000);
        ADC_IntConfig(LPC_ADC,ADC_CHANNEL_0,DISABLE);
        ADC_ChannelCmd(LPC_ADC,ADC_CHANNEL_0,ENABLE);
        ADC_IntConfig(LPC_ADC,ADC_CHANNEL_1,DISABLE);
        ADC_ChannelCmd(LPC_ADC,ADC_CHANNEL_1,ENABLE);
        ADC_IntConfig(LPC_ADC,ADC_CHANNEL_2,DISABLE);
        ADC_ChannelCmd(LPC_ADC,ADC_CHANNEL_2,ENABLE);
...etc.

        ADC_StartCmd(LPC_ADC,ADC_START_NOW);
        while (!(ADC_ChannelGetStatus(LPC_ADC,ADC_CHANNEL_0,ADC_DATA_DONE)));
        ADC_Val[0] = ADC_ChannelGetData(LPC_ADC,ADC_CHANNEL_0);
        while (!(ADC_ChannelGetStatus(LPC_ADC,ADC_CHANNEL_1,ADC_DATA_DONE)));
        ADC_Val[1] = ADC_ChannelGetData(LPC_ADC,ADC_CHANNEL_1);
        while (!(ADC_ChannelGetStatus(LPC_ADC,ADC_CHANNEL_2,ADC_DATA_DONE)));
        ADC_Val[2] = ADC_ChannelGetData(LPC_ADC,ADC_CHANNEL_2);



Only the Channel 0 conversion completes. If I comment out the Channel 0 read, Channel 1 hangs on ChannelGetStatus. Same with 2.

I'm obviously missing something here - any ideas?

Thanks,

Mike
0 项奖励
回复
8 回复数

1,883 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by federoasio on Sat Jun 23 11:14:34 MST 2012
Hi rattus, I'm having exactly the same problem you did, but I can't undestand how did you fix it. Would you help me please?
0 项奖励
回复

1,883 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Thu Aug 11 08:01:06 MST 2011

Quote: rattus
From which distribution are your header files sourced?



NXP_LPCXpresso1769_MCB1700_2011-02-11.zip\ADC sample
0 项奖励
回复

1,883 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rattus on Thu Aug 11 07:55:31 MST 2011
In your header file, yes. in my LPC17xx_adc.h, sadly not...

They're named ADC_DR_DONE_FLAG and ADC_DR_OVERRUN_FLAG in lpc17xx_adc.h

From which distribution are your header files sourced? Mine come out of the Lib_MCU and were authored by NXP.

Thanks, the conversions now work great. As the ADDRs are separate in my lpc17xx.h header, I had to use a switch statement instead of the channelNum array index, but no problem.
0 项奖励
回复

1,883 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Thu Aug 11 07:31:47 MST 2011

Quote: rattus
What are the values of ADC_DONE and ADC_OVERRUN?



Described in adc.h:

#define ADC_DONE            0x80000000
#define ADC_OVERRUN    0x40000000
#define ADC_ADINT           0x00010000
0 项奖励
回复

1,883 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rattus on Thu Aug 11 07:27:15 MST 2011
Thanks Zero - you obviously have a different header file.

What are the values of ADC_DONE and ADC_OVERRUN?
0 项奖励
回复

1,883 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Thu Aug 11 07:01:59 MST 2011
You can also find a wonderful ADC read polling function in:

In NXP_LPCXpresso1769_MCB1700_2011-02-11.zip\ADC sample

/*****************************************************************************
** Function name:        ADCRead
**
** Descriptions:        Read ADC channel
**
** parameters:            Channel number
** Returned value:        Value read, if interrupt driven, return channel #
** 
*****************************************************************************/
uint32_t ADCRead( uint8_t channelNum )
{
#if !ADC_INTERRUPT_FLAG
  uint32_t regVal, ADC_Data;
#endif

  /* channel number is 0 through 7 */
  if ( channelNum >= ADC_NUM )
  {
    channelNum = 0;        /* reset channel number to 0 */
  }
  LPC_ADC->CR &= 0xFFFFFF00;
  LPC_ADC->CR |= (1 << 24) | (1 << channelNum);    
                /* switch channel,start A/D convert */
#if !ADC_INTERRUPT_FLAG
  while ( 1 )            /* wait until end of A/D convert */
  {
    regVal = LPC_ADC->DR[channelNum];
    /* read result of A/D conversion */
    if ( regVal & ADC_DONE )
    {
      break;
    }
  }    
        
  LPC_ADC->CR &= 0xF8FFFFFF;    /* stop ADC now */    
  if ( regVal & ADC_OVERRUN )    /* save data when it's not overrun, otherwise, return zero */
  {
    return ( 0 );
  }
  ADC_Data = ( regVal >> 4 ) & 0xFFF;
  return ( ADC_Data );    /* return A/D conversion value */
#else
  return ( channelNum );    /* if it's interrupt driven, the ADC reading is 
                            done inside the handler. so, return channel number */
#endif
}
Anyway, using debugger to read ADC->ADCR register (bit 7:0 = selected AD channel) while your program is hanging will show you which channel is selected :eek:

I'm not familiar with the funny example you are using, but I think  ADC_ChannelCmd is selecting the channel and therefore has to be called each time before ADC_StartCmd (which just starts the selected channel) is used
0 项奖励
回复

1,883 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rattus on Thu Aug 11 06:54:41 MST 2011
Pins 0.23, 24, and 25 are set to AD0.0, 1 and 2, respectively.

I am using the functions in the (pretty sure latest) Lib_MCU...

void ADC_StartCmd(LPC_ADC_TypeDef *ADCx, uint8_t start_mode)
{
        CHECK_PARAM(PARAM_ADCx(ADCx));
        CHECK_PARAM(PARAM_ADC_START_OPT(start_mode));

        ADCx->ADCR &= ~ADC_CR_START_MASK;
        ADCx->ADCR |=ADC_CR_START_MODE_SEL((uint32_t)start_mode);
}


where

#define ADC_CR_START_MASK       ((7UL<<24))
0 项奖励
回复

1,883 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Thu Aug 11 06:34:11 MST 2011
Did you check your Pinsel settings (Debugger: Peripherals View-> PCB) ?


Quote:

ADC_StartCmd(LPC_ADC,ADC_START_NOW);

should do something like:

LPC_ADC->ADCR = START_ADC | OPERATIONAL_ADC | SEL_AD0 ;

that should be stopped after reading AD0 and next channel should be started :)
0 项奖励
回复