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.

TM4C123G SPI with DAC8564 etc.

Other Parts Discussed in Thread: DAC8564, TM4C123GH6PM, DAC8164, DAC7565

Hi,

TM4C123G SPI frame format data bit is 4 to 16bit, 

TI DAC8564 etc chip-set frame format data bit is 24bit.

TM4C123G cannot direct support these DAC chip-set.

Do you have any idea?

Thanks and regards,

Lung Tat Ng

  • Hello Lung Tat,

    To support such an interface you would need to do the following

    1. Change the FSS control to GPIO

    2. Configure the SSI for 8-bit transactions or 12-bit transactions

    3. When sending the data, make the GPIO low and write the 3 8-bit words or 2 12-bit words

    4. Make the GPIO high.

    Regards

    Amit

  • Hi Ami,

    Thank you,

    My setting is as following: (MCU is master, writing data out only, 1Mhz,12bit)

    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);    //set SSI1

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);   //set Port D

    GPIOPinConfigure(GPIO_PD0_SSI1CLK);

     GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_1);   //change  PD1 to GPIO

    GPIOPinConfigure(GPIO_PD3_SSI1TX);

    GPIOPinTypeSSI(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_3);

    SSIConfigSetExpClk(SSI1_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 12);

    SSIEnable(SSI1_BASE);

    The parameter "SSI_FRF_MOTO_MODE_0" may I need to change? and where can I find the above command set  explanation.

    Can I set PD1 default high?

    Best regards,

    Lung Tat Ng

  • Hello Lung Tat,

    The SSI Frame Format is defined in the SSI Chapter of the Data Sheet. The SPO and SPH setting decide what SSI_FRF_MOTO_MODE_X is.

    The PD1 must be set high if the CS as expected by the Slave device for a transaction is low. Please do note that the API for setting the Pin High would be

    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_1, GPIO_PIN_1);

    Regards

    Amit

  • Hi Amit,

    Thanks for your advice.

    As mention above, between sending two 12bit, some signal would be shown if first 12bit sent:

    1. SSIRIS Transmit FIFO raw Interrupt status Register, TXRIS bit = 1: FIFO empty.

    2. SSISR SSI status register, a. TFE bit = 1: SSI transmit FIFO empty, b. BSY bit = 1: SSI busy.

    3. SSICR1 SSI control register, EOT bit = 1: TXRIS interrupt is enabled.

    May I know which one is better for indicate if first 12bit sent, this is in order to guarantee second 12bit sending correctly.

    Thanks and regards,

    Lung Tat Ng

     

  • Hello Lung Tat,

    The option-3 would be the best one to use.

    Regards

    Amit

  • Hi Amit,

    I'm still facing identifier error, I try a SSI axemple as follow:


    #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"

    //*****************************************************************************

    //
    // Number of bytes to send and receive.
    //
    //*****************************************************************************
    #define NUM_SSI_DATA 3

    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
    //
    // Enable GPIO port A which is used for UART0 pins.
    // TODO: change this to whichever GPIO port you are using.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Configure the pin muxing for UART0 functions on port A0 and A1.
    // This step is not necessary if your part does not support pin muxing.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);

    //
    // Enable UART0 so that we can configure the clock.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    //
    // Use the internal 16MHz oscillator as the UART clock source.
    //
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);

    //
    // Select the alternate (UART) function for these pins.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Initialize the UART for console I/O.
    //
    UARTStdioConfig(0, 115200, 16000000);
    }

    //*****************************************************************************
    //
    // Configure SSI0 in master Freescale (SPI) mode. This example will send out
    // 3 bytes of data, then wait for 3 bytes of data to come in. This will all be
    // done using the polling method.
    //
    //*****************************************************************************
    int
    main(void)
    {
    uint32_t pui32DataTx[NUM_SSI_DATA];
    uint32_t pui32DataRx[NUM_SSI_DATA];
    uint32_t ui32Index;

    //
    // Set the clocking to run directly from the external crystal/oscillator.
    // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
    // crystal on your board.
    //
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
    SYSCTL_XTAL_16MHZ);

    //
    // Set up the serial console to use for displaying messages. This is
    // just for this example program and is not needed for SSI operation.
    //
    InitConsole();

    //
    // Display the setup on the console.
    //
    UARTprintf("SSI ->\n");
    UARTprintf(" Mode: SPI\n");
    UARTprintf(" Data: 8-bit\n\n");

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

    //
    // For this example SSI0 is used with PortA[5:2]. The actual port and pins
    // used may be different on your part, consult the data sheet for more
    // information. GPIO port A needs to be enabled so these pins can be used.
    // TODO: change this to whichever GPIO port you are using.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Configure the pin muxing for SSI0 functions on port A2, A3, A4, and A5.
    // This step is not necessary if your part does not support pin muxing.
    // TODO: change this to select the port/pin you are using.
    //
    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
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |
    GPIO_PIN_2);

    //
    // Configure and enable the SSI port for SPI master mode. Use SSI0,
    // system clock supply, idle clock level low and active low clock in
    // freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data.
    // For SPI mode, you can set the polarity of the SSI clock when the SSI
    // unit is idle. You can also configure what clock edge you want to
    // capture data on. Please reference the datasheet for more information on
    // the different SPI modes.
    //
    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,
    SSI_MODE_MASTER, 1000000, 8);

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

    //
    // Read any residual data from the SSI port. This makes sure the receive
    // FIFOs are empty, so we don't read any unwanted junk. This is done here
    // because the SPI SSI mode is full-duplex, which allows you to send and
    // receive at the same time. The SSIDataGetNonBlocking function returns
    // "true" when data was returned, and "false" when no data was returned.
    // The "non-blocking" function checks if there is any data in the receive
    // FIFO and does not "hang" if there isn't.
    //
    while(SSIDataGetNonBlocking(SSI0_BASE, &pui32DataRx[0]))
    {
    }

    //
    // Initialize the data to send.
    //
    pui32DataTx[0] = 's';
    pui32DataTx[1] = 'p';
    pui32DataTx[2] = 'i';

    //
    // Display indication that the SSI is transmitting data.
    //
    UARTprintf("Sent:\n ");

    //
    // Send 3 bytes of data.
    //
    for(ui32Index = 0; ui32Index < NUM_SSI_DATA; ui32Index++)
    {
    //
    // Display the data that SSI is transferring.
    //
    UARTprintf("'%c' ", pui32DataTx[ui32Index]);

    //
    // Send the data using the "blocking" put function. This function
    // will wait until there is room in the send FIFO before returning.
    // This allows you to assure that all the data you send makes it into
    // the send FIFO.
    //
    SSIDataPut(SSI0_BASE, pui32DataTx[ui32Index]);
    }

    //
    // Wait until SSI0 is done transferring all the data in the transmit FIFO.
    //
    while(SSIBusy(SSI0_BASE))
    {
    }

    //
    // Display indication that the SSI is receiving data.
    //
    UARTprintf("\nReceived:\n ");

    //
    // Receive 3 bytes of data.
    //
    for(ui32Index = 0; ui32Index < NUM_SSI_DATA; ui32Index++)
    {
    //
    // Receive the data using the "blocking" Get function. This function
    // will wait until there is data in the receive FIFO before returning.
    //
    SSIDataGet(SSI0_BASE, &pui32DataRx[ui32Index]);

    //
    // Since we are using 8-bit data, mask off the MSB.
    //
    pui32DataRx[ui32Index] &= 0x00FF;

    //
    // Display the data that SSI0 received.
    //
    UARTprintf("'%c' ", pui32DataRx[ui32Index]);
    }

    return 0;
    }

    The Error message picture as below, after build project.

    But the header file already contains them.

    What things I'm missing?

    Lung Tat Ng

  • Hi Amit,

    It is passed if adding "MAP_" in the front of command

    MAP_GPIOPinConfigure(GPIO_PD0_SSI1CLK);

    I find that "MAP_***" is macro expansion, what mean is it if no "MAP_" in front

    Regards,

    Lung Tat Ng

  • Hello Lung Tat Ng

    Did you add the pin_map.h file to the include. The Error means that either that is missing or the Define PART_TM4C123GH6PM is missing in the pre-processor define of the build settings,

    Regards

    Amit

  • Hi,

    I try to run setting DAC via SSI1, the program is as follow:

    MAP_SSIConfigSetExpClk(SSI1_BASE, MAP_SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,
    SSI_MODE_MASTER, 1000000, 12); //SSI_MODE_MASTER, 1000000, 8)

    //
    // Enable the SSI1 module.
    //
    MAP_SSIEnable(SSI1_BASE);

    //Disable DAC8164 internal Vref, use external Vref=3v
    MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_1, 0); //SYNC=L
    for(j=0;j<2;j++) {
    MAP_SSIDataPut(SSI1_BASE, disDACintnalVrf[j]); //Write DAC
    while (!(SSI_O_CR1 & SSI_CR1_EOT)); //wait SSI1 Tx buffer empty
    }
    MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_1, GPIO_PIN_1); //SYNC=H

    //Set all DAC8164 output channel to 1v
    MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_1, 0); //DAC7565 SYNC=L
    for(j=0;j<2;j++) {
    MAP_SSIDataPut(SSI1_BASE, allDACchannel[j]); //Write DAC
    while (!(SSI_O_CR1 & SSI_CR1_EOT)); //wait SSI1 Tx buffer empty
    }
    MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_1, GPIO_PIN_1); //SYNC=H
    //End of SSI test

    Compilation passed.

    But debugging hang in while() command, I guess I haven't explain SSI1 control register 1 correctly.

    Can you give a help?

    Thanks and regards,

    Lung Tat Ng

  • Hello Lung Tat,

    The while loop should have been

    while(!(HWREG(SSI1_BASE+SSI_O_CR1) && SSI_CR1_EOT))

    Regards

    Amit

  • Hi Amit,

    Compiling the program after modify while(), the error is "undefined HWRE."

    The information is as above.

    Best regards,

    Lung Tat Ng

  • Hello Lung Tat

    You would have missed the following include

    #include "inc/hw_types.h"

    Also zip and attach your project as it would be easier for us to correct it at my end.


    Regards

    Amit

  • lung tat ng said:

    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
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2);

    This - (your code @ post (01:48)) - long after Amit had advised (and you acknowledged) use of a GPIO to meet your "special" SPIFSS requirements. 

    Attention to such detail is required - endless (imprecise) code dumps blur the eyes (and perhaps more importantly - the mind!)

  • Hi Amit,

    Talking above example,  without "MAP_" prefix, "undefined symbol" appear when <Linking> is running.

    My "include setting" is as below picture

    And I also set "Predefined symbols" is as below

    I don't understand why CCS cannot find those symbols.

    The example project is attached as below.

    1376.SPIm.rar

    Thanks and regards,

    Lung Tat Ng

  • Hello Lung Tat,

    I resolved the issues as followes

    1. I updated the TIVAWare version to 2.1.0-12573 as I do not have TIVWare 1.1 version

    2. The driverlib.lib mapping was missing in the Linker Options

    3. The uartstdio.c and .h from utils was missing for UARTStdioConfig function

    4. The GPIOAIntHandler, Timer0AIntHandler and Timer0BIntHandler were not defined any where but were being used in the startup_ccs.c. So I have replaced them with IntDefaultHandler

    6131.SPIm.7z

    Regards

    Amit

  • Hi cb1_mobile,

    The SSI full function pin is as you said, but the unused pin function can be changed to normal GPIO pin if you want.

    Actually I want to say that these ICs are TI's products, why MCU(support 32 bit) SPI port don't design their hardware  to support itself DAC ICs(SPI data 24 bit), but using software to meet DAC ICs waveform. The SPI data bit length is 16 bit maximum in current MCU.

    Best regards,

    Lung Tat Ng

  • Hi Amit,

    Using your sent back files, I change the include path back to TivaWare 1.1, but the compilation result same as previous, 

    Can you send me your compile result, I think I can update my Tiva ware to 2.1.0 if new version can solve these  "undefined symbol" problem.

    Thanks and regards,

    Lung Tat Ng

  • Hello Lung Tat,

    Attached is the compilation log

    5875.compile.log
    **** Build of configuration Debug for project SPIm ****
    
    "C:\\ti\\ccsv5\\utils\\bin\\gmake" -k all 
    'Building file: ../main.c'
    'Invoking: ARM Compiler'
    "C:/ti/ccsv5/tools/compiler/arm_5.1.1/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 --abi=eabi -me -g --include_path="C:/ti/ccsv5/tools/compiler/arm_5.1.1/include" --include_path="C:/ti/ccsv5/tools/compiler/arm_5.0.4/include" --include_path="C:/ti/TivaWare_C_Series-2.1.0.12573" --define=ccs="ccs" --define=PART_TM4C123GH6PZ --define=TARGET_IS_BLIZZARD_RB1 --diag_warning=225 --display_error_number --diag_wrap=off --preproc_with_compile --preproc_dependency="main.pp"  "../main.c"
    'Finished building: ../main.c'
    ' '
    'Building file: ../startup_ccs.c'
    'Invoking: ARM Compiler'
    "C:/ti/ccsv5/tools/compiler/arm_5.1.1/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 --abi=eabi -me -g --include_path="C:/ti/ccsv5/tools/compiler/arm_5.1.1/include" --include_path="C:/ti/ccsv5/tools/compiler/arm_5.0.4/include" --include_path="C:/ti/TivaWare_C_Series-2.1.0.12573" --define=ccs="ccs" --define=PART_TM4C123GH6PZ --define=TARGET_IS_BLIZZARD_RB1 --diag_warning=225 --display_error_number --diag_wrap=off --preproc_with_compile --preproc_dependency="startup_ccs.pp"  "../startup_ccs.c"
    'Finished building: ../startup_ccs.c'
    ' '
    'Building file: ../uartstdio.c'
    'Invoking: ARM Compiler'
    "C:/ti/ccsv5/tools/compiler/arm_5.1.1/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 --abi=eabi -me -g --include_path="C:/ti/ccsv5/tools/compiler/arm_5.1.1/include" --include_path="C:/ti/ccsv5/tools/compiler/arm_5.0.4/include" --include_path="C:/ti/TivaWare_C_Series-2.1.0.12573" --define=ccs="ccs" --define=PART_TM4C123GH6PZ --define=TARGET_IS_BLIZZARD_RB1 --diag_warning=225 --display_error_number --diag_wrap=off --preproc_with_compile --preproc_dependency="uartstdio.pp"  "../uartstdio.c"
    'Finished building: ../uartstdio.c'
    ' '
    'Building target: SPIm.out'
    'Invoking: ARM Linker'
    "C:/ti/ccsv5/tools/compiler/arm_5.1.1/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 --abi=eabi -me -g --define=ccs="ccs" --define=PART_TM4C123GH6PZ --define=TARGET_IS_BLIZZARD_RB1 --diag_warning=225 --display_error_number --diag_wrap=off -z --stack_size=512 -m"SPIm.map" --heap_size=0 -i"C:/ti/ccsv5/tools/compiler/arm_5.1.1/lib" -i"C:/ti/ccsv5/tools/compiler/arm_5.1.1/include" --reread_libs --warn_sections --display_error_number --diag_wrap=off --xml_link_info="SPIm_linkInfo.xml" --rom_model -o "SPIm.out"  "./uartstdio.obj" "./startup_ccs.obj" "./main.obj" "../tm4c123gh6pz.cmd" -l"libc.a" -l"C:\ti\TivaWare_C_Series-2.1.0.12573\driverlib\ccs\Debug\driverlib.lib" 
    <Linking>
    'Finished building target: SPIm.out'
    ' '
    
    **** Build Finished ****
    

    What is missing is the following in Linker

    Regards

    Amit

  • Hi Amit,

    I've tried yet, version 1.1 can not add any folder in this manual.

    Do you have any idea to solve it except update version.

    Thanks and regards,

    Lung Tat Ng

  • Hello Lung Tat,

    It is not a folder but a file that needs to be added. replace the driverlib.lib with the equivalent driverlib.lib in the same path for TIVAWare 1.1

    Regards

    Amit

  • Hi Amit,

    The "undefined symbol" spent my long time. These problems almost solved after install TivaWare 2.1.0..

    Here share my SPI communication waveform if you interest.

    1. using  "while(!(HWREG(SSI1_BASE+SSI_O_CR1) && SSI_CR1_EOT));"

    The EOT has not show the Tx ending correctly.

    2. Change to "while (SSIBusy(SSI1_BASE));"

    The waveform meet the requirement.

    Best regards,

    Lung Tat Ng

  • Hello Lung Tat,

    That is good news that you have it working.

    For the EOT waveform was the SSICR1.EOT bit set?

    Regards

    Amit

  • Hi Amit,

    Yes, the instruction is:

    while(!(HWREG(SSI1_BASE+SSI_O_CR1) && SSI_CR1_EOT));

    Now I need make the clock phase shift, setting SPH=1 in SSI1_CR0 , but I don't know which command  can do it.

    Please give a help.

    Thanks and regards,

    Lung Tat Ng

  • Hello Lung Tat,

    The while loop is wrong in programming model. It should be

    HWREG(SSI1_BASE+SSI_O_CR1) |= SSI_CR1_EOT;

    So that the TX interrupt becomes EOT interrupt

    You can attach the updated code so that we can review it and send back any comments.

    To use SPH=1 you would have to use SSI_FRF_MOTO_MODE_3 or SSI_FRF_MOTO_MODE_1

    Regards

    Amit

  • lung tat ng said:

    Please give a help.

    Suspect that even casual glance @, "Facts in Evidence" - this thread - reveals, "Quite a Help" has long (since) been delivered!