• Join
  • Sign In with my.TI Login
Texas Instruments
  • Products
  • Applications
  • Tools & Software
  • Support & Community
  • Sample & Buy
  • About TI
Sample & Purchase Cart Sample & Purchase Cart
  • Search
  • Advanced
TI E2E™ Community
  • Support Forums
  • Blogs
  • Groups
  • Videos
  • 简体中文
  • More ...
TI Home » TI E2E Community » Support Forums » Microcontrollers » MSP430™ Microcontrollers » MSP430 Ultra-Low Power 16-bit Microcontroller Forum » Using Pointer to help send multiple AD Conversions out Serially
Share
MSP430™ Microcontrollers
  • Forum
  • Announcements
  • E2E Wiki
Options
  • Subscribe via RSS
MSP430 Resources
  • MSP430 Product Folder
  • MSP-EXP430G2 - MSP430 LaunchPad Value Line Development kit
  • MSP430 Getting Started Guide
  • MSP430 Microcontroller Projects
  • More Resources >
  • Using Pointer to help send multiple AD Conversions out Serially

    Using Pointer to help send multiple AD Conversions out Serially

    This question is not answered
    Martin Novotny102956
    Posted by Martin Novotny102956
    on Apr 11 2012 21:06 PM
    Prodigy30 points
    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 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
    DMACTL0 = DMA0TSEL_6; // ADC12IF set
    DMACTL1 = DMAONFETCH;
    __data16_write_addr((unsigned short) &DMA0SA, (unsigned long) &ADC12MEM0); // Source address
    __data16_write_addr((unsigned short) &DMA0DA, (unsigned long) 0x001108); // Destination single address
    DMA0SZ = 0x0FFF; // Set DMA Block size ADCSample size
    DMA0CTL = DMADT_4 + DMADSTINCR_3 + DMAIE + DMADSTBYTE + DMASRCBYTE; // Repeat single, inc dst, interrupts

    ADCSample = ADC12MEM0; //Set integer to value of ADC12MEM0
    Pointer1 = &ADCSample; //Set Pointer1 to the address of ADCSample(Not sure where this address, I want it to be at 0x001108)
    DMA0CTL |= DMAEN; //Enable DMA
    ADC12CTL0 |= ADC12SC; //Start Conversions


    //Serial Loop
    while(*Pointer1 <= 0x030FF) // Execute loop until loop reaches 0x030FF address
    {
    ADCSample2 = *Pointer1; //Set integer to value stored in Pointer1
    UCA0TXBUF = ADCSample2 >> 8; //Send upper byte from Pointer1 to Serial
    while(!(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);
    }
    }



    Report Abuse
    • Reply
    You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    All Replies
    • Jens-Michael Gross
      Posted by Jens-Michael Gross
      on Apr 12 2012 11:33 AM
      Guru140650 points

      Martin Novotny102956
      IE2 |= UCA0TXIE + UCA0RXIE; // enable RXD and TXD interrupt;

      Why do you enable interrupts fo rRX and TX if you want to handle the sending in a busy-waiting loop?

      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 Novotny102956
      ADC12CTL0 |= ADC12SC; //Start Conversions

      Yes, it starts conversions. However, you do not wait for the conversions to complete. So your following code tries to send conversion results that haven't been sampled yet.

      Martin Novotny102956
      while(*Pointer1 <= 0x030FF) // Execute loop until loop reaches 0x030FF address

      No. This while lopps until the INT value where Pointer1 points to, exceeds 0x30FF.
      Since oyu assigned Pointer1 = &ADCSample, and ADCSample is statically filled with, well, the power-on value of ADC12MEM0 some lines before, this loop will run either forever or never

      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 Novotny102956
      while(!(IFG2 & UCA0TXIFG))
      {
      __delay_cycles(1000);// wait for first transmit
      }

      THis makes no sense. Either you wait for TXIFG set (then you don't need a delay) or you want a delay (then you don't need the while).
      Jus tuse the while, with no delay code.

      Martin Novotny102956
      *Pointer1 = (*Pointer1 + 1) &0x030FF; //Increment Pointer1 from address 0x001108 to 0x030FF

      Definitely not.

      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.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Martin Novotny102956
      Posted by Martin Novotny102956
      on Apr 12 2012 16:15 PM
      Prodigy30 points

      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.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Norman Wong
      Posted by Norman Wong
      on Apr 12 2012 17:49 PM
      Guru14970 points

      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 256
      volatile 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.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jens-Michael Gross
      Posted by Jens-Michael Gross
      on Apr 13 2012 09:30 AM
      Guru140650 points

      Martin Novotny102956
      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.

      Well, Telling you where some fundamental errors hide in your code (well, the do not really 'hide') is definitely some sort 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

      I gave the suggestion to learn about pointers. Once doing so successfully, you'll see by yourself where and why you mixed up pointers, references and values.
      And I gave you a lot of specific information about where you did wrong.

      Martin Novotny102956
      you simply told me everything already know which is that my code is obviously flawed

      Not that (this you obvbiously know or else you wouldn't have pasted here), but why.

      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.

      _____________________________________
      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.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jens-Michael Gross
      Posted by Jens-Michael Gross
      on Apr 13 2012 10:24 AM
      Guru140650 points

      Norman Wong
      Jens-Michael Gross is one of more tolerant gurus. You must have caught him at a bad moment.

      Thanks :) Well, my time is limited and I try to help people who need my help (or from someone else with deeper MSP knowledge). It's always a 'bad time' when I come over a post that requests 'I have a job to do, can you give the the finished code for free'. I ususally ignore them, or write a short sarcastic answer.
      But then there are cases where I see that someone has already written code (sometimes more than my weary eyes want to read) and asks for advice, and I usually start replying. But if I then discover that there are basic coding errors that are not MSP related, and indicate that fundamental concepts of the used programming language are unknown or at least not understood, I consider this as a waste of my time. Literally bad (= wasted) time. Sure, I  could simply close the browser tab and move on, but since I already started replying, I tend to 'finish' it instead and point at least in a direction that will result in some improvement.

      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

      This line is intended to put the CPU to sleep until the timer triggers an interrupt and the interupt funciton ends the sleep mode. But since it is ina comment, the necessary settling delay isn't performed. So it shoud be replaced by a busy-waiting version:

      TACCTL0 &= ~CCIFG; clear interrupt flag
      while (!(TACCTL0&CCIFG)); // wait until TAR has counted to TACCR0

      Norman Wong
      IE2      |= UCA0TXIE + UCA0RXIE; // enable RXD and TXD interrupt;

      You shouldn't enable interrupts if you intend to manuall do the transfer in main. And definitely not before you have somehting to send :)
      As soon as you set UCA0TXIE, the transmit ISR is called (and I don't see one).

      Norman Wong
      DMA0SZ  = SAMPLES; // Set DMA Block size ADCSample size BYTES? ITEMS?????

      Transfers (ITEMS). The DMA can do byte and word transfers. It can even do write reads to word writes (clearing the upper byte), or word reads to byte (dropping the upper byte) in case the peripheral requires a word access.

      Norman Wong
        DMA0CTL = DMADT_4 + DMADSTINCR_3 + DMAIE + DMADSTBYTE + DMASRCBYTE;

      I Guess, DMADT_0 is to be used here. Else the transfer is repeated from start after the 256th conversion. (but maybe that's what you want later).
      Also, I don't see a DMA ISR, so DAMIE really shouldn't be set.

      Norman Wong
        // Need to wait for first sample to complete here. How to?


      You can check DMA0SZ. It is decremented after each transfer.

      Norman Wong
          __bis_SR_register(LPM0_bits + GIE);  // What does this do?


      Normally, it puts the CPU to sleep but allows interrupts. So if an interrupt is triggered, the CPU is activated, and once teh ISR returns, it goes back to sleep (unless the ISR has explicitely ended the sleep mode using the bic_SR_regsiter_on_exit(LPM0_bits) intrinsic.
      The LPM bits ar epart of the processor status register, which is saved on ISR entry and restored (together with the LPM bits) on ISR exit. LPM0_bits is a macro that ony contains the CPUOFF bit, disabling MCLK. LPM1_bits would also disable the DCO, but then there would be a delay for switching MCLK on again. And since the DMA transfer also requires MCLK...

      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));

      _____________________________________
      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.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    TI E2E™ Community
    • Support Forums
    • Blogs
    • Videos
    • Groups
    • Site Support & Feedback
    • Settings
    TI E2E™ Community Groups
    • TI University Program
    • Make the Switch
    • Microcontroller Projects
    • Motor Drive & Control
    Other Communities
    • Deyisupport
    • Designsomething.org
    • beagleboard.org
    • TI on Element 14
    • TI on TechXchangeSM
    Other Technical & Support Resources
    • WEBENCH® Design Center
    • Product Information Centers
    • Technical Documents
    • TI Design Network
    • TI Technical Articles
    • TI Training

    All content and materials on this site are provided "as is". TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with regard to these materials, including but not limited to all implied warranties and conditions of merchantability, fitness for a particular purpose, title and non-infringement of any third party intellectual property right. TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with respect to these materials. No license, either express or implied, by estoppel or otherwise, is granted by TI. Use of the information on this site may require a license from a third party, or a license from TI.

    Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms of Use of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms of Use of this site. TI, its suppliers and providers of content reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.

    Follow Us Texas Instruments on Facebook Texas Instruments on Twitter Texas Instruments on LinkedIn Texas Instruments on Google+
    TI Worldwide | Contact Us | my.TI Login | Site Map | Corporate Citizenship | mobile m.ti.com (Mobile Version)

    TI is a global semiconductor design and manufacturing company. Innovate with 100,000+ analog ICs and
    embedded processors, along with software, tools and the industry’s largest sales/support staff.

    © Copyright 1995-2013 Texas Instruments Incorporated. All rights reserved.
    Trademarks | Privacy Policy | Terms of Use