i.MX8ULP LPADC compare function Hello, I'm trying to use the i.MX8ULP ADC in comparator mode from the M33 core, specifically, setup the ADC such that if the conversion value falls below a threshold I get an interrupt to process the event. My understanding from the reference manual is that this should be possible: - setup the ADC with a fifo watermark of 1, so any data triggers the interrupt (this part works, in the example below I removed the interrupt code to make the code simpler) - setup the compare function with "Repeat compare until true", CVH/CVL appropriately and trigger will then sample the ADC continuously and raise the data once it is appropriate Unfortunately I've not been able to make the compare values work at all, the manual states that various operations are possible depending on CVL/CVH but none of them seemed to work for me using ADC1 / command 1 / trigger 1: Experimentally, I've seen: - CVL < CVH (manual says true if outside range e.g. val < CVL || val > CVH): value always returned (even if it falls within range) - CVH max, CVL set (should be less than CVL): maximum value is not specified so I wasn't sure, setting CVH to 0xfff or 0x1000 the value is always returned regardless of CVL, setting CVH to 0xffff the value is never returned - CVL min, CVH set (should be greater than CVH): value is always returned - CVL > CVH (should be inside range e.g. CVH < val < CVL): value is never returned Here's the code I used: lpadc_config_t adcConfig;
LPADC_GetDefaultConfig(&adcConfig);
adcConfig.FIFOWatermark = 0;
adcConfig.enableAnalogPreliminary = true;
LPADC_Init(ADC1, &adcConfig);
lpadc_conv_trigger_config_t triggerConfig;
LPADC_GetDefaultConvTriggerConfig(&triggerConfig);
triggerConfig.targetCommandId = 1;
triggerConfig.enableHardwareTrigger = true;
LPADC_SetConvTriggerConfig(ADC1, 0, &triggerConfig);
lpadc_conv_command_config_t commandConfig;
LPADC_GetDefaultConvCommandConfig(&commandConfig);
commandConfig.channelNumber = 5;
commandConfig.sampleChannelMode = kLPADC_SampleChannelSingleEndSideB;
commandConfig.sampleScaleMode = kLPADC_SampleFullScale;
commandConfig.hardwareAverageMode = kLPADC_HardwareAverageCount2;
commandConfig.hardwareCompareMode = kLPADC_HardwareCompareRepeatUntilTrue;
commandConfig.hardwareCompareValueHigh = v_high;
commandConfig.hardwareCompareValueLow = v_low;
LPADC_SetConvCommandConfig(ADC1, 1, &commandConfig);
SDK_DelayAtLeastUs(1000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
LPADC_DoSoftwareTrigger(ADC1, 1 << 0);
// this is LPADC_GetConvResultBlocking() with a timeout
uint32_t tmp, cnt = 0;
tmp = ((ADC_Type *)ADC1)->RESFIFO;
while (ADC_RESFIFO_VALID_MASK != (tmp & ADC_RESFIFO_VALID_MASK) && cnt < 100000)
{
tmp = ((ADC_Type *)ADC1)->RESFIFO;
cnt++;
}
if (ADC_RESFIFO_VALID_MASK != (tmp & ADC_RESFIFO_VALID_MASK))
{
PRINTF("ADC timeout\r\n");
}
else
{
tmp &= ADC_RESFIFO_D_MASK;
tmp >>= 3;
PRINTF("got %d (%#x) in %d\r\n", tmp, tmp, cnt);
} I've also dumped registers, I'm confident the "compare repeat until true" part works because the STAT register considers the trigger/command to still be running, and I got identical results with "Store on true" setting (And fiddling with CV (compare value) while the command is running gets weird results, but properly returns the triggers that were waiting for condition to be true - I'm sure we're not supposed to change CV while running so let's ignore this bit) Here's registers while waiting for conversion, with CVL = 0xffe and CVH = 0x1 (so should return any value between the two): ADC1 0x280a2000
VERID: 0x200101a
PARAM: 0xf041004
CTRL: 0x1
^ ADCEN
STAT: 0x1000800
^ CMDACT 1, ADC_ACTIVE
IE: 0
DE: 0
CFG: 0x10800000
^ PWREN, PUDLY = 0x80
PAUSE: 0
TSTAT: 0
TCTRL[0]: 0x1000001
^ TCMD = CMD1, HTEN (no difference when disabled)
FCTRL: 0
CMD[0].CMDL: 0x2025
^ CSCALE full-scale, ABSEL = B, CH5
CMD[0].CMDH: 0x1003
^ AVGS = 2 conversions, CMPEN = repeat until true
CV[0]: 0x10ffe
^ compare value, CVH=1 and CVL=0xffe Am I holding this wrong? Thanks, Dominique
查看全文