Different HSADC Match setting got same result

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

Different HSADC Match setting got same result

1,239 Views
cpchen
Contributor III

Dear Sir, 

I been testing my LPC4370 board for a project,  encounter a problem that when changing descriptor match number, I did not see the expected effective sampling rate change.  below are three cases with match value equal to 80, 160, 1600.  they are very similiar.   

I have been checking the code many times, couldn't figure out where went wrong.   Can anyone give advise, very appreciated !   raymundovelarde   I learn many from your posts, say thanks here.  

   

           Match = 80                                                                    Match = 160

pastedImage_1.png pastedImage_2.png      

                Match = 1600

pastedImage_6.png

Test scenario : 

/**********************************************************

* SET HSADC Clock to 20MHz

  * input signal is 60Hz sin wave

  * use interrupt to store 33,332 converted result to SDRAM,

  * using different match value to verify match value function

**********************************************************/

Code of HSADC setting is here,  full program attached as attachment 

void HSADC_Setup(void)

{

    uint32_t freqHSADC = 0;

/* HSADC settings */

 

/* 设定 HSADC Clock = 20MHz  */

 

Chip_USB0_Init();

Chip_Clock_SetDivider(CLK_IDIV_A,CLKIN_USBPLL,2);

Chip_Clock_SetDivider(CLK_IDIV_E, CLKIN_IDIVA, 12);

Chip_Clock_SetBaseClock(CLK_BASE_ADCHS, CLKIN_IDIVE, true, false);

/* Enable HSADC register Clock */

Chip_Clock_EnableOpts(CLK_MX_ADCHS, true, true, 1);

/* Enable HSADC sample Clock */

Chip_Clock_Enable(CLK_ADCHS);

 

/*  初始化中断设定及状态  */

            LPC_ADCHS->INTS[0].CLR_EN   = 0x7F; // disable interrupt 0

            LPC_ADCHS->INTS[0].CLR_STAT = 0x7F; // clear interrupt status

            while(LPC_ADCHS->INTS[0].STATUS & 0x7D); // wait for status to clear, have to exclude FIFO_EMPTY

            LPC_ADCHS->INTS[1].CLR_EN   = 0x7F;

            LPC_ADCHS->INTS[1].CLR_STAT = 0x7F;

            while(LPC_ADCHS->INTS[1].STATUS & 0x7D);

 

            /* 初始化HSADC */

            LPC_ADCHS->POWER_DOWN = 0;

            LPC_ADCHS->FLUSH = 1;

            Chip_HSADC_Init(LPC_ADCHS);

 

/* FIFO interrupt 1, No Packed mode  */

Chip_HSADC_SetupFIFO(LPC_ADCHS, 1, false);

 

/*  HSADC starts with Table 0, Descriptor1 */

LPC_ADCHS->DSCR_STS = (1 << 1)| 0;

 

/*Set Table 0,Desciptor 0 , match no is the test target*/

/* Match value of 80,160,1600 give almost same waveform, very strange  */

LPC_ADCHS->DESCRIPTOR[0][0] = (1 << 24) /* RESET_TIMER*/

| (0 << 22) /* THRESH*/

| (1600 << 8) /* set desired MATCH number here */

| (1 << 6) /* BRANCH to First*/

| (1 << 4) /* interrupt when conversion done */;

/* Set descriptor 1 to take a measurement after 0x9A clocks and branch to first descriptor*/

LPC_ADCHS->DESCRIPTOR[0][1] = (1 << 31) /* UPDATE TABLE*/

| (1 << 24) /* RESET_TIMER*/

| (0x9A << 8) /* MATCH wait 0x9A for HSADC to stabilize*/

| (0x01 << 6) /* BRANCH to first*/;

 

LPC_ADCHS->CONFIG = (0x90 << 6) /* RECOVERY_TIME*/

| (0 << 5) /* CHANNEL_ID_EN*/

| (0x01) /* TRIGGER_MASK*/;

 

/* Setup HSADC interrupts on group 0 - FIFO trip (full), FIFO overrun

       error, and descriptor statuses */

    Chip_HSADC_EnableInts(LPC_ADCHS, 0, (HSADC_INT0_FIFO_FULL | HSADC_INT0_DSCR_DONE |

                                        HSADC_INT0_FIFO_OVERFLOW | HSADC_INT0_DSCR_ERROR));

 

    /* do not use any bias */

    Chip_HSADC_SetACDCBias(LPC_ADCHS, 0, HSADC_CHANNEL_NODCBIAS, HSADC_CHANNEL_NODCBIAS);

 

 

/* Configure HSAC power and speed setting and set data format to offset binary  */

Chip_HSADC_SetPowerSpeed(LPC_ADCHS, true);

 

 

/* Enable HSADC interrupts in NVIC */

    NVIC_EnableIRQ(ADCHS_IRQn);

 

/* Enable HSADC Power */

Chip_HSADC_EnablePower(LPC_ADCHS);

Chip_HSADC_UpdateDescTable(LPC_ADCHS,0);

 

 

freqHSADC = Chip_HSADC_GetBaseClockRate(LPC_ADCHS);

printf("%5d" , freqHSADC); /* print out CPU base clock, */

}

Labels (1)
0 Kudos
6 Replies

1,095 Views
Ray_V
Contributor V

I don't see anything in the ADCHS setup that could be a problem.

The show data function hoever does not print consecutive addresses. You add addr_jump every loop which means you skip several addresses.

void show_data_out(void)
/* due to screen limit, we want to make output data stop when filling one screen full, so we take part of the sampl data */
{
  uint32_t *addr_a, i, addr_jump, Overrun_status;
  addr_jump = test_fifo_count / 3750;

  addr_a = (uint32_t *)SDRAM_A_PART;
  for(i=0;i<3750;i++)
  {
    get_data = *(addr_a+=addr_jump);
    hi_da[i] = (get_data >> 16) & 0x0fff;
    if(hi_da[i] > 2048)hi_da[i] = (hi_da[i] - 4096);
    low_da[i] = (get_data >> 6) & 0x0fff;

    //Overrun_status = (get_data >> 1) & 0x00000001;
    if(low_da[i] > 2048)low_da[i] = (low_da[i] - 4096);
    printf("%5d ", low_da[i]);
  }
}

Also you are reading LPC_ADCHS->LAST_SAMPLE[0] which never contains "packed" data (2 samples per word), and you did not set "packed data" any way.

I think this function will do what you want to do:

void show_data_out(uint32_t addr_jump)
/* due to screen limit, we want to make output data stop when filling one screen full, so we take part of the sampl data */ 
{
 uint32_t *addr_a, i;

 addr_a = (uint32_t *)SDRAM_A_PART;
 addr_a += addr_jump;

 for(i=0;i<3750;i++)
 {
  // left justify for signedness (2's complement used)
  low_da[i] = (*(addr_a++) >> 2) & 0xffff;
  // shift for 12-bit accuracy
  low_da[i] = low_da[i] >> 4;

  printf("%5d ", low_da[i]);
 }
}
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Just pass it the starting sample you want to display from.

Test with this to make sure the samples you are using are contiguous addresses

0 Kudos

1,095 Views
cpchen
Contributor III

Hi Raymundo, 

THanks for the advise, I also found it might be due to I enable too many interrupt like below.  

Chip_HSADC_EnableInts(LPC_ADCHS, 0, (HSADC_INT0_FIFO_FULL | HSADC_INT0_DSCR_DONE |

                                        HSADC_INT0_FIFO_OVERFLOW | HSADC_INT0_DSCR_ERROR));

 

I will test change interrupt to only enable DSCR_DONE,  following and also your advise next week when come back from travel

Chip_HSADC_EnableInts(LPC_ADCHS, 0, HSADC_INT0_DSCR_DONE);

Best REgards,

0 Kudos

1,095 Views
Ray_V
Contributor V

I didn't pay attention to the enabled interrupts, but most of them only occur when there is an error.

I assume you are running the processor at the example default of 204MHz. You are running the ADCHS clock at 20MHz, with MATCH Number set at 80 you should be sampling at 250K sps, set at 160 you have 125K sps and at 1600 you have 12.5K sps so I doubt that   FIFO_OVERFLOW ever occurs.

DSCR_ERROR won't occur otherwise you would have no samples.

You have set FIFO_LEVEL to 1 so unless your processor can't keep up, the FIFO_FULL interrupt will not occur.

What I notice is that in your Interrupt Handler you don't check which interrupt occurred, also you don't clear the interrupt flag.

-Ray

0 Kudos

1,095 Views
cpchen
Contributor III

Ray,  Thanks for the advise, it's very helpful.  I will add interupt source check and clear the interrupt in interrupt handler. will post te result afer testing.

- CP

0 Kudos

1,095 Views
Ray_V
Contributor V

I just thought of another possibility.

If you find that interrupts are not fast enough to transfer data without getting the FIFO_FULL and/or FIFO_OVERFLOW interrupts it could be because your Vector Table and Interrupt Handler are in SPIFI Flash, which increases the interrupt latency. 

Place your Vector Table and Interrupt Handler to RAM. This is a good idea to do in any case.

You could also try using DMA to transfer the ADCHS samples to memory.

-Ray

0 Kudos

1,095 Views
cpchen
Contributor III

Ray, 

We have solve the problem after adding clear interrupt on the interupt handler routine.  thanks for the advise.  we will now move on with faster HSADC sampling rate and using DMA to transfer to SDRAM. we will need to use 80MHz HSADC & DMA & SDRAM in our project .

It's good advise of placing to RAM,  we will not test it as the project will use DMA to store sample data to SDRAM,  thanks anyway. 

CP

0 Kudos