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.

TM4C123GH6PM: Interfacing with DAC0840S

Part Number: TM4C123GH6PM

I am connecting the DAC084SO to the TIVA C series Launch pad using SPI protocol in SSI0.

I write the same input values (a  triangular wave form using the while loop with counter) to all 4 channels and I am getting the required output in the channels 2,3 and 4. However, I am getting disrupted output in output channel 1.

I have pasted the oscilloscope screen shots of the 3 working outputs and the 1 disrupted output below:

I have pasted the code below:

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"

//*****************************************************************************
//! Trying to get DAC SSI 084 working. 4 channel.
//!
//! This example uses the following peripherals and I/O signals.  You must
//! review these and change as needed for your own board:
//! - SSI0 peripheral
//! - GPIO Port A peripheral (for SSI0 pins)
//! - SSI0Clk - PA2
//! - SSI0Fss - PA3
//! - SSI0Rx  - PA4
//! - SSI0Tx  - PA5
#define NUM_SSI_DATA            3

int
main(void)
{

    uint8_t loopCount = 0;
    uint16_t dacAaddress_dontUpdate = 0b0000;// Writing to regster 00 A , not updating till D is written
    uint16_t dacBaddress_dontUpdate = 0b0100;// Writing to regster 01 B,  not updating till D is written
    uint16_t dacCaddress_dontUpdate = 0b1000;// Writing to regster 10 C,  not updating till D is written
    uint16_t dacDaddress_doUpdate   = 0b1101;// Writing to regster 11 D,  updating all outputs as D is written

    // Shift the address and update bits 8 bits inside so that you can use OR operator to write the last 8 bits
    dacAaddress_dontUpdate = dacAaddress_dontUpdate<<8;
    dacBaddress_dontUpdate = dacBaddress_dontUpdate<<8;
    dacCaddress_dontUpdate = dacCaddress_dontUpdate<<8;
    dacDaddress_doUpdate   = dacDaddress_doUpdate<<8;

    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    // The SSI0 peripheral must be enabled for use.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    // For this example SSI0 is used with PortA[5:2].
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    // Configure the pin muxing for SSI0 functions on port A2, A3, A4, and A5.
    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    GPIOPinConfigure(GPIO_PA4_SSI0RX);
    GPIOPinConfigure(GPIO_PA5_SSI0TX);

    // Configure the GPIO settings for the SSI pins.  This function also gives
    // control of these pins to the SSI hardware.  Consult the data sheet to
    // see which functions are allocated per pin.
    // The pins are assigned as follows:
    //      PA5 - SSI0Tx
    //      PA4 - SSI0Rx
    //      PA3 - SSI0Fss
    //      PA2 - SSI0CLK
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |GPIO_PIN_2);

    // Configure and enable the SSI port for TI master mode.  Use SSI0, system
    // clock supply, master mode, 1MHz SSI frequency, and 16-bit data.
    // Bit rate has to be 2MHz or higher
    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_TI,SSI_MODE_MASTER, 1000000, 16);

    // Enable the SSI0 module.
    SSIEnable(SSI0_BASE);


    while(1){
        // Now use OR operator to put your control value in the input bits
        // Loop count is a 8 bit value . So will modify the last 8 bits of parent only.

        // Now shift  all the input variables to 4 bits inside further.
        // Input variable to the DAC048S is 16 bit and last 4 bits are expected to be useless.
        // Without shifting inside , the last 8 bits of the now 12 bit word will be neglected!.


        SSIDataPut(SSI0_BASE,  ((dacAaddress_dontUpdate | loopCount)<<4));
        SSIDataPut(SSI0_BASE,  ((dacBaddress_dontUpdate | loopCount)<<4));
        SSIDataPut(SSI0_BASE,  ((dacCaddress_dontUpdate | loopCount)<<4));
        SSIDataPut(SSI0_BASE,  ((dacDaddress_doUpdate   | loopCount)<<4));

        while(SSIBusy(SSI0_BASE)){}


        loopCount++;
        if (loopCount==255)
            loopCount=0;
    }

}
// UART interrupt handler, definition in main program
// Simply because we put this in NVIC table in startup ccs file, something has to be here.
void UARTIntHandler(void)
{
}

Any help on why one channel is not working smoothly?

  • HI,

      I don't really spot anything wrong with your code. First, Do you have another spare DAC device that you can try? I will suggest you do some experiments. Secondly, Only test the first channel and leave out the other 3 channels for now. Will you get the same problem? Since you have a scope (a logic analyzer will be even better), you can look at the SPI output from the MCU and see if it is outputting the correct serial data. If the serial data is correct but the output voltage from the DAC is not correlating with the input value then you will need to post your question to the Data Converters forum at https://e2e.ti.com/support/data-converters/f/73. I can only support the MCU, not the DAC device. Again, if you have an extra part, try your program on the second part first. If a second part is giving the same result, then it is most likely having something to do with your code. In that case, focus on just the channel that is not giving the correct result. 

  • Hello Charles and Balaji,

    Just a thought on the SSI protocol selection in line 67.  So-called TI frame protocol was selected in the API (FRF_TI).

    Is it possible that selecting one of the Motorola SPI protocols can alleviate the CH_A situation?

    I've had a similar situation, maybe this idea helps in your case.

    Regards,

    P.S.

    Here's the API selection possibilities from TI's document :

    The ui32Protocol parameter defines the data frame format. The ui32Protocol parameter

    can be one of the following values: SSI_FRF_MOTO_MODE_0, SSI_FRF_MOTO_MODE_1,

    SSI_FRF_MOTO_MODE_2, SSI_FRF_MOTO_MODE_3, SSI_FRF_TI, or SSI_FRF_NMW.

    Note that the SSI_FRF_NMW option is only available on some devices. Refer to the device

    data sheet to determine if the Microwire format is supported on a particular device. The Mo-

    torola frame formats encode the following polarity and phase configurations:

    Polarity Phase Mode

    0 0 SSI_FRF_MOTO_MODE_0

    0 1 SSI_FRF_MOTO_MODE_1

    1 0 SSI_FRF_MOTO_MODE_2

    1 1 SSI_FRF_MOTO_MODE_3

  • Hi Otto,

      Thank you for the suggestion. I read the datasheet yesterday and it looks like the TI frame format is correct. Besides, it works for the other three channels. Certainly, the poster can try the Freescale format and see if that makes a difference. 

  • Thank you for your reply. I will check with an alternate DAC and get back to you.

  • Thank you for the reply.

    I will check using the other SSI modes and get back to you.

  • Hi Charles,

    1)      I tried with another DAC IC. The results are the same. Channel A not working correctly, other 3 are working.

    2)      I disabled other 3 channels and ran only channel A with immediate output update using the code below in while loop. Channel A is working fine in this setup.

    SSIDataPut(SSI0_BASE, ((0b000100000000| loopCount)<<4));
    //SSIDataPut(SSI0_BASE, ((dacBaddress_dontUpdate | loopCount)<<4));
    //SSIDataPut(SSI0_BASE, ((dacCaddress_dontUpdate | loopCount)<<4));
    //SSIDataPut(SSI0_BASE, ((dacDaddress_doUpdate   | loopCount)<<4));

    3)      Then I tried using 2 of the 4 channels with immediate output update after each SSI write, using the code below. Channel A is disturbed while channel B is good looking.

     

     SSIDataPut(SSI0_BASE, ((0b000100000000| loopCount)<<4));
    
     SSIDataPut(SSI0_BASE, ((0b010100000000| loopCount)<<4));
    
     //SSIDataPut(SSI0_BASE, ((dacBaddress_dontUpdate | loopCount)<<4));
    
     //SSIDataPut(SSI0_BASE, ((dacCaddress_dontUpdate | loopCount)<<4));
    
     //SSIDataPut(SSI0_BASE, ((dacDaddress_doUpdate   | loopCount)<<4));

         Next I again did the 2 channels , but this time updated both outputs only after writing channel B data. Now disturbance in channel A looks of higher duration. Channel B is again OK.

           SSIDataPut(SSI0_BASE, ((0b000000000000| loopCount)<<4));

           SSIDataPut(SSI0_BASE, ((0b010100000000| loopCount)<<4));

           //SSIDataPut(SSI0_BASE, ((dacBaddress_dontUpdate | loopCount)<<4));

           //SSIDataPut(SSI0_BASE, ((dacCaddress_dontUpdate | loopCount)<<4));

           //SSIDataPut(SSI0_BASE, ((dacDaddress_doUpdate   | loopCount)<<4));

     

    4)      As another attempt, I used all 4 and updated each after writing its data Channel A alone is disturbed with fluctuations of higher frequency, probably due to immediate update.

     

           SSIDataPut(SSI0_BASE, ((0b000100000000| loopCount)<<4));

           SSIDataPut(SSI0_BASE, ((0b010100000000| loopCount)<<4));

           SSIDataPut(SSI0_BASE, ((0b100100000000| loopCount)<<4));

           SSIDataPut(SSI0_BASE, ((0b110100000000| loopCount)<<4));

     

    I think updating after giving data to other channels gives more spacing between the fluctuations in channel A.

    Any suggestions please?

     

  • Hi Otto,

    I tried the different frame formats you have mentioned.

        // SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_TI,SSI_MODE_MASTER, 1000000, 16);            // 3 out of 4 are working.
        // SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_NMW,SSI_MODE_MASTER, 1000000, 16);           // None work
        // SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3,SSI_MODE_MASTER, 1000000, 16);   // None work
        SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_2,SSI_MODE_MASTER, 1000000, 16);   // all are working
        // SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_1,SSI_MODE_MASTER, 1000000, 16);   // None work
        // SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,SSI_MODE_MASTER, 1000000, 16);   // Gives garbled output on all 4 channels
    

    The moto mode 2 format gives clean outputs in all 4 channels when updating the output at the end of writing data to fourth register. Thank you for your suggestion.