Due to the U.S. Thanksgiving holiday, please expect delayed responses during the week of 11/22.

This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430:F5528 ADCのDMA転送中、ADC割り込み使用時DMA転送されない

Other Parts Discussed in Thread: MSP430F5528

MSP430F5528マイコンで、ADC12_AをTIMER_A0(256Hzインターバル)の出力で変換タイミングをコントロールし、DMA Ch0でADC12_A_MEMORY_1(A0ポートに設定)のA/D値を1365サンプル転送し、DMA Ch0が1365サンプル転送完了後にDMA Ch0割込みで次の1365サンプルをDMA転送するようにしています。

この時、1分毎にA1ポートを8回、上記の256HzでA0ポートと一緒にA/D変換したいため、A1ポートをADC12_A_MEMORY_0に設定し、A0ポートの変換完了直後にADC12_Aの設定を変更して、繰り返し連続チャネルモードでADC12_A_MEMORY_0, ADC12_A_MEMORY_1をA/D変換し、ADC12_A_MEMORY_1はDMA Ch0でデータ転送、ADC12_A_MEMORY_0はADC12IFG0割込みでデータ取得しようとしています。8回ADC12_A_MEMORY_0を取得後は、ADC12_A_MEMORY_0の変換を止めADC12の割り込みも無効にしています。

この時、ADC12割込みでADC12_A_MEMORY_0を取るようにしている最中、DMA Ch0によってデータ転送がされていませんでした。8回ADC12_A_MEMORY_0を取得後のADC12_A_MEMORY_0の変換とADC12の割り込み無効後は再びDMA Ch0によってデータ転送がされています。

ADC12割込みを使用している最中も、DMA転送が止まらずに動く方法はありませんでしょうか?

以下、設定部分と、ADC12割込み部分のソースコードです。

---ADC12_A設定---

ADC12_A_configureMemoryParam param0 = {0};
ADC12_A_configureMemoryParam param1 = {0};

ADC12_A_init(ADC12_A_BASE,
ADC12_A_SAMPLEHOLDSOURCE_1,
ADC12_A_CLOCKSOURCE_ADC12OSC,
ADC12_A_CLOCKDIVIDER_1);

ADC12_A_enable(ADC12_A_BASE);

ADC12_A_setupSamplingTimer(ADC12_A_BASE,
ADC12_A_CYCLEHOLD_32_CYCLES,
ADC12_A_CYCLEHOLD_4_CYCLES,
ADC12_A_MULTIPLESAMPLESDISABLE);

param0.memoryBufferControlIndex = ADC12_A_MEMORY_0;
param0.inputSourceSelect = ADC12_A_INPUT_A1;
param0.positiveRefVoltageSourceSelect = ADC12_A_VREFPOS_EXT;
param0.negativeRefVoltageSourceSelect = ADC12_A_VREFNEG_EXT;
param0.endOfSequence = ADC12_A_NOTENDOFSEQUENCE;
ADC12_A_configureMemory(ADC12_A_BASE,&param0);

param1.memoryBufferControlIndex = ADC12_A_MEMORY_1;
param1.inputSourceSelect = ADC12_A_INPUT_A0;
param1.positiveRefVoltageSourceSelect = ADC12_A_VREFPOS_EXT;
param1.negativeRefVoltageSourceSelect = ADC12_A_VREFNEG_EXT;
param1.endOfSequence = ADC12_A_ENDOFSEQUENCE;
ADC12_A_configureMemory(ADC12_A_BASE,&param1);

--TIMER_A0設定---

Timer_A_initCompareModeParam initCompParam = {0};
Timer_A_initUpModeParam initUpParam = {0};

initCompParam.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1;
initCompParam.compareInterruptEnable =
TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE;
initCompParam.compareOutputMode = TIMER_A_OUTPUTMODE_RESET_SET;
initCompParam.compareValue = 1;
Timer_A_initCompareMode(TIMER_A0_BASE, &initCompParam);

initUpParam.clockSource = TIMER_A_CLOCKSOURCE_ACLK;
initUpParam.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_1;
initUpParam.timerPeriod = 255;
initUpParam.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;
initUpParam.captureCompareInterruptEnable_CCR0_CCIE =
TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE;
initUpParam.timerClear = TIMER_A_DO_CLEAR;
initUpParam.startTimer = false;
Timer_A_initUpMode(TIMER_A0_BASE, &initUpParam);

--DMA Ch0設定---

DMA_initParam initParam0 = {0};

DMA_enableTransferDuringReadModifyWrite();

initParam0.channelSelect = DMA_CHANNEL_0;
initParam0.transferModeSelect = DMA_TRANSFER_SINGLE;
initParam0.transferSize = 0;
initParam0.triggerSourceSelect = DMA_TRIGGERSOURCE_24;
initParam0.transferUnitSelect = DMA_SIZE_SRCWORD_DSTWORD;
initParam0.triggerTypeSelect = DMA_TRIGGER_RISINGEDGE;
DMA_init(&initParam0);

DMA_setSrcAddress(DMA_CHANNEL_0,
ADC12_A_getMemoryAddressForDMA(ADC12_A_BASE,
ADC12_A_MEMORY_1),
DMA_DIRECTION_UNCHANGED);

DMA_setDstAddress(DMA_CHANNEL_0,
(uint32_t)&gaus_Buffer[0],
DMA_DIRECTION_INCREMENT);

DMA_clearInterrupt(DMA_CHANNEL_0);
DMA_enableInterrupt(DMA_CHANNEL_0);

---A/Dスタート---

DMA_disableTransfers(DMA_CHANNEL_0);

DMA_setDstAddress(DMA_CHANNEL_0,
(uint32_t)&gaus_ECG_Buffer[0],
DMA_DIRECTION_INCREMENT);
DMA_setTransferSize(DMA_CHANNEL_0,
1365);

DMA_clearInterrupt(DMA_CHANNEL_0);
DMA_enableTransfers(DMA_CHANNEL_0);

ADC12MCTL0 &= ~((uint8_t)ADC12EOS);
ADC12MCTL1 |= (uint8_t)ADC12EOS;

ADC12_A_startConversion(ADC12_A_BASE,
ADC12_A_MEMORY_1,
ADC12_A_REPEATED_SEQOFCHANNELS);

ADC12_A_disableInterrupt(ADC12_A_BASE, ADC12IE0);
ADC12_A_clearInterrupt(ADC12_A_BASE, ADC12IFG0);

Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_UP_MODE);

---!1分毎 A1ポート変換設定変更---

while(ADC12_A_BUSY != ADC12_A_isBusy(ADC12_A_BASE));   //BUSY待ち

HWREG8(ADC12_A_BASE + OFS_ADC12CTL0_L) &= ~(ADC12ENC);

//ENCビット0後、シーケンス変換終わってNOT BUSYになったらADC設定変更処理開始
while(ADC12_A_NOTBUSY != ADC12_A_isBusy(ADC12_A_BASE)); //NOT BUSY待ち

ADC12MCTL0 &= ~((uint8_t)ADC12EOS);
ADC12MCTL1 |= (uint8_t)ADC12EOS;

ADC12_A_clearInterrupt(ADC12_A_BASE, ADC12IFG0);
ADC12_A_enableInterrupt(ADC12_A_BASE, ADC12IE0);

ADC12_A_startConversion(ADC12_A_BASE,
ADC12_A_MEMORY_0,
ADC12_A_REPEATED_SEQOFCHANNELS);

--- ADC12割込みでMEM0(A1ポート)取得---

#pragma vector=ADC12_VECTOR
__interrupt
void ADC12_A_ISR(void)
{
switch(__even_in_range(ADC12IV,34))
{
case 0: break; //Vector 0: No interrupt
case 2: break; //Vector 2: ADC overflow
case 4: break; //Vector 4: ADC timing overflow
case 6: //Vector 6: ADC12IFG0

GPIO_setOutputHighOnPin(GPIO_PORT_P1, GPIO_PIN6);

agus_AD_Value_array[0] =
ADC12_A_getResults(ADC12_A_BASE, ADC12_A_MEMORY_0);


__bic_SR_register_on_exit(LPM3_bits); // Exit LPM0-3
break;
case 8: break;//Vector 8: ADC12IFG1
case 10: break; //Vector 10: ADC12IFG2
case 12: break; //Vector 12: ADC12IFG3
case 14: break; //Vector 14: ADC12IFG4
case 16: break; //Vector 16: ADC12IFG5
case 18: break; //Vector 18: ADC12IFG6
case 20: break; //Vector 20: ADC12IFG7
case 22: break; //Vector 22: ADC12IFG8
case 24: break; //Vector 24: ADC12IFG9
case 26: break; //Vector 26: ADC12IFG10
case 28: break; //Vector 28: ADC12IFG11
case 30: break; //Vector 30: ADC12IFG12
case 32: break; //Vector 32: ADC12IFG13
case 34: break; //Vector 34: ADC12IFG14
default: break;
}
}

  • F552xには、制御手順によってはDMA停止するerrataが有ります。 これが影響している可能性が有ります。
    ADCを使わない方法に切り替えて試していただけますか。

    RTCを使ったプログラムの制御の仕方は、個別の問題になりますので、
    お手数ですが、CSC(旧PIC)へお問い合わせのほどお願いいたします。
  • 回答ありがとうございます。
    ADC計測は必須のため、2チャンネルを計測するときだけDMAを停止し、
    割込みで規定回数2チャンネル計測したあと、DMA転送で1チャンネル計測するよう試してみます。