This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RM48 ADC Conversion logic

Other Parts Discussed in Thread: HALCOGEN

Hello,

I wanted confirmation if I understand how adc conversion works for each channel.

In Halcogen, the ADC1, Group 1 configuration is:

The following routine evaluates each and every channel defined above.  So every invocation of bsp_ADC1_GET, Channels 0,1,2,3,4,5,6,8,10,11,12,13,14,15,16,18 all get converted.  Is this correct?

uint16  bsp_ADC1_GET (uint8 terminal)
{

  adcData_t adc_data;
  adcData_t *adc_data_ptr = &adc_data;

  /** - Start Group ADC Conversion
  */
  adcStartConversion_SelChn(adcREG1, terminal, ADC_FIFO_SIZE, ADC_SUBGROUP_01);

  /** - Wait for ADC Group conversion to complete */
  while(!adcIsConversionComplete(adcREG1, ADC_SUBGROUP_01));

   /** - Read the conversion result
   */
   adcGetSingleData(adcREG1, ADC_SUBGROUP_01, adc_data_ptr);

   return(adc_data_ptr->value);
}

The following routine, simply recalls the last converted value for a channel from RAM.  It does not actually do any conversion itself.  Correct?

void adcGetSingleData(adcBASE_t *adc, unsigned group, adcData_t *data)
{
  unsigned  buf;
  adcData_t *ptr = data;

  /** -  Get conversion data and channel/pin id */
  buf        = adc->GxBUF[group].BUF0;
  ptr->value = (unsigned short)(buf & 0xFFFU);
  ptr->id    = (unsigned short)((buf >> 16U) & 0x1FU); //!< int to unsigned short

  adc->GxINTFLG[group] = 9U;

}

If adcGetSingleData truly does not do any conversion for a single channel, is there any way to request for a single channel conversion, without having to convert everything in the group?

Thanks.

Ubaid

  • Ubaid,

    You are right: every invocation of bsp_ADC1_GET converts every channel selected for conversion in group1.

    The adcgetSingleData routine returns a single conversion result from the group1 results' FIFO. This value is the conversion result of the first channel selected for conversion in that group (it is a First In First Out buffer).

    If you want to convert a single channel, you need to only pick that one channel by setting the appropriate bit in the ADG1SEL register. You can enable the other channels for conversion in another group (Event or group2) and then trigger that group separately.

    Regards,
    Sunil
  • Thank you Sunil,

    Also wanted clarification that ADC1 group 1 is unrelated in function to ADC2 group 1. There are essentially 4 different groups the channels can be gathered in (excluding group events).

    Thanks.
    Ubaid
  • That is correct. Note that all ADC2 channels are also shared with ADC1. Any particular reason for excluding the default event-triggered group from your count?

    Sunil
  • Partly lack of understanding in our requirements and also lack of understanding in TI feature set. We already finalized our pin configuration and so will have to wait until another hw respin to re-evaulate using hw triggers.

    I wanted to ask, it seems that currently we do overwrite ADG1SEL to evaluate a single adc channel. If we evaluate the entire group, how would we request the value for a specific channel in the group? So if the group has pins 1,2, and 3, how do we get the adc conversion for pin 2 after the conversion is completed?

    Thanks.
    Ubaid
  • Ubaid,

    The good thing about h/w triggers is that they don't necessarily cost you pin functions. For example, the connection from the N2HET1 module to the ADC1/2 modules is done internally within the MCU, so no external connection is required to trigger the ADC1/2 using the selected N2HET1 channels. Just something to consider.

    The ADC allows the application direct access to the result memory as well. For your example, let us say you have configured channels 1, 2 and 3 for conversion in group1. Also assume that the event group is allocated no buffers in the results' memory (ADBNDCR.BNDA = 0). That means that the group1 conversions are stored in ADC1 result memory starting from address 0xFF3E_0000 onwards.

    Conversion results are stored in the ADC memory in the order in which they are converted. So, in your example, the conversion result for channel 1 will be at 0xFF3E0000, that for channel 2 will be at 0xFF3E0004 and that for channel 3 will be at 0xFF3E0008.

    If you only want to read channel 2's conversion result, you can read directly from 0xFF3E0004. Note that the channel id is always stored in the result. The format is as shown in section 19.3.9.2 in the TRM (spnu503B, pages 680 and 681).

    Sunil

  • Hello Sunil,

    I need some guidance in finding the correct starting address for ADC1 group 1 and group 2 conversions in RAM.  Below are the configurations for ADC1 group1 and group2 in halcogen.

    Memory configuration for ADC1.

    Below is a screenshot of both memory mapping, as well as register values for BNDR, and BNDEND for ADC 1 at run-time.  

    You can see that BNDA = 0x8, and BNDB = 0x10.

    1) Group 1 Conversion Address?

    Based on 19.3.9.3, I gather then that Group 1 conversions should start at (0xFF3E0000 + BNDA) = 0xFF3E0008.  This is not correct as the memory map shows the data Group 1 data starts at 0xFF3E0040.

    Is the correct way to determine the address (section 19.3.8) of the first conversion in ADC1 Group1 determined by (Base Address + 4 * (2*BNDA))?  4 is the number of bytes associated per conversion.  This results in (0xFF3E0000 + 4*(2*8)) = 0xFF3E0040.

    2) Group 2 Conversion Address?

    Based on 19.3.8, the group 2 conversion address should be (Base Address + 4*(2*BNDA) + 4*(BNDB - BNDA)).  This would be  (0xFF3E0000 + 4*(2*8) + 4(16 - 8)) = 0xFF3E0060.  Is this correct?

    3) Group 2 Conversion Request Fails:

    I make a request to convert ADC1 Group2.  The conversion does not ever complete and gets held up in the wile loop below.  Why would this be the case?  The below routine is also used to successfully request conversion of ADC1 Group1.

    void  bsp_ADC1_SampleGroup ( uint8 group)
    {
    	   if( (group == ADC_GROUP_01) || (group == ADC_GROUP_02))
    	   {
    		   adcStartConversion(adcREG1, group);
    
    		   while(!adcIsConversionComplete(adcREG1, group));
    	   }
    }

    Thanks.

    Ubaid

  • Hello Ubaid,

    Answering each question separately:

    1) Group 1 Conversion Address?

    Based on 19.3.9.3, I gather then that Group 1 conversions should start at (0xFF3E0000 + BNDA) = 0xFF3E0008.  This is not correct as the memory map shows the data Group 1 data starts at 0xFF3E0040.

    Is the correct way to determine the address (section 19.3.8) of the first conversion in ADC1 Group1 determined by (Base Address + 4 * (2*BNDA))?  4 is the number of bytes associated per conversion.  This results in (0xFF3E0000 + 4*(2*8)) = 0xFF3E0040.

    >> Yes, the value stored in BNDA chooses how many pairs of buffers are available for the event group (same applies for BNDB). So when you choose BNDA = 8, the first 16 buffers are available for the event group. This takes 16 * 4-bytes = 64 bytes. Therefore, the group1 results start at offset of 0x40.

    2) Group 2 Conversion Address?

    Based on 19.3.8, the group 2 conversion address should be (Base Address + 4*(2*BNDA) + 4*2*(BNDB - BNDA)).  This would be  (0xFF3E0000 + 4*(2*8) + 4*2*(16 - 8)) = 0xFF3E00680.  Is this correct?

    >> Yes, as you can see from the register contents, BNDB is programmed to be 0x10. This configures 16 buffers available for group1 conversions. So the group2 conversion results are stored starting from an offset of 32 * 4-bytes = 128 bytes, or an offset of 0x80. I have made the correction in the formula in your question above.

    3) Group 2 Conversion Request Fails:

    I make a request to convert ADC1 Group2.  The conversion does not ever complete and gets held up in the wile loop below.  Why would this be the case?  The below routine is also used to successfully request conversion of ADC1 Group1.

    void  bsp_ADC1_SampleGroup ( uint8 group)
    {
    	   if( (group == ADC_GROUP_01) || (group == ADC_GROUP_02))
    	   {
    		   adcStartConversion(adcREG1, group);
    
    		   while(!adcIsConversionComplete(adcREG1, group));
    	   }
    }
    

    >> Group2 is configured to be triggered on a rising edge on GIOB[0], and not software-triggered. The above code extract only configures the number of channels to be converted and then starts polling for the conversions to complete. The actual conversions will only start once a rising edge appears on GIOB[0]. Only then the code execution will exit this while loop. If this is not the desired functionality, you may want to change group2 to be software-triggered using the HALCoGen GUI.

    Regards,
    Sunil
  • Thanks Sunil!

    The address mapping makes sense and does correlate with values in the memory browser.

    I didn't see that ADC1, Group 2 was setup for a hardware interrupt. Good catch!

    Ubaid
  • Sunil,

    What is the correlation of the fifo size to the conversion result in RAM? For single conversion, there is help text in halcogen that the fifo size should be the number of channels to convert. For ADC1 Group1, if I set the fifo size to 1, I do not see any behavior difference compared to if I were to 5.

    Please advise.
    Thanks.
    Ubaid

    Edit:  Looked at the chip specifications, and didn't see where it was defined exactly how the FIFO's function.

  • Ubaid,

    The actual memory allocated for each group's conversion results is configured using the BNDx registers. This is graphically configured via the "ADCx Memory" tab in HALCoGen. The "FIFO Size" configuration on the individual group configuration tab is slightly confusing, I agree. This configures the group's interrupt threshold counter. That is, how many conversions should the ADC accumulate for that group before it generates the group's threshold interrupt flag? For a single conversion sequence the ADC will always convert the number of channels selected and then stop. So you can use the "group conversion end" status flag to generate the interrupt. If you are periodically triggering a conversion group, then you can choose to have a multiple of the number of channels converted before triggering the interrupt. For example, if you have 3 channels selected for conversion in group1, you can make the ADC accumulate up to 60 conversion results for group1 before interrupting the CPU. You will still need to trigger the ADC every 3 conversions, and you need to configure the ADC to not reset the results' memory each time that group is triggered.

    Regards,
    Sunil