Hey guys,
I am trying to use a DMA and Pointers to help me send A/D values through serial. Right now, I can only get the code to display the values coming in from ADC12MEM0
on my terminal program. The other values being dumped into my RAM are not being transmitted to the terminal. Therefore, I am trying to set up a pointer that will keep track of
where I am in RAM and send every conversion to the terminal. Here is my code, I tried using the comments to explain what I was thinking
# include <msp430xG46x.h>int ADCSample;int *Pointer1;int ADCSample2;void main(void){WDTCTL = WDTPW+WDTHOLD; // Stop watchdogP5DIR |= 0x02;P5OUT |= 0x02;// Initialization of ADC12//P6SEL |= 0x01; // Enable A/D channel A0ADC12CTL0 &= ~ENC; // Disable ConversionsADC12CTL0 = ADC12ON + SHS_1 + REFON + REF2_5V + MSC; // turn on ADC12, set samp timeADC12CTL1 = SHP+CONSEQ_2; // Use sampling timerADC12MCTL0 = SREF_1+INCH_0; // Vr+=VeREF+ (external)//ADC12IFG = 0;//Timer ATACCR0 = 1500; // Delay to allow Ref to settleTACCR1 = 1470;//TACCTL0 |= CCIE; // Compare-mode interrupt.TACCTL1 = OUTMOD_7;TACTL = TASSEL_1 + MC_1 + TACLR; // TACLK = ACLK, Up mode.//__bis_SR_register(LPM3_bits + GIE); // Wait for delay, Enable interruptsADC12CTL0 |= ENC; // Enable conversions// Initialization of Rs-232//FLL_CTL0 |= XCAP14PF; // Configure load capsdo{IFG1 &= ~OFIFG; // Clear OSCFault flag_delay_cycles(50000); // Time for flag to set}while ((IFG1 & OFIFG)); // OSCFault flag still set?P2SEL |= 0x30; // P2.4,5 = USCI_A0 RXD/TXDUCA0CTL1 |= UCSSEL_1; // CLK = ACLKUCA0BR0 = 0x03; // 32k/9600 - 13.65UCA0BR1 = 0x00; //UCA0MCTL = 0x06; // ModulationUCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**IE2 |= UCA0TXIE + UCA0RXIE; // enable RXD and TXD interrupt;// Initialize DMADMACTL0 = DMA0TSEL_6; // ADC12IF setDMACTL1 = DMAONFETCH;__data16_write_addr((unsigned short) &DMA0SA, (unsigned long) &ADC12MEM0); // Source address__data16_write_addr((unsigned short) &DMA0DA, (unsigned long) 0x001108); // Destination single addressDMA0SZ = 0x0FFF; // Set DMA Block size ADCSample sizeDMA0CTL = DMADT_4 + DMADSTINCR_3 + DMAIE + DMADSTBYTE + DMASRCBYTE; // Repeat single, inc dst, interruptsADCSample = ADC12MEM0; //Set integer to value of ADC12MEM0Pointer1 = &ADCSample; //Set Pointer1 to the address of ADCSample(Not sure where this address, I want it to be at 0x001108)DMA0CTL |= DMAEN; //Enable DMAADC12CTL0 |= ADC12SC; //Start Conversions//Serial Loopwhile(*Pointer1 <= 0x030FF) // Execute loop until loop reaches 0x030FF address{ADCSample2 = *Pointer1; //Set integer to value stored in Pointer1UCA0TXBUF = ADCSample2 >> 8; //Send upper byte from Pointer1 to Serialwhile(!(IFG2 & UCA0TXIFG)){__delay_cycles(1000);// wait for first transmit}UCA0TXBUF = ADCSample2;*Pointer1 = (*Pointer1 + 1) &0x030FF; //Increment Pointer1 from address 0x001108 to 0x030FF__bis_SR_register(LPM0_bits + GIE);}}
Martin Novotny102956IE2 |= UCA0TXIE + UCA0RXIE; // enable RXD and TXD interrupt;
You didn't post any ISR, so I assume you have none, so the first interrupt 8after GIE has been set) will jump into the void, crashing and resetting the MSP.
Martin Novotny102956ADC12CTL0 |= ADC12SC; //Start Conversions
Martin Novotny102956while(*Pointer1 <= 0x030FF) // Execute loop until loop reaches 0x030FF address
The DMA probably does the transfer of 4k of words (= 8k data) from ADC12MEM0 to 0x1108 to 0x3106 (overwriting everything that happens to be placed there by the linker), but it would be pure coincidence if this changes *Pointer1 without also messing up Pointer1 itself.
Martin Novotny102956while(!(IFG2 & UCA0TXIFG)){__delay_cycles(1000);// wait for first transmit}
Martin Novotny102956*Pointer1 = (*Pointer1 + 1) &0x030FF; //Increment Pointer1 from address 0x001108 to 0x030FF
What thsi does is: it takes the value pointed to by Pointer1, increments this value by 1, then does a bit-wise AND with 0x30ff and stores the result back to the memory location Pointer1 points to (whcih still is either ADCSample variable, or maybe anywhere int the addressing range, depending on what damage teh DMA has done.
The whole construct makes no sense, sorry.I guess, you didn't really understand what pointers in C are and how they are used.
_____________________________________Before posting bug reports or ask for help, do at least quick scan over this article. It applies to any kind of problem reporting. On any forum. And/or look here.If you cannot discuss your problem in the public, feel free to start a private conversation: click on my name and then 'start conversation'. But please do so only if you really cannot do it in a public thread, as I usually read all threads. And I prefer to answer where others can profit from it (or contribute to it) too.
Sorry, I guess I'm not sure why you bothered to even reply to my post when all you did was tell me everything I did wrong and offered no means of assistance. Of course, the code does not do what I was describing and NO I do not have a great understanding of what pointers in C are, but no where in your post did you make any attempt to help me learn or suggest ways to improve my code. Therefore do not bother responding to this reply because I won't be coming back to this forum. Its embarassing that you are to the go to expert on these forums as I posted a problem and instead of posting possible fix or even some good advice you simply told me everything already know which is that my code is obviously flawed.
Jens-Michael Gross is one of more tolerant gurus. You must have caught him at a bad moment.
I am guessing you are trying to DMA a number of samples from ADC to a buffer and simultaneously sending the buffer to the serial port. I think your code is using unallocated memory as though it was an array. This is not safe as the unallocated memory can move. Better to allocate yourself an array and ask the DMA to fill that array. The questions is not really about pointers but more of buffer arrays and DMA transfer. My background is not with MSP430...here's my "straw man" version of your code. See if others will knock it down.
# include <msp430xG46x.h>#define SAMPLES 256volatile int ADCSamples[SAMPLES];void main(void){ int i; int x; WDTCTL = WDTPW+WDTHOLD; // Stop watchdog P5DIR |= 0x02; P5OUT |= 0x02; // Initialization of ADC12// P6SEL |= 0x01; // Enable A/D channel A0 ADC12CTL0 &= ~ENC; // Disable Conversions ADC12CTL0 = ADC12ON + SHS_1 + REFON + REF2_5V + MSC; // turn on ADC12, set samp time ADC12CTL1 = SHP+CONSEQ_2; // Use sampling timer ADC12MCTL0 = SREF_1+INCH_0; // Vr+=VeREF+ (external) //ADC12IFG = 0; //Timer A TACCR0 = 1500; // Delay to allow Ref to settle TACCR1 = 1470; //TACCTL0 |= CCIE; // Compare-mode interrupt. TACCTL1 = OUTMOD_7; TACTL = TASSEL_1 + MC_1 + TACLR; // TACLK = ACLK, Up mode. //__bis_SR_register(LPM3_bits + GIE); // Wait for delay, Enable interrupts ADC12CTL0 |= ENC; // Enable conversions // Initialization of Rs-232// FLL_CTL0 |= XCAP14PF; // Configure load caps do { IFG1 &= ~OFIFG; // Clear OSCFault flag _delay_cycles(50000); // Time for flag to set } while ((IFG1 & OFIFG)); // OSCFault flag still set? P2SEL |= 0x30; // P2.4,5 = USCI_A0 RXD/TXD UCA0CTL1 |= UCSSEL_1; // CLK = ACLK UCA0BR0 = 0x03; // 32k/9600 - 13.65 UCA0BR1 = 0x00; // UCA0MCTL = 0x06; // Modulation UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** IE2 |= UCA0TXIE + UCA0RXIE; // enable RXD and TXD interrupt; // Initialize DMA // Repeat single src, inc dst, interrupts DMACTL0 = DMA0TSEL_6; // ADC12IF set DMACTL1 = DMAONFETCH; __data16_write_addr((unsigned short) &DMA0SA, (unsigned long) &ADC12MEM0); // Source __data16_write_addr((unsigned short) &DMA0DA, (unsigned long) ADCSamples); // Dest DMA0SZ = SAMPLES; // Set DMA Block size ADCSample size BYTES? ITEMS????? DMA0CTL = DMADT_4 + DMADSTINCR_3 + DMAIE + DMADSTBYTE + DMASRCBYTE; DMA0CTL |= DMAEN; //Enable DMA ADC12CTL0 |= ADC12SC; //Start Conversions // Need to wait for first sample to complete here. How to? //Serial Loop //Send samples from DMA buffer to serial port. //Assumes that ADC samples faster that the serial port transmits. for(i=0; i<SAMPLES; i++) { x = ADCSamples[i]; // Get a 16 bit sample UCA0TXBUF = x >> 8; // Send upper byte to Serial while(!(IFG2 & UCA0TXIFG)) continue; // Wait for first transmit UCA0TXBUF = x; // Send lower byte to Serial while(!(IFG2 & UCA0TXIFG)) continue; // Wait for second transmit __bis_SR_register(LPM0_bits + GIE); // What does this do? }}
I've put questions marks '?" where I'm not sure what is your intent. Note that the code sends binary values across the serial port. A terminal program such as Hyperterminal wants ASCII characters. Maybe your terminal program has a mode where it will print out binary values in human readable form.
Martin Novotny102956Sorry, I guess I'm not sure why you bothered to even reply to my post when all you did was tell me everything I did wrong and offered no means of assistance.
It won't help you if I jsut write a workign code version for you. You wouldn't learn anything and come back to the forum with your next non-working code. Telling you where you did wrong (and giving you the advice to take a class about usage of C pointers) will, if accepted by you, increase your knowledge and therefore your ability to do it right by yourself, while at the same time decreasing the probability that you come back for more assistance soon - with the very same mistakes.
Martin Novotny102956 I do not have a great understanding of what pointers in C are, but no where in your post did you make any attempt to help me learn or suggest ways to improve my code
Martin Novotny102956you simply told me everything already know which is that my code is obviously flawed
And I never provide complete code. First because I don't have the time to write it and test it (I surely don't want to release untested code), then I don't have the equipment to test the code (there are ~400 MSP derivates, not counting the required external circuitry for each case). And finally, nobody learns walking if he's carried around all the time.I may lend a hand while some tries to walk, but if someone hasn't even discovered that he has legs... well, I have given private lessons in the past. Mainly chemistry, physics and math. But for cash. And back then I had the time for doing so. Today, I have a fulltime job, and it's not being the 'go to expert'. It's not even for TI. I do this is my spare time. Free of charge.
Norman WongJens-Michael Gross is one of more tolerant gurus. You must have caught him at a bad moment.
But now to your code. I didn't check the clock and por tinitialization. However, there are a few things...
Norman Wong //__bis_SR_register(LPM3_bits + GIE); // Wait for delay, Enable interrupts
TACCTL0 &= ~CCIFG; clear interrupt flagwhile (!(TACCTL0&CCIFG)); // wait until TAR has counted to TACCR0
Norman WongIE2 |= UCA0TXIE + UCA0RXIE; // enable RXD and TXD interrupt;
Norman Wong DMA0SZ = SAMPLES; // Set DMA Block size ADCSample size BYTES? ITEMS?????
Norman Wong DMA0CTL = DMADT_4 + DMADSTINCR_3 + DMAIE + DMADSTBYTE + DMASRCBYTE;
Norman Wong // Need to wait for first sample to complete here. How to?
Norman Wong __bis_SR_register(LPM0_bits + GIE); // What does this do?
However, there is no ISR at all, so this line is not doing any good.It should be replaced by something that checks DMA0SZ:
while(DMA0SZ>=(SAMPLES-i));