EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

problem in reading Global DONE bit for ADC0

Started by naderus2000 March 12, 2007
I used ADC0.3 for sampling MIC signal on the IAR KIT
and then immediately write the ADC value to DAC that connect to
an LM386.
I used Timer0 that intterupted every 22us for get ADC value and
write it to DAC.I do this in Match mode only and use simple polling
mode for ADC.I also set ADC clock to max speed 60/14=4.2MHZ<4.5MHZ
All of that is only for testing the LPC2148 peripherals.

But most of the time when I start the program the CPU
trap in reading of the DONE bit for ADC.this bit never
change to 1s.

do
{
i = AD0GDR; // Read A/D Data Register
}while ((i & 0x80000000) == 0); // Wait for end of A/D Conversion

I don't know why this happend.Most it happend in RAM debug.
I want to send the full source code but I don't know how attach it.
here is my simple code.
I don't know where can be wrong.

I also change the startup of IAR with this line:
LDR pc, [pc,#-0xFF0] ; Branch to irq_handler

for IRQ vector.It's ok and work well.
please some one help me.
Thanks.

/*************************************************
// GPIO
#define P(x) ((unsigned int)0x00000001 << (x))

// DAC
#define DACSet(Val) DACR = ((Val)<<6)

//ADC
#define Ch0 (1<<0)
#define Ch1 (1<<1)
#define Ch2 (1<<2)
#define Ch3 (1<<3)
#define Ch4 (1<<4)
#define Ch5 (1<<5)
#define Ch6 (1<<6)
#define Ch7 (1<<7)

#define CLKDIV_14 (14<<8)
#define BURST (1<<16)
#define BIT10 (0<<17)
#define BIT8 (2<<17)
#define PDN (1<<21)
#define START (1<<24)
#define EDGE_F (1<<27)

__irq __arm void Timer0ISR(void)
{
DACSet(ADCGet(Ch3));
T0IR = 1;
VICVectAddr = 0; // Clear interrupt in VIC
}

void Timer0Init(void)
{
T0IR = 0xFF; // reset match and capture event interrupts
T0TC = 0; // Clear timer counter
T0PC = 0;
T0PR = 0; // No Prescalar
T0TCR = 2; // Reset counter and prescaler
T0MR0 = 1360;
T0MCR = 3; // Reset Timer Counter & Interrupt on match
T0TCR = 1; // Intteruppt on MR0
T0CTCR = 0; // Counting enable
}

void ADCInit(void)
{
PINSEL1_bit.P0_30 = 1;
AD0CR = CLKDIV_14|BIT10|PDN;
}

short ADCGet(char channel)
{
unsigned int i;
AD0CR |= PDN|CLKDIV_14|channel;
AD0CR |= START; // Start A/D Conversion
do
{
i = AD0GDR; // Read A/D Data Register
} while ((i & 0x80000000) == 0); // Wait for end of A/D Conversion
return ((i >> 6) & 0x03FF); // bit 6:15 is 10 bit AD value
}

void VIC_Init(void)
{
VICIntSelect = 0; // Assign all interrupt chanels
to IRQ
VICIntEnClear = 0xFFFFFFFF; // Diasable all interrupts
VICSoftIntClear = 0xFFFFFFFF; // Clear all software interrutps
// VIC registers can be accessed in User or privileged mode
VICProtection = 0;
VICVectAddr = 0; // Clear interrupt
// Clear address of the Interrupt Service routine (ISR) for non-
vectored IRQs.
VICDefVectAddr = 0;
// Clear address of the Interrupt Service routine (ISR) for
vectored IRQs.
VICVectAddr0 = VICVectAddr1 = VICVectAddr2 = VICVectAddr3 VICVectAddr4 = \
VICVectAddr5 = VICVectAddr6 = VICVectAddr7 = VICVectAddr8 VICVectAddr9 = \
VICVectAddr10 = VICVectAddr11 = VICVectAddr12 = VICVectAddr13 = \
VICVectAddr14 = VICVectAddr15 = 0;
// Disable all vectored IRQ slots
VICVectCntl0 = VICVectCntl1 = VICVectCntl2 = VICVectCntl3 VICVectCntl4 = \
VICVectCntl5 = VICVectCntl6 = VICVectCntl7 = VICVectCntl8 VICVectCntl9 = \
VICVectCntl10 = VICVectCntl11 = VICVectCntl12 = VICVectCntl13 = \
VICVectCntl14 = VICVectCntl15 = 0;
}

void VIC_SetVectoredIRQ(void(*pIRQSub)(), unsigned char IRQSlot,
unsigned int IRQSrc)
{

VICIntSelect &= ~(1< *(&VICVectAddr0+IRQSlot) = (unsigned long)pIRQSub; // Set Addr
function to corresponding Slot
*(&VICVectCntl0+IRQSlot) = IRQSrc | 0x20;// Set source channel
and enable the slot
VICIntEnable |= (1< }

void SystemInit(void)
{
/************* MAM Initial **************/
MAMCR = 0x00; // Turn MAM off first
MAMTIM = 0x03; // 3 cycle wait for flash
MAMCR = 0x02; // MAM fully enabled
/************* PLL Initial **************/
PLLCFG = 0x00000024; // Set multiplier & divider of PLL to give
60.00 MHz
PLLCON = 0x00000001; // Enable the PLL
PLLFEED = 0x000000AA; // Update PLL registers with feed sequence
PLLFEED = 0x00000055;
while (!(PLLSTAT & 0x00000400)); // test Lock bit
PLLCON = 0x00000003; // Connect the PLL
PLLFEED = 0x000000AA; // Update PLL registers with feed sequence
PLLFEED = 0x00000055;
/********** Clock peripheral Initial **********/
VPBDIV = 0x01; // Peripheral clock is the same with cclk
/************* Power Control Initial **********/
// PCONP = P_TIM0|P_UART0|P_SPI1|P_AD0;
/**************** GPIO Configure **************/
SCS = 0x03; // Fast GPIO Mode
/************* Intterupt Initial **************/
VIC_Init();
VIC_SetVectoredIRQ((void(*)())Btn1DownISR, IRQ2, VIC_EINT2);
Timer0Init();
VIC_SetVectoredIRQ((void(*)())Timer0ISR, IRQ1, VIC_TIMER0);
UART0_Init();
DACInit();
ADCInit();
__enable_interrupt();
}

void main (void)
{
SystemInit();

while(1)
{
}

}

An Engineer's Guide to the LPC2100 Series

when I set the CLKDIV field of the ADCR to 18 every thing is ok.
what why with the 14 the DONE bit never 1?
ADC must work up to 4.5 MHZ and 60/14 = 4.2 MHZ so it also must work.

The 2024 Embedded Online Conference