こんにちは、
私はM33コアのi.MX8ULP ADCをコンパレータモードで使おうとしています。具体的には、変換値が閾値を下回った場合にイベントを処理する割り込みを出すようにADCを設定したいです。
参考マニュアルによると、これは可能なはずです:
- ADCをFIFOウォーターマーク1に設定し、データがあれば割り込みをトリガーする(この部分は機能します。下の例では割り込みコードを削除してコードをシンプルにしています)
- 比較関数を「真になるまで比較を繰り返す」で設定し、CVH/CVLを適切に設定すると、トリガーはADCを継続的にサンプリングし、適切な値になったらデータを上昇させます。
残念ながら、比較値を全く機能させることができませんでした。マニュアルには、CVL/CVHに応じてさまざまな操作が可能であると記載されていますが、ADC1 / コマンド 1 / トリガー 1 を使用しても、どれも機能しませんでした。
実験的に、私は以下のことを確認しました。
- CVL < CVH (マニュアルでは範囲外の場合に真と記載されています。例:val < CVL || val > CVH): 値が常に返されます(範囲内であっても)。
- CVH max、CVL 設定(CVL 未満であるべき):最大値は指定されていないため確信が持てませんでした。CVH を0xfffに設定するか、0x1000 値は CVL に関係なく必ず返されます。CVH を 0xffff に設定すると値が返りません
- CVL が最小値、CVH が設定されています (CVH より大きい必要があります): 値は常に返されます
- CVL > CVH (範囲内である必要があります。例:CVH < val < CVL): 値は返されません
私が使用したコードは以下のとおりです。
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);
}レジスタもダンプしましたが、「trueまで繰り返し比較する」部分は、STATレジスタがトリガー/コマンドをまだ実行中とみなしているので機能すると確信しています。「Store on true」設定でも同じ結果が得られました(コマンドを実行しながらCVをいじって値と比較すると変な結果が出ますが、条件がtrueになるのを待っていたトリガーは正しく返されます。実行中にCVを変更するべきではないはずなので、この部分は無視しましょう)
変換待ち中のレジスタはこちらで、CVL = 0xffe、CVH = 0x1(したがって、その間の値が返されるはずです):
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持ち方が間違っているのでしょうか?
ありがとうございます
ドミニク