使用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 */ } 硬件原理图:
Hi feilix zhang,
刚刚检查了下你的代码,还是发现了些问题。
我发现你的代码有些问题的。
1. PCONP中没有使能IOCON位
2.看到手册上面关于BURST有这样的一句话:
所以我觉得你再使能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!
-----------------------------------------------------------------------------------------------------------------------