i need to enable 12 DMA transferts from each ADC buffers (12) to internal RAM.
The ADC triggers DMA when conversion of the analog input pin (12th ADC channel) specified by the ADA0S register is completed.
The DMA generates an interrupt when transfers are completed.
The ADC is set in continuos scan mode over all adc channel (12th).
The DMA is set to perform 12 transferts (DBCn = 11).
The problem is that ADC performs the scan of all channels at XX Hz... but the DMA generates an interrupt at (XX/12) Hz!!! It's normally?
I need that for each ADC complete scan of 12 channels the DMA performs the transfer of all ADC conversion result registers (ADA0CRn) to RAM.
Can someone help me?
/** Configure ADC.
* Performs ADC setup setting it in Continuous Scan Mode. It sets the High
* Speed Conversione Mode (3,25us) and selects to scan all channels.
* Finally starts the ADC.
// clears ADC ADA0M0 register
ADA0M0 = 0;
// continuous scan mode
ADA0M0 = ADA0M0 | 0x10;
// clears ADC ADA0M1 register
ADA0M1 = 0;
// high speed conversion mode
ADA0M1 = ADA0M1 | 0x80;
// 3.25us conversion time
ADA0M1 = ADA0M1 | 0x03;
// clears ADC ADA0S register
ADA0S = 0;
// selects to scan all channels
ADA0S = 0x0B;
// clears trigger sources
ADA0M2 = 0;
// enbles ADC interrupt
ADIC = 0x04;
// starts ADC conversion
ADA0M0 = ADA0M0 | 0x80;
/** Configure DMA.
* Sets DMA channel 0 with ADC output registers as source address and
* ADCDMABuff as destination address. Sets number of transmit to 12 and
* selects 16bit as transfer unit. DMA trigger is connected to INTAD signal,
* which is generated at the end of each ADC scan. In the end enables
* interrupts and DMA.
UINT32 addr ;
// disables DMA
E00 = 0 ;
// disables DMA interrupt
DMAMK0 = 1U ;
// clears interruot flag
DMAIF0 = 0U ;
// enables DMA channel 0 programming
INIT0 = 1 ;
// sets DMA channel 0 destination address
addr = (UINT32) &ADCDMABuff ;
DDA0H = (UINT16)(addr>>16) & 0x03FF | 0x8000;
DDA0L = (UINT16)(addr & 0x0000FFFF);
//DDA0H = DDA0H & 0x03FF;
//DDA0H = DDA0H | 0x8000;
// sets DMA channel 0 source address to ADC output registers
DSA0H = 0x03FF;//0xFF;
DSA0L = 0xF210;
//DSA0H = DSA0H & 0x03FF;
// sets tranfers number
DBC0 = 11;
// sets 16 bit transfer unit
DADC0 = 0x4000;
// sets DMA trigger source to ADC INTAD signal
DTFR0 = 0x2C;
// clears DCHC0 register
DCHC0 = 0x00;
// clears interrupt flag
DMAIF0 = 0 ;
// enables interrupt
DMAMK0 = 0 ;
// enables DMA
E00 = 1U ;
// enables DMA interrupt
//DMAIC0 = 0x00; // probably not needed
//DMAIC0 = DMAIC0 | 0x04; // probably not needed
#pragma vector=INTDMA0_vector //0x00000380
__interrupt void dmaISR(void)
I don't know V850 in detail, but I would expect that each DMA trigger transfers 1 byte or 1 word (or whatever the data size is), and NOT 12 values. To transfer 12 values you would need 12 DMA triggers.
Ok, but if i need a continuos scan of 12 ADC channels and i need to transfer all ADC conversion result registers to ram using DMA without using CPU.... how can I do?
....I can do?
From reading this device user manual, unfortunately it does not appear that you will be able to use a single DMA operation to transfer all A/D conversion result data to RAM. For this mcu, you only get one interrupt at the end of the conversion scan, which is the only trigger signal sent to the DMA. The DMA requires a trigger for every transfer, as FrankL mentioned, so you would need 12 triggers/interrupts from the ADC to get all of the results transfered (this is why you see the noted behavior that after 12 conversion scans of the ADC, you get the DMA completion interrupt).
The solution should be to write a simple interrupt handler for the A/D conversion end interrupt, and transfer the data using the CPU. I believe the CPU time will be quite small.
If possible, you could use a software trigger. Start your DMA transfer from the interrupt routine of your ADC, it should than transfer amount of data defined in the DBCn register. You have to write a short interrupt routine in this case. It is not a pure hardware solution, but could help.