I am now writing code using timer1 tirgger 4 channel of ADC and read it out via DMA. First i write a standalnoe project to test it. Everything goes on well. But when i combine it with bluetooth project. The result in the DMA sequence gets disorder(meaning the result array can start from any channel). I can see in the result array(from the result shown at bluetooth central), the fisrt element can be result from every channel which is supposed to be only channel 0. I think the reason is beceause i am checking the dma flag every 1ms, and stops the timer1 if there is flag. In the interval between DMA is ready and the ready is recognized, timer1 closed(stops ADC). There are still ADC events carrying on.This is my code:
static char resultbuf[41]={255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
static char resultbuf1[41]={255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
static uint8 toggle = 0;
static halDMADesc_t *dma_channel;
void SimpleBLEPeripheral_Init( uint8 task_id )
{
simpleBLEPeripheral_TaskID = task_id;
//init ADC p0.0 p0.1 p0.4 p0.5
APCFG |=0x33;
P0DIR &=~ 0x33;
ADCCON1 = 0x23;// timer1 channel 0 will trigger the ADC
//ADCCON1 = 0x33;// timer1 channel 0 will trigger the ADC
ADCCON2 = 0xB5;
//ADCCON3 = 0xB1;
PERCFG |= 0x40; // Select Timer 1 Alternative 1 location
P2SEL = (P2SEL & ~0x10); // Give priority to Timer 1
P1DIR |= 0x04; // Set P1.2 to output
P1SEL |= 0x04; // Set P1.2 to peripheral
T1CC0L = 0x06; // PWM signal period
T1CC0H = 0x01;
T1CCTL0 = (T1CCTL0 & ~0x63) | 0x14; // PWM output 0x23
T1CTL |= 0x0E; // divide with 128 and to do Modulo Mode ************************TIMER1 WORKING PWM ON P1.2
dma_channel = HAL_DMA_GET_CH3_ADDR();
// //dma_channel = HAL_DMA_GET_DESC0();
//
////
//// // rearm is needed when 40 byte is read out.
//// // also clear interrupt
//// // Setup DMA configuration.
//// //source address
dma_channel->srcAddrH = (uint8)((uint16)(&X_ADCH) >> 8); //X_ADCH
dma_channel->srcAddrL = (uint8)((uint16)(&X_ADCH));// & 0xFF); //X_ADCL
//destination adress
dma_channel->dstAddrH = (uint8)(((uint16)&resultbuf[1]) >> 8);
dma_channel->dstAddrL = (uint8)(((uint16)&resultbuf[1]) & 0xFF);
// // 000 use len for transfer countr
// // 00000
dma_channel->xferLenV = 0x00;
// //lenl is the length of transfer byte
dma_channel->xferLenL = 40; // Tranfer Count 4 byte
// // wordsize 8bit 0 00 repeated single, every trigger read out 1, and awaits the next trigger. until 24 times.
// // 20 10100 means ADC_ALL_READY
dma_channel->ctrlA = 0x14;
// //source no increment , dest increment, disable transfer(single) interrupt , high proi
dma_channel->ctrlB = 0x16;
// //DMAARM |=0x08;
DMAARM |=0x08;
....
....
....
}
every 1ms:
static void performPeriodicTask( void )
{
// 10ms ADC data
if(DMAIRQ&0x09)
{
DMAIRQ &=~ 0x08;
T1CTL &= ~0x02; // Stop timer
if(toggle == 0)
{
dma_channel->dstAddrH = (uint8)(((uint16)&resultbuf1[1]) >> 8);
dma_channel->dstAddrL = (uint8)(((uint16)&resultbuf1[1]) & 0xFF);
DMAARM |=0x08; // rearm dma
T1CNTL = 0x00; // Reset counter value
T1CTL |= 0x02; // Start timer
emgProfile_SetParameter( EMGPROFILE_DATA,EMGPROFILE_DATA_LEN, resultbuf );
emgProfile_SetParameter( EMGPROFILE_DATA,EMGPROFILE_DATA_LEN, &resultbuf[20] );
toggle = 1;
}
else
{
dma_channel->dstAddrH = (uint8)(((uint16)&resultbuf[1]) >> 8);
dma_channel->dstAddrL = (uint8)(((uint16)&resultbuf[1]) & 0xFF);
DMAARM |=0x08; // rearm dma
T1CNTL = 0x00; // Reset counter value
T1CTL |= 0x02; // Start timer
emgProfile_SetParameter( EMGPROFILE_DATA,EMGPROFILE_DATA_LEN, resultbuf1 );
emgProfile_SetParameter( EMGPROFILE_DATA,EMGPROFILE_DATA_LEN, &resultbuf1[20] );
toggle = 0;
}
}
}
I think up of 2 ways, 1 is calculate the interrupt of dma, if it's 40, then stops the timer1,but it takes CUP time and ADC is still working when interrupt is there. 2 one is restart ADC, but i don't know how to do that. Is there any solutions?