I use the LWADC driver from MQX for accessing the ADC in Vybrid VF6xx by using the two functions: "_lwadc_init_input()" and "_lwadc_read_raw()".
For one single channel (ADC0SE2) this method works, but when I add a second channel (ADC0SE8) I don't get the correct samples, for any of the two channels!
Is there any restriction if I put more than one ADC channel into continuous mode by calling "_lwadc_init_input()"?
Thanks,
Johannes
Solved! Go to Solution.
Hi Johannes,
this is obviously a bug in MQX. I've written a workaround for you and will report this to MQX team. Please try my workaround and tell me if it works.
lwadc_vadc.c
boolean _lwadc_read_raw_v2( LWADC_STRUCT_PTR lwadc_ptr, LWADC_VALUE_PTR outSample)
{
ADC_MemMapPtr adc_ptr = _bsp_get_adc_base_address(lwadc_ptr->context_ptr->init_ptr->ADC_NUMBER);
LWADC_VALUE sample;
_mqx_int ch_num = adc_ptr->HC1 & 0x1F;
if( ch_num != lwadc_ptr->input )
adc_ptr->HC1 = ADC_CHANNEL(lwadc_ptr->input);
while((adc_ptr->HS & ADC_HS_COCO1_MASK) == 0){}
sample = adc_ptr->R1;
*outSample = sample & ADC_CDR_CDATA_MASK;
/* Clear conversion complete */
adc_ptr->HC1 &= ~ADC_HC1_AIEN1_MASK;
return TRUE;
}
lwadc_vadc.h
extern boolean _lwadc_read_raw_v2( LWADC_STRUCT_PTR lwadc_ptr, LWADC_VALUE_PTR outSample);
Thanks
Rene
Hi Johannes,
this is obviously a bug in MQX. I've written a workaround for you and will report this to MQX team. Please try my workaround and tell me if it works.
lwadc_vadc.c
boolean _lwadc_read_raw_v2( LWADC_STRUCT_PTR lwadc_ptr, LWADC_VALUE_PTR outSample)
{
ADC_MemMapPtr adc_ptr = _bsp_get_adc_base_address(lwadc_ptr->context_ptr->init_ptr->ADC_NUMBER);
LWADC_VALUE sample;
_mqx_int ch_num = adc_ptr->HC1 & 0x1F;
if( ch_num != lwadc_ptr->input )
adc_ptr->HC1 = ADC_CHANNEL(lwadc_ptr->input);
while((adc_ptr->HS & ADC_HS_COCO1_MASK) == 0){}
sample = adc_ptr->R1;
*outSample = sample & ADC_CDR_CDATA_MASK;
/* Clear conversion complete */
adc_ptr->HC1 &= ~ADC_HC1_AIEN1_MASK;
return TRUE;
}
lwadc_vadc.h
extern boolean _lwadc_read_raw_v2( LWADC_STRUCT_PTR lwadc_ptr, LWADC_VALUE_PTR outSample);
Thanks
Rene
Dear Rene,
when I use your function I get the correct values, but the while loop confuses me a little bit, because I don't want the read_raw-Function to be blocking (it is read from an ISR), therefore I'm going to try Juan Antonios solution!
Sorry, I meant to say the lwadc_vdac.c file.
Yeah, definitelly my suggestion will not work. The HC1 register does not expect bit-fields.
The patch from Rene should work.
I test Rene's changes updated to my version I working on (I'm not using the lwadc_vdac.c file from thread/317081), so I modified the read function in next way and it worked for me:
boolean _lwadc_read_raw(LWADC_STRUCT_PTR lwadc_ptr, LWADC_VALUE_PTR outSample)
{
ADC_MemMapPtr adc_ptr;
LWADC_VALUE sample;
uint_32 device, input;
_mqx_int ch_num;
if (NULL == lwadc_ptr){
return FALSE;
}
input = lwadc_ptr->input;
device = ADC_DEVICE(input);
if (lwadc_ptr->context_ptr == NULL) {
return FALSE;
}
adc_ptr = lwadc_ptr->context_ptr->adc_ptr;
ch_num = adc_ptr->HC1 & 0x1F;
if( ch_num != input )
adc_ptr->HC1 = ADC_CHANNEL(lwadc_ptr->input);
if ((adc_ptr->GC & ADC_GC_ADCO_MASK) == 0) {
/* ADC is not in continuous mode. */
adc_ptr->GC |= ADC_GC_ADCO_MASK;
}
sample = adc_ptr->R1;
*outSample = sample & ADC_CDR_CDATA_MASK;
return TRUE;
}
Note that:
Instead of replacing lwadc_vdac.c from thread/317081, what I did to make the ADC work was to comment out the next lines in _lwadc_init and just add the last line.
// enable clock for adc module
//if (_bsp_adc_io_init(init_ptr->ADC_NUMBER) != IO_OK)
//{
// return FALSE;
//}
_bsp_adc_io_init(init_ptr->ADC_NUMBER);
The problem is that the _bsp_adc_io_init is ALWAYS returning IO_ERR, so not checking the return value do the trick.
I just commenting this if you are using a MQX version closer to 4.0.
Next release 4.0.1 will be as the lwadc_vdac.c file already provided by Rene.
Dear juangutierrez,
what is the current status of the ADC fix? Is it already fixed in the BSP trunk and when can we expect the new release?
Thanks Johannes
Hi rendy
I checked the MQX4.1 and this fix was not included, actually they stick with the version in 4.0.
Any idea of why? Do you know when they plan to include this fix?
Thanks
Dear rendy and juangutierrez
please give a short update when it is to expect that the fix will be included in the trunk version of MQX RTOS!
Thanks,
Johannes
After checking the problem more in detail it seems, that only the last added input (with _lwadc_init_input()) is returned when calling _lwadc_read_raw().
When I pause the CPU and manually set the "ADCH" bits in the register ADC0_HC0 I can enable another channel, but each time calling _lwadc_read_raw() the same channel is read out, no matter what pointer is passed as "lwadc_ptr"! Please give advice!
Dear Johannes,
Before a software person starts digging deeper, may you, please, take a look at https://community.freescale.com/thread/317081? - Perhaps it will help you.
Regards, Naoum Gitnik.
Dear Naoum,
thanks for your answer, but this doesn't solve my problem, since I already applied this workaround in my BSP.
My problem is, when I use two (or more) different inputs on the same ADC (e.g. ADC0SE2, ADC0SE8) I only can read the values of the last input that has been registered with _lwadc_init_input(), when using _lwadc_read_raw().
I also tried to swap the init order of the inputs: at first ADC0SE8 and afterwards ADC0SE2 and as a result I only get the values from Input 2, even if I try reading Input 8.
Here's a code snippet how I'm using the ADC:
...
LWADC_STRUCT input2;
LWADC_STRUCT input8;
LWADC_VALUE sample2 = 0;
LWADC_VALUE sample8 = 0;
_lwadc_init_input (&input2, ADC_INPUT_ADC0_AN2);
_lwadc_init_input (&input8, ADC_INPUT_ADC0_AN8);
while (1)
{
_lwadc_read_raw (&input2, &sample2);
_lwadc_read_raw (&input8, &sample8);
printf ("val2: %d, val8: %d \n", sample2, sample8); // at this time i always get the samples from input8
_time_delay(250);
}
...
When you then swap the two lines
_lwadc_init_input (&input8, ADC_INPUT_ADC0_AN8);
_lwadc_init_input (&input2, ADC_INPUT_ADC0_AN2);
Then you will see that only the samples from input2 are output.
Looking forward to receiving your feedback!
BR,
Johannes
Hi
Inspecting the code, it seems that each time _lwadc_init_input is called the ADC_HC1 is overwritten allowing the conversion for only the last channel initialized by this fxn.
Can you try the next change at mqx\source\io\lwadc.c file, please?
boolean _lwadc_init_input(LWADC_STRUCT_PTR lwadc_ptr, uint_32 input)
{
ADC_MemMapPtr adc_ptr;
uint_32 device, channel;
. . .
/* Set channel to convert */
- adc_ptr->HC1 = channel;
+ adc_ptr->HC1 |= channel;
return TRUE;
}
I will try it tomorrow too.
Hello,
I don't have the file mqx\source\io\lwadc.c in my BSP, but what I got is mqx/source/io/lwadc/lwadc_vadc.c (File-Version: 3.8.1.0, Oct-3-2012 with applied patch for ADC0/1) so I modified this one!
But the modification does not bring the benefit. It makes it even worse, because the function _lwadc_wait_next() does not return. So I tried it without wait_next, i.e. directly call _lwadc_read_raw() in a loop, but it only reads zeros. Please let me know how your tests are going?
Thanks,
Johannes
Dear rendy,
May you look into this thread, please? - It looks like you already developed expertise with Vybrid ADC while dealing with the ADC previous issue.
Thanks in advance, Naoum Gitnik.