This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430f2274 SPI interfacing with DAC8830.

Other Parts Discussed in Thread: DAC9881, DAC8830

Hi,

I am trying to control a VCO with the DAC for some RF circuit.

The MSP430 that I use, has an output streambit of 8bit (or 7), and the DAC needs a 16 bit input. I have read that I need to send 2 bytes. I have tried a 1000 ways to do that but it will not work.

Right now, my aim is just to send only one 16 bit stream like for example 1000 0000 0000 0000 to the DAC and get a voltage output of Vref/2. That's it, from that point on I can grow :).

The last code that I tried is:

#include "msp430x22x4.h"

void main(void) {

double data1,data2,i;

int byte0, byte1;

WDTCTL = WDTPW + WDTHOLD;             // Stop watchdog timer
  
P3SEL |= 0x0A;        //We activate P3.1 and P3.3 (pin10 and 12) for USCI mode
P4DIR |= 0x2A;         //we activate as outputs P4.1, P4.3 and P4.5 (pins: 16, 18 and 20). This are the CS controlls to controll 3VCO's, that is my final objective.
P4OUT &= 0x00;        //Make sure that everything is low
P4OUT |= 0x28;        //we set high P4.3 and P4.5, so data only goes to P4.1. Remeber that data loads on low
UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC;  // 3-pin, 8-bit SPI master, Sinchronous mode
UCB0CTL1 |= UCSSEL_2;                     // SMCLK

UCB0BR0 |= 0x02;
UCB0BR1 = 0;                          
UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**

byte0 = 0x10000000;
byte1 = 0x00000000;

while ((IFG2 & UCB0TXIFG) == 0);   //wait until buffer is ready
      UCB0TXBUF = byte0;             // Send clocks to the DAC, this shifts 1st byte
while ((IFG2 & UCB0TXIFG) == 0);
      UCB0TXBUF = byte1 ;             // Send clocks to the DAC, this shifts 2nd byte
                    
P4OUT |= 0x02; Turn the CS of the DAC on high

}

I have also a 18bit DAC9881, would I have to send 3 bytes?

Thank you very much for your help. I have tried for several days, and I have been doing some research on the web but I couldn't find anything helpfull.

  • Hi RIV,

    The DAC8830 only requires a 16 bit word and the output should update on the falling edge of the 16th SCLK since there is no /LDAC in this device. I would double check your clock phasing and polarity to verify that they are correct and the SDI is changing on the falling edge so it is valid on the rising edge as shown in Figure 1 of the data sheet. If you can, take a scope picture of your data transfer word showing your /CS, SCLK, and SDI signals. From there we can get an idea of what is going wrong. Now, the DAC8830 is unbuffered so you are going to need a output amplifier to isolate the internal resistor string from the output load.

    The DAC9881 uses a 24 bit data transfer word as shown in Table 4 on page 29 of that data sheet. I would look through that section before trying to communicate with the DAC9881.

    Regards,

    Tony Calabria

  • Hi RIV,

    RIV said:
    byte0 = 0x10000000;
    byte1 = 0x00000000;

     

    what compiler do you use? If IAR then the code above byte0 and byte1 are both  gonna be  zeros since numbers starting with 0x are considered hexadecimal numbers. Try this: byte0=0x80, byte1=0x00. As far as I know there is no prefix for binary numbers in IAR.

    It is also wise to name your variables at least not to be misleading. 'Int' is a 16 bit variable as opposed to a byte which is a 8 bits wide. I'd change the the typed definition to 'short' or 'unsigned char'.

     

    I'd also try out the different UCCKPH settings as Tony pointed out.

     

    Greg

  • FINAL WORKING SOLUTION!

    So finally I managed to solve the problems also thanks to the 2 replies.

    For if someone is ever interested, and has the same problem I have. I am going to writte the code that I used with all the helpfull comments.

    Thank you very much again for your help.

    Let me say that this thing works as perfectly.


    #include "msp430x22x4.h"

    void main(void) {
     
    unsigned char byte0, byte1, i;

    WDTCTL = WDTPW + WDTHOLD;             // Stop watchdog timer, always put it after the declaration of variables
    UCB0CTL1 = UCSWRST;
    P1DIR |= 0x40;        //Set port1 pin6 as an output 01000000 (TI FORUM:its a pin that sets an led)
    P1OUT = 0x40;        //Activate that PIN as an output
    P3SEL |= 0x0A;        //We activate P3.1 and P3.3 (pin10 and 12) for USCI mode
    P4DIR |= 0x2A;         //we activate as outputs P4.1, P4.3 and P4.5 (pins: 16, 18 and 20) (TI FORUM:final objective is to control DAC's)
    P4OUT &= 0x00;        //Make sure that everything is low
    P4OUT |= 0x28;        //we set high P4.3 and P4.5, so data only goes to P4.1. Remember that data loads on low (Because there is where i have hooked up my test DAC)
    UCB0CTL0 |= UCCKPL + UCMSB + UCMST + UCSYNC;  // 3-pin, 8-bit SPI master
    UCB0CTL1 |= UCSSEL_2;                     // SMCLK
    UCB0BR0 |= 0x02;                            //baudrate/2
    UCB0BR1 = 0;                              //

    UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**

    byte0 = 0xA3;        //Set some random number to see if it works
    byte1 = 0x8F;        //Set some random number to see if it works

    P4OUT &= ~0x02;        //Make sure that it's low, probably not needed in this code
    while ((IFG2 & UCB0TXIFG) == 0);
          UCB0TXBUF = byte0;             // Send clocks to the DAC, this shifts 1st byte
                              // Wait until all 8 bits have been received.
    while ((IFG2 & UCB0TXIFG) == 0);
          UCB0TXBUF = byte1 ;             // Send clocks to the DAC, this shifts 2nd byte
                              // Wait until all 8 bits have been received.
    while ((IFG2 & UCB0TXIFG) == 0);    //wait until it is done too put CS on high
    i=1;        //To waist some time after so CS is not going up to fast (problem detected with an osciloscope
    P4OUT |= 0x02;

    }

    //Right now with byte0 and byte1 we would get 0.6389*Vref. The way that this works is that first it shifts
    //the byte0 and MSB first, then it shifts in the byte1 and MSB first. So that means that what the DAC will read
    //is: first byte0 and then byte1 resulting A38F. In decimal that would be A38F = 41871. So the Vout should be
    //Vout=Vref*41871/65536.
    //To clarify, for Vref*0.5 type byte0=0x80 and byte1=0x00. That would give 1000 0000 0000 0000.

  • Hi

            I have going to interface the MSP430f5438 with digital potentiometer MCP41010 by SPI communication.For that i have write the code as below.My spi  had some problem because of that i am not able to write the value in the data registers.If anyone had any solution for me then please send me.

     

     

    void spi_init(void)
    {
       
      //unsigned char spi_cmd,spi_data;
      WDTCTL = WDTPW+WDTHOLD;                   // Stop watchdog timer

      P10OUT |= 0x01;                            //Chip select
      P10DIR |= 0x01;                            // Set P10-1 to output direction
      P10SEL |= 0xA;                            // P10.1,3 option select for the si and clk

      UCB3CTL1 |= UCSWRST;                      // **Put state machine in reset**
      UCB3CTL0 |= UCMST+UCSYNC+UCMSB;    // 3-pin, 8-bit SPI master
                                                // Clock polarity high, MSB
      UCB3CTL1 |= UCSSEL_2;                     // SMCLK
      UCB3BR0 = 0x02;                           // /2
      UCB3BR1 = 0;                              //
      //UCA3MCTL = 0;                             // No modulation
      UCB3CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
     // UCA0IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt

      P10OUT &= ~0x01;                           // Now with SPI signals initialized,
      P10OUT |= 0x01;                            // reset slave


    }

    void spi_write(unsigned char data)
    {
       while (!(UCB3IFG&UCTXIFG));               // USCI_A0 TX buffer ready?
      UCB3TXBUF = data;    

    }

    void main (void)

    {

    spi_init();

    P10OUT&=~0x01;

    spi_write(17);      //command set for the digital pot IC

    spi_write(120);   //values given to the data register

    P10OUT |=0x01;

    }

     

  • Hi,

    My first recommendation is to get a picture of your SPI data transfer word using an oscilloscope. Here we can check the clock phasing and polarity as well as verify you are writing to the DAC what you think you are.

    Regards,

    Tony Calabria

  • Hi,

              I have check  on CRO but it don't show clock pulses on pin no 10.3. Is their any problem with the code?

  • Hi,

     

    I haven't checked your data sheet to see the number of bytes you can output, pin connections and I have not checked the POT neither but I suggest this:

    In your function:

    void spi_write(unsigned char data)
    {
       while (!(UCB3IFG&UCTXIFG));               // USCI_A0 TX buffer ready?
      UCB3TXBUF = data;    

    }

     

    Try this instead:

    void spi_write(unsigned char data)
    {
     int i=0;

    while (!(UCB3IFG&UCTXIFG));

      UCB3TXBUF = data;    

    while (!(UCB3IFG&UCTXIFG));        //waits for the data to have transfered completly

    i = 0;                      //waits a little instant more

    }

     

    One thing more, shouldnt it be UCB3TXIFG?

    I supose that you are transfering 16 bit and that your MCU is 8bit SPI I/O right?

    You also want to make sure that before setting your SPI interface you have this command:

    UCB3CTL1 |= UCSWRST; //Make sure that the SPI interface is off while setting it.

    That should work, tell us if it worked :)