使用LPC1752的ADC第5通道,读取寄存器DR5的值都一直为0xFFF

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

使用LPC1752的ADC第5通道,读取寄存器DR5的值都一直为0xFFF

1,506 Views
zhanglei2015xx
Contributor II

使用LPC1752的ADC第5通道,按照下面两种方式读取寄存器DR5的值都一直为0xFFF。 请问是哪里出错了呢?谢谢 软件ADC初始化配置 Chip_IOCON_PinMux(LPC_IOCON, 1, 31, IOCON_MODE_INACT, IOCON_FUNC3);//AD0.5 /*电池电压检测 */ // LPC_IOCON->PINSEL[3] |= (3ul<<30); // LPC_IOCON->PINMODE[3] |= (2ul<<30); LPC_SYSCTL->PCONP |= (1ul<<12); //功率使能 LPC_ADC->CR |= (1ul<<5); //选择5通道 LPC_ADC->CR |= (11ul<<8); //DIV = 11 ADCclk = 6MHz/(11+1) = 500KHz LPC_ADC->CR |= (1ul<<21); //ADC处于正常工作模式 读取方式1: #define BURST_EN() LPC_ADC->CR |= (1ul<<16) //硬件转换 #define BURST_DIS() LPC_ADC->CR &= ~(1ul<<16) uint32_t ADCBURSTRead(uint8_t channelnum) { uint32 clear,rt; clear = clear; clear = LPC_ADC->DR[channelnum]; //转换前清除完成标志 读取清除 LPC_ADC->INTEN = 0; BURST_EN(); while(!(LPC_ADC->STAT&(1ul<<channelnum))); 等待转换完成="" rt="(LPC_ADC-">DR[channelnum]>>4)&0x0FFF; BURST_DIS(); return rt; } 读取方式2: uint32_t ADC0Read( uint8_t channelNum ) { int32_t counter; uint32_t regVal, ADC_Data; counter = 0xFFFF; LPC_ADC->CR &= 0xFFFFFF00; LPC_ADC->CR |= (1 << 24) | (1 << channelNum); /* switch channel,start A/D convert */ while ( counter-- ) /* wait until end of A/D convert */ { regVal = LPC_ADC->DR[channelNum]; /* read result of A/D conversion */ if ( regVal & 0x80000000 ) { break; } } LPC_ADC->CR &= 0xF8FFFFFF; /* stop ADC now */ if ( (regVal & 0x40000000)||(counter<10) ) /* 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 */ } 硬件原理图:

Labels (1)
Tags (1)
0 Kudos
Reply
1 Reply

1,157 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi feilix zhang,

    刚刚检查了下你的代码,还是发现了些问题。

   我发现你的代码有些问题的。

  1. PCONP中没有使能IOCON位

   2.看到手册上面关于BURST有这样的一句话:

pastedImage_1.png

所以我觉得你再使能BURST=1的时候,最好保证START=0。

  3. 我认为你可以用软件去启动试试。

   我这边在MCB1768板子上面,使用了纯寄存器控制方式的代码,能够正确采集ADC0.5通道,下面是我的代码供你参考:

/*----------------------------------------------------------------------------
 * Name:    ADC.c
 * Purpose: low level ADC functions
 * Note(s): possible defines select the used ADC interface:
 *            __ADC_IRQ   - ADC works in Interrupt mode
 *                        - ADC works in polling mode (default)
 *----------------------------------------------------------------------------
 * This file is part of the uVision/ARM development tools.
 * This software may only be used under the terms of a valid, current,
 * end user licence from KEIL for a compatible version of KEIL software
 * development tools. Nothing else gives you the right to use this software.
 *
 * This software is supplied "AS IS" without warranties of any kind.
 *
 * Copyright (c) 2008-2011 Keil - An ARM Company. All rights reserved.
 *----------------------------------------------------------------------------*/

#include "LPC17xx.H"                         /* LPC17xx definitions           */
#include "ADC.h"

uint16_t AD_last;                            /* Last converted value          */
uint8_t  AD_done = 0;                        /* AD conversion done flag       */

/*----------------------------------------------------------------------------
  Function that initializes ADC
 *----------------------------------------------------------------------------*/
void ADC_Init (void) {

  LPC_SC->PCONP |= ((1 << 12) | (1 << 15));  /* enable power to ADC & IOCON   */

  LPC_PINCON->PINSEL1  &= ~( 3 << 18);
  LPC_PINCON->PINSEL1  |=  ( 1 << 18);       /* P0.25 is AD0.2                */
  LPC_PINCON->PINMODE1 &= ~( 3 << 18);
  LPC_PINCON->PINMODE1 |=  ( 2 << 18);       /* P0.25 no pull up/down         */

     //JJ add p1.31 ad0.5
  LPC_PINCON->PINSEL3  &= ~( 3 << 30);
  LPC_PINCON->PINSEL3  |=  ( 3 << 30);       /* P1.31 is AD0.5                */
  LPC_PINCON->PINMODE1 &= ~( 3 << 30);
  LPC_PINCON->PINMODE1 |=  ( 2 << 30);       /* P1.31 no pull up/down         */
     
  LPC_ADC->ADCR        =  ( 1 <<  5) |//( 1 <<  2) |       /* select AD0.2 pin              *///jjmodify to select AD0.5
                          ( 4 <<  8) |       /* ADC clock is 25MHz/5          */
                          ( 1 << 21);        /* enable ADC                    */

#ifdef __ADC_IRQ
  LPC_ADC->ADINTEN     =  ( 1 <<  5);  //( 1 <<  8);        /* global enable interrupt       *///

  NVIC_EnableIRQ(ADC_IRQn);                  /* enable ADC Interrupt          */
#endif
}


/*----------------------------------------------------------------------------
  start AD Conversion
 *----------------------------------------------------------------------------*/
void ADC_StartCnv (void) {
  LPC_ADC->ADCR &= ~( 7 << 24);              /* stop conversion               */
  LPC_ADC->ADCR |=  ( 1 << 24);              /* start conversion              */
}


/*----------------------------------------------------------------------------
  stop AD Conversion
 *----------------------------------------------------------------------------*/
void ADC_StopCnv (void) {

  LPC_ADC->ADCR &= ~( 7 << 24);              /* stop conversion               */
}


/*----------------------------------------------------------------------------
  get converted AD value
 *----------------------------------------------------------------------------*/
uint16_t ADC_GetCnv (void) {

#ifndef __ADC_IRQ
//  while (!(LPC_ADC->ADGDR & ( 1UL << 31)));  /* Wait for Conversion end       */
//  AD_last = (LPC_ADC->ADGDR >> 4) & ADC_VALUE_MAX; /* Store converted value   */

     while (!(LPC_ADC->ADDR5 & ( 1UL << 31)));  /* Wait for Conversion end       */
  AD_last = (LPC_ADC->ADDR5 >> 4) & ADC_VALUE_MAX; /* Store converted value   */
     
  AD_done = 1;
#endif

  return(AD_last);
}


/*----------------------------------------------------------------------------
  A/D IRQ: Executed when A/D Conversion is done
 *----------------------------------------------------------------------------*/
#ifdef __ADC_IRQ
void ADC_IRQHandler(void) {
  volatile uint32_t adstat;

  adstat = LPC_ADC->ADSTAT;                       /* Read ADC clears interrupt     */

  //AD_last = (LPC_ADC->ADGDR >> 4) & ADC_VALUE_MAX; /* Store converted value   */
  AD_last = (LPC_ADC->ADDR5 >> 4) & ADC_VALUE_MAX; /* Store converted value   */ //ad0.5 use AD0DR5 register
     
  AD_done = 1;
}
#endif
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

有两种方式,中断和直接转换方式。你可以试试我的代码。

我这边测试是正常工作的。


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply