I am trying to do some extra credit in my SerialLoader and have a test routine that reads ADC inputs, but I'm not having much luck.
I see various other posts about the ADC, I have checked ADC_Timers.h for example config as well as the pdf on ADC usage, but I still get no reading.
I have two inputs on the i.MX RT (1062), GPIO_AD_B1_04 and GPIO_AD_B1_05. which have the analog voltage coming in. Using the NXP MCUXpresso SDK, I am able to set up ADC_ETC and the ADC channels 1 and 2 with chaining to successfully read both inputs after a chained conversion is triggered by a PIT.
Using uTasker, I don't really have a clue where to start...
I don't know how to understand the mapping of the actual pins applies to the ADC_SETUP. I assume that the int_adc_bit should define this using one of the ADC_SE defines in iMX.h:
#define ADC_SE0_SINGLE 0
#define ADC_SE1_SINGLE 1
#define ADC_SE2_SINGLE 2
#define ADC_SE3_SINGLE 3
#define ADC_SE4_SINGLE 4
#define ADC_SE5_SINGLE 5
#define ADC_SE6_SINGLE 6
#define ADC_SE7_SINGLE 7
#define ADC_SE8_SINGLE 8
#define ADC_SE9_SINGLE 9
#define ADC_SE10_SINGLE 10
#define ADC_SE11_SINGLE 11
#define ADC_SE12_SINGLE 12
#define ADC_SE13_SINGLE 13
#define ADC_SE14_SINGLE 14
#define ADC_SE15_SINGLE 15
#define ADC_ETC_SINGLE 16
But it also mentions these should map to inputs 0...31 (?). and I see ADC_ETC as well, but I don't see how to set that up.
I also see some of the examples seem to set the int_handler multiple times before setting the actual interrupt, wouldn't this just overwrite the previous value and have no effect?
For example in the ADC pdf it has:
ADC_SETUP adc_setup; // interrupt configuration parameters
adc_setup.int_type = ADC_INTERRUPT; // identifier when configuring
adc_setup.pga_gain = PGA_GAIN_OFF; // PGA gain can be specified for certain inputs
adc_setup.int_handler = fnRangeInterrupt; // handling function
adc_setup.int_priority = PRIORITY_ADC; // ADC interrupt priority
adc_setup.int_adc_controller = 1; // ADC controller 1
adc_setup.int_adc_offset = 0; // no offset
adc_setup.int_adc_mode = (ADC_CALIBRATE | ADC_SELECT_INPUTS_A | 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 | ADC_SINGLE_SHOT_MODE | ADC_12_BIT_MODE |
ADC_SW_TRIGGERED); // 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
adc_setup.int_adc_result = 0; // no result is requested
adc_setup.int_adc_bit = ADC_DM1_SINGLE; // ADC DM1 single-ended
adc_setup.int_adc_bit_b = ADC_DISABLED; // channel B only valid in HW triggered mode
adc_setup.int_adc_int_type = (ADC_LOW_LIMIT_INT);
// interrupt type (trigger only when lower than the defined level)
adc_setup.int_low_level_trigger = (unsigned short)(ADC_VOLT * 1.3);
// the low level trigger threshold represented as input voltage
adc_setup.int_handler = adc_ready_1; // handling function
Which sets the int_handler twice, once to fnRangeInterrupt and then to adc_ready_1 at the end. How is this supposed to work?
Here is the code I have been trying to get working as a test on the iMX:
ADC_RESULTS samples;
void fnADCresult()
{
// get the sample
fnDebugMsg("ADC SAMPLE: ");
fnDebugHex((unsigned short) samples.sADC_value[0], (sizeof(unsigned short) | WITH_LEADIN | WITH_CR_LF));
// set up for the next sample (after we get this working once)
}
void fnInitializePots(void)
{
fnDebugMsg("INIT ADC\r\n");
// set the ADC input pins?
_CONFIG_PORT_INPUT(6, PIN_GPIO_AD_B1_04_GPIO6_IO20, (0));
_CONFIG_PORT_INPUT(6, PIN_GPIO_AD_B1_05_GPIO6_IO21, (0));
// now we need to set up the ADC to read the pot values
ADC_SETUP adc_setup; // interrupt configuration parameters
adc_setup.int_type = ADC_INTERRUPT; // identifier when configuring
adc_setup.pga_gain = PGA_GAIN_OFF; // PGA gain can be specified for certain inputs
adc_setup.int_priority = PRIORITY_ADC; // ADC interrupt priority
adc_setup.int_adc_controller = iMX_ADC_1; // first i.MX RT ADC
adc_setup.int_handler = 0; // handling function, removed for now
adc_setup.int_adc_bit = ADC_SE10_SINGLE; // which pin is this?
adc_setup.int_adc_offset = 0; // no offset
adc_setup.int_adc_mode = (ADC_CALIBRATE | ADC_SELECT_INPUTS_A | 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 {12}
adc_setup.int_adc_sample = (ADC_SAMPLE_LONG_PLUS_12 | ADC_SAMPLE_AVERAGING_32);
// additional sampling clocks
adc_setup.int_adc_result = &samples;
adc_setup.int_adc_bit_b = ADC_DISABLED; // channel B only valid in HW triggered mode
adc_setup.int_adc_int_type = (ADC_END_OF_SCAN_INT);
fnConfigureInterrupt((void *)&adc_setup); // configure and start next sequence
fnADCresult();
}
This results in a value of 0x0000. from the result (which isn't correct).
After/if I get this working, I definitely wouldn't know how to get chaining to work for using both inputs at the same time!
Thanks