I have ADC reading issues on the SE6b and SE7b on NXP MKL27Z64VFM4(QFN32). The other channel reading is fine after I connected PTE30 to Vcc. Does somebody know how to get hardware trigger and reading the correct ADC value?
Albert
The 32 pin package has PTE30 as primary source of reference voltage for the ADC and that is why you needed to put 3.3V on it if you use this setting.
You can however use the Valt setting instead and then the ADC takes its reference internally from VDDA. To do this, set BIT0 in ADC0_CFG2.
Since you no longer need to apply 3.3V to PTE30 you can use it as ADC0_SE32 instead.
You just need to ensure that the precision reference module is disabled (its default state), which is however also the case when using the primary reference on PTE30.
Regards
Mark
Hi Mark,
What is Valt setting?
The listed BIT0 of ADC0-CFG2 is for ADLSTS Long Sample selection. Set ADLSTS =01 =12 extra ADCK cycle…. It is strange that will set internal reference to VDDA?
Could set PTE30 to a GPIO output and the reference internal connect to VDDA?
Best regards,
Albert Zhou
Sr. Electronics Engineer
Sensorex
p:
+1 714-230-2768
a:
11751 Markon Drive, Garden Grove, CA 92841
w:
www.sensorex.com<http://www.sensorex.com/>; e: albert.zhou@sensorex.com<mailto:albert.zhou@sensorex.com>
<https://www.facebook.com/Sensorex> <https://twitter.com/SensorexInc> <https://www.linkedin.com/company-beta/1768298/>
Albert
Sorry, my mistake, the bit is in ADC0_SC2 !
Regards
Mark
Ops, Everything works OK.
Albert
Hi Mark,
Thanks a lot. Yes, I did understand that could be ADC0_SC2 this morning. Very thing now works OK.
Thanks thanks again!!
Albert Zhou
Sr. Electronics Engineer
Sensorex
p:
+1 714-230-2768
a:
11751 Markon Drive, Garden Grove, CA 92841
w:
www.sensorex.com<http://www.sensorex.com/>; e: albert.zhou@sensorex.com<mailto:albert.zhou@sensorex.com>
<https://www.facebook.com/Sensorex> <https://twitter.com/SensorexInc> <https://www.linkedin.com/company-beta/1768298/>
Hi Albert
See Appendix A. Paragraph d of http://www.utasker.com/docs/uTasker/uTaskerADC.pdf
Regards
Mark
Kinetis: http://www.utasker.com/kinetis.html
Kinetis KL25, KL26, KL27, KL28, KL82:
- http://http://www.utasker.com/kinetis/FRDM-KL25Z.html
- http://www.utasker.com/kinetis/TWR-KL25Z48M.html
- http://www.utasker.com/kinetis/FRDM-KL26Z.html
- http://www.utasker.com/kinetis/TEENSY_LC.html
- http://www.utasker.com/kinetis/FRDM-KL27Z.html
- http://www.utasker.com/kinetis/Capuccino-KL27.html
- http://www.utasker.com/kinetis/FRDM-KL28Z.html
- http://www.utasker.com/kinetis/FRDM-KL82Z.html
For less questions and faster, cheaper developments: try uTasker for Kinetis
This one does not say any thing about hardware trigger that should be very simple instead of long long code and many prototypes.....
For HW triggering just read the manual since it tells you all you need to know about sources and trigger selection::
There is an example of PIT triggering in appendix A, paragraph B and of TPM triggering in paragraph E (this allows variable A/B HW triggering).
Paragraph D explains input mixing fundamentals that are needed to be understood to correctly to use 'parallel' A/B channel triggering and a/b muxing.
If you have problems with (just) SE6b and SE7b inputs it is not a HW triggering issue but incorrect input channel muxing (again paragraph D explains this, which is why I pointed it out). These inputs don't need HW triggering - they can be read in SW mode as others that you already have working.
Notice the a/b and A/B notations used since they have DIFFERENT meanings.
Regards
Mark
Hi Mark,
I have changed code as this below, that still does not work: (hang there…)
#define Convertion_in_Progress ((ADC0->SC2)&(BIT7))
uint16_t ADC16(uint8_t channel)
{
uint16_t adcValue;
//ADC0->CFG2 &= ~BIT4;
//ADC0->SC1[0] =channel;
//while(Convertion_in_Progress!=0){};
//while(Convertion_Complete==0){};
//adcValue =ADC0->R[0];
if((channel==6)||(channel==7))
{
ADC0->CFG2 |= BIT4;
ADC0->SC1[0] =channel;
//ADC0->CFG2 |= BIT4;
while(Convertion_in_Progress!=0){}; //
while(((ADC0->SC1[0])&(BIT7))==0){};
adcValue =ADC0->R[0];
}
else
{
ADC0->CFG2 &= ~BIT4;
ADC0->SC1[0] =channel;
while(Convertion_in_Progress!=0){};
while(Convertion_Complete==0){};
adcValue =ADC0->R[0];
}
return adcValue;
}
Hi Albert
I just checked operation on SE6b on a KL27 with following code:
ADC_SETUP adc_setup; // interrupt configuration parameters
adc_setup.int_type = ADC_INTERRUPT; // identifier when configuring
adc_setup.pga_gain = PGA_GAIN_OFF;
adc_setup.int_priority = PRIORITY_ADC; // ADC interrupt priority
adc_setup.int_adc_controller = 0; // ADC controller 0
adc_setup.int_handler = adc_conversion_complete;
adc_setup.int_adc_int_type = (ADC_SINGLE_SHOT_TRIGGER_INT);
adc_setup.int_adc_bit = ADC_SE6_SINGLE;
adc_setup.int_adc_mode = (ADC_CALIBRATE | ADC_SELECT_INPUTS_B | ADC_CLOCK_BUS_DIV_2 | ADC_CLOCK_DIVIDE_8 | ADC_SAMPLE_ACTIVATE_LONG | ADC_CONFIGURE_ADC | ADC_REFERENCE_VREF | ADC_CONFIGURE_CHANNEL | ADC_SINGLE_ENDED_INPUT | ADC_SINGLE_SHOT_MODE | ADC_12_BIT_MODE | ADC_SW_TRIGGERED); // note that the first configuration should calibrate the ADC - single shot with interrupt on completion
adc_setup.int_adc_sample = (ADC_SAMPLE_LONG_PLUS_12 | ADC_SAMPLE_AVERAGING_32); // additional sampling clocks
fnConfigureInterrupt((void *)&adc_setup); // configure ADC and start first conversion
It uses an interrupt and when the conversion is complete I checked the value with a debug message to verify the operation was correct across the voltage range (12 bit mode)
ADC triggered: 0x0fff
ADC triggered: 0x0d54
ADC triggered: 0x0b30
ADC triggered: 0x0932
ADC triggered: 0x0724
ADC triggered: 0x0509
ADC triggered: 0x0307
ADC triggered: 0x0153
ADC triggered: 0x0000
So that you can check the ADC interaction, this is the low level code that this controls:
KINETIS_ADC_REGS *ptrADC = (KINETIS_ADC_REGS *)ADC0_BLOCK;
POWER_UP_ATOMIC(6, ADC0); // enable clocks to module
ptrADC->ADC_CFG1 = (ADC_CLOCK_DIVIDE_8 | ADC_SAMPLE_ACTIVATE_LONG | ADC_12_BIT_MODE | ADC_CLOCK_BUS_DIV_2); // 0x75
// Do ADC calibration sequence - not shown
ptrADC->ADC_CFG2 = (ADC_CFG2_MUXSEL_B | ADC_SAMPLE_LONG_PLUS_12); // 0x11
_CONFIG_PERIPHERAL(D, 5, PD_5_ADC0_SE6b); // ensure that the ADC pin is configured
ptrADC->ADC_SC2 = ADC_REFERENCE_VREF; // configure the reference voltage and triggering - 0x00
ptrADC->ADC_SC3 = ADC_SAMPLE_AVERAGING_32; // 0x07 - single shot conversion
// Configure interupt handler - not shown
ptrADC->ADC_SC1A = (ADC_SC1A_AIEN | ADC_SC1A_ADCH_6); // 0x46
// When interrupt fires - read result
result = ptrADC->ADC_RA;
I have shown the HEX values written to the registers and note the following:
1) You should preform ADC calibration before first use
2) Although the pin PTD5 default to its ADC0_SE6b function it is good practice to ensure that it is correct - and power up the PTD port.
3) Although I don't see all your ADC initialisation details setting BIT4 of ADC0_CFG2 is what selects the b input, so that looks correct.
4) As a test, I selected a input on SE6a - and the result was then always 0x0fff (presumably the unavailable SE6 a input is connected internally to VDD).
With these details you may be able to identify your issue.
Regards
Mark
You can also download the uTasker project from its open source reference on GitHub for check the coding details from above and simulate the KL27 in Visual Studio.
Short video attached of testing/verifying the ADC input.
Hi Mark,
Yes, it works with the code I send to you when I flashed the target board. I had a mistake at debug display line. I put
“ADC0->SC1[0] =6;” after “ADC0->SC1[0] =6;”. So the screen display is “0…..”.
I guess I did not put a line for ensure PTD5 (SE6b) to ALT0 at earlier time. I did it then send the code to you.
Thank you…. Thanks a lot for help me out for this critical issue.
Plus. I still have the question about PTE30. Please advise.
Albert Zhou
Sr. Electronics Engineer
Sensorex
p:
+1 714-230-2768
a:
11751 Markon Drive, Garden Grove, CA 92841
w:
www.sensorex.com<http://www.sensorex.com/>; e: albert.zhou@sensorex.com<mailto:albert.zhou@sensorex.com>
<https://www.facebook.com/Sensorex> <https://twitter.com/SensorexInc> <https://www.linkedin.com/company-beta/1768298/>
Hi Mark,
Thanks for your help.
I did ADC self-calibration I hare attached complete code for your check.
I read your code. It seems almost the same as I did except clock setup and 12 bit – 16 bit and interrupt. I will check it again with ADC interrupt as you did.
One more thing, about the PTE30 pin. I have to connect this pin(9 for 32QFN) to Vcc(3.3V) for accurate read, otherwise if I used as SE23 as ADC input. The ADC channel(a) could not read accurate value.
Is that right? That means I have lost another ADC channel(SE23)? Please advise.
Best regards,
Albert Zhou
Sr. Electronics Engineer
Sensorex
p:
+1 714-230-2768
a:
11751 Markon Drive, Garden Grove, CA 92841
w:
www.sensorex.com<http://www.sensorex.com/>; e: albert.zhou@sensorex.com<mailto:albert.zhou@sensorex.com>
<https://www.facebook.com/Sensorex> <https://twitter.com/SensorexInc> <https://www.linkedin.com/company-beta/1768298/>
Hi Mark,
Thank you for your point out that the SE6b and SE7b inputs do not need Hardware trigger just change input mux. That will help me a lot.
I tried this code below that does not work. Please advise.
uint16_t ADC16(uint8_t channel)
{
uint16_t adcValue;
//ADC0->SC1[0] =channel;
//while(Convertion_in_Progress!=0){};
//while(Convertion_Complete==0){};
//adcValue =ADC0->R[0];
if((channel==6)||(channel==7))
{
ADC0->CFG2 |= BIT4;
ADC0->SC1[1] =channel;
while(Convertion_in_Progress!=0){};
while(((ADC0->SC1[1])&(BIT7))==0){};
adcValue =ADC0->R[1];
}
else
{
ADC0->CFG2 &= ~BIT4;
ADC0->SC1[0] =channel;
while(Convertion_in_Progress!=0){};
while(Convertion_Complete==0){};
adcValue =ADC0->R[0];
}
return adcValue;
}
Best regards,