Hello!,
I´m trying to develop a double circular buffer using DMA to get frames of an extabilished size from ADC converted data.
To reach this goal I wrote this code using a String to ceck how works this main file. I discovered that It works in the right way only one time, and once both buffers are full it stops to write them.
-Is there any way to force the initial address once the last buffer is full?
- How is possible to reduce ISR time?
#include "msp430x54xA.h" #include "stdint.h" #define Num_Samples 20 volatile uint8_t buffer0[Num_Samples]; volatile uint8_t buffer1[Num_Samples]; static char Switch=1; //index for Switch/double buffer static char string1[] = { "Hello World this is an array written to test the duoble circular buffer" }; int volatile audioread; void Port_init() { P10OUT &= ~BIT7; // P10.7 clear P10DIR |= BIT7; // P10.7 output P4DIR |= BIT1; // P4.1 output P4SEL |= BIT1; // P4.1 select P6SEL = P6SEL | 0x80; //P6.7 --> ADC function P6DIR = P6DIR & 0x7F; } void TimerB_init() { //Setup Timer B0 /* Configure TimerB to produce the triggers for the ADC */ TBR = 0; TBCTL = TBSSEL_1 | MC_1 | TBCLR; // Use ACLK, count up, reset counter and direction TBCCR0 = 4096; // Init TBCCR0 w/ sample period TBCCR1 = 4036; // Trigger for ADC12 Sample Conversion TBCCTL1 = OUTMOD_7; // Reset OUT1 on EQU1, set on EQU0 } void ADC_init() { // Setup ADC12 ADC12CTL0 &= ~ADC12ENC; ADC12CTL0 = ADC12ON + //Turn on ADC12 ADC12SHT0_1+// 32 cycles per sample (Sampling time) ADC12MSC + //multiple sample ADC12REFON; //enable int ref ADC12CTL1 = ADC12SHP + //pulse mode ADC12CONSEQ_0 +//single channel single conversion ADC12SSEL_3 + //clock source SMCLK ADC12CSTARTADD_0;//select first (in order) register (7) ADC12CTL2 = ADC12RES_0 + ADC12REFBURST; // 8bit res, 9 clock cycles to convert,Reference buffer on only during sample-and-conversion ADC12CTL2 &= ~(ADC12DF); //ADC12DF=0 --> unsigned format ADC12MCTL0 = ADC12SREF_7 + ADC12EOS + ADC12INCH_7; //End of Sequence --> Bit7 = 1; ADC12SREF = 0b111; ADC12INCH = 0b0111; __delay_cycles(75); // 35us delay to allow Ref to settle // based on default DCO frequency. // See Datasheet for typical settle // time. ADC12CTL0 |= ADC12ENC; // Enable conversions ADC12CTL0 |= ADC12SC; // Start conversion audioread=ADC12MEM0; // Setup DMA0 double buffer DMACTL0 = DMA0TSEL_6; // ADC12IFGx triggered // DMA0SA = (__SFR_FARPTR)(unsigned int)&ADC12MEM0; DMA0SA =(__SFR_FARPTR)(unsigned int)&string1; // Source block address //DMA0SZ = sizeof Num_Samples; // Block size DMA0SZ = sizeof string1-1; // Block size DMA0CTL = DMADT_4 +//Rpt single block DMASRCINCR_3 +//Source address increment DMADSTINCR_3 + //Destination address increment //DMASRCBYTE + DMALEVEL + DMASBDB; //Transfer byte to byte __bis_SR_register(LPM0_bits + GIE); // LPM0 w/ interrupts __no_operation(); // used for debugging } void main(void) { WDTCTL = WDTPW+WDTHOLD; // Hold WDT Port_init(); TimerB_init(); ADC_init(); //store audio on Ram DMA0CTL |= DMAIE;//Interrupt enable __bis_SR_register(LPM0_bits + GIE); __no_operation(); // used for debugging } //------------------------------------------------------------------------------ // DMA Interrupt Service Routine \\2 CLOCK MCLK PER TRANSFER after synchronization and 1 of wait //------------------------------------------------------------------------------ #pragma vector = ADC12_VECTOR __interrupt void ADC12_ISR(void) { //Depending on Index Change destination address of DMAs if(Switch==1) { DMA0DA = (__SFR_FARPTR)(unsigned int)&buffer0[0]; DMA0CTL |= DMAEN; // Enable DMA0CTL |= DMAREQ; // Trigger block transfer //DMA1DA = (__SFR_FARPTR)(unsigned long)&dataBuff2.bufferA5[0]; } else { DMA0DA = (__SFR_FARPTR)(unsigned int)&buffer1[0]; DMA0CTL |= DMAEN; // Enable DMA0CTL |= DMAREQ; // Trigger block transfer //DMA1DA = (__SFR_FARPTR)(unsigned long)&dataBuff1.bufferA5[0]; } //Clear IFGs __bic_SR_register_on_exit(LPM0_bits); } #pragma vector = DMA_VECTOR __interrupt void DMA_ISR(void) { Switch^=1; __bic_SR_register_on_exit(LPM0_bits); }
Thank you!