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.

TM4C1294NCPDT: I2C Communication protocol development

Part Number: TM4C1294NCPDT

Hi All, 

I'm trying to develop I2C protocol using TM4C1294NCPDT with PORT B and I2C0. I'm facing difficulties in sending a character byte through the SDA bus. Could you please have a look at the code snippet and give me more suggestion or advice in the application development. 


#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "MAX6955.h"
#include "display_task.h"



#define SLAVEADDRESS 0xCA


void I2CSendChar(uint8_t slavedeviceAddress,uint8_t deviceRegister, uint8_t deviceData)
{
    I2CMasterSlaveAddrSet(I2C0_BASE, slavedeviceAddress, false);
    I2CMasterDataPut(I2C0_BASE, deviceRegister);

    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);

    while(I2CMasterBusy(I2C0_BASE));


    I2CMasterDataPut(I2C0_BASE, deviceData);

    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);


    while(I2CMasterBusy(I2C0_BASE));

}

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

int
main(void)
{

    uint32_t ui32SysClock;

    // Set the clocking to run directly from the external crystal/oscillator.


    ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                       SYSCTL_OSC_MAIN |
                                       SYSCTL_USE_OSC), 25000000);



    // The I2C0 peripheral must be enabled before use.

    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);


    // GPIO port B needs to be enabled so these pins can

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    GPIOPinConfigure(GPIO_PB2_I2C0SCL);
    GPIOPinConfigure(GPIO_PB3_I2C0SDA);

    // GPIO pins pins for I2C operation, setting them to
    // open-drain operation with weak pull-ups.
    //
    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);

        I2CMasterEnable(I2C0_BASE);
    HWREG(I2C0_BASE + I2C_O_MCR) |= 0x10;
    //
    // Enable and initialize the I2C0 master module.  Use the system clock for
    // the I2C0 module.  The last parameter sets the I2C data transfer rate.
    // If false the data rate is set to 100kbps and if true the data rate will
    // be set to 400kbps.  For this example we will use a data rate of 100kbps.
    //

    I2CMasterInitExpClk(I2C0_BASE, ui32SysClock, false);



    InitConsole();
    //
    I2CMasterSlaveAddrSet(I2C0_BASE, SLAVEADDRESS, false);
    UARTprintf("The slave address: %X\n", SLAVEADDRESS);


   // initMAX6955();



while(1){

    I2CSendChar(SLAVEADDRESS, reg_digit0, 0x4D);
    I2CSendChar(SLAVEADDRESS, reg_digit1, 0x41);
    I2CSendChar(SLAVEADDRESS, reg_digit2, 0x58);
    I2CSendChar(SLAVEADDRESS, reg_digit3, 0x49);
    I2CSendChar(SLAVEADDRESS, reg_digit4, 0x4D);
    I2CSendChar(SLAVEADDRESS, reg_digit5, 0x2D);
    I2CSendChar(SLAVEADDRESS, reg_digit4, 0x49);
    I2CSendChar(SLAVEADDRESS, reg_digit5, 0x43);
  


}
}

Thanks and Regards,

Sai Santha

  • Hi,

      The first thing I spot is probably an incorrect slave address. For I2C protocol the slave address is 7-bit. You do not left-shift by a bit when you call the I2CMasterSlaveAddrSet. 

    In your code you set the SLAVEADDRESS to 0xCA which is already left-shifted by a bit. I think this is wrong. If you look at the I2C device datasheet the upper three bits (A6-A4)  is 110. This means the slave address should be 0x6X where X is whatever you configure on the AD1 and AD0. Tis is the first thing to address. You should also use a logic analyzer or scope to see what is going on the bus. Probe the SDA and SCL pins. If the master is sending out the slave address but no no one acknowledges then it means the slave address is not recognized by any devices on the bus. Make sure you have proper pullup resistor on the SDA and SCL buses or it won't work. 

  • Dear Charles, 

    Yes, That's right. However, I'm currently using MAX6955 Evaluation KIT. Please find the attached picture for the reference. 

    For Evaluation board the device address for write is 0xCA and for read is 0xCB. 

    Thanks and Regards,
    Sai Santha

    8587641805

  • Hi,

     I understand you are using MAX6955. I use the attached datasheet for reference. 

    https://datasheets.maximintegrated.com/en/ds/MAX6955.pdf

      So what is unclear to you? You pick the below slave address, don't you? What is the address? It is 1100101b or 0x65, isn't? This is 7 bit address. When the master sends the slave address out, it will append the R/W bit. If you are writing then the Address+R/W becomes 11001010 or 0xCA. Please refer to my reply earlier again. You DO NOT left-shift the bit when you call I2CMasterSlaveAddrSet. Look at the scope output and see what it is outputting. 

  • Dear Charles, 

     

    Please have a look at table below. I hope, this might be the device address. Could you please cross verify it? 

     

     

    Thanks,
    Sai Santha

  • Hi,

      Again, what is shown is after the R/W bit is added, isn't. This is why there is a 0xCA under the Write column and 0xCB under the Read column. This means the R/W bit which is the 8th bit is added. The slave address by itself is 0x65, isn't? If you still have doubt, I suggest you simply use the scope the capture the SDA bus. 

      If you want to write then you do I2CMasterSlaveAddrSet(I2C0_BASE, 0x65, false);

  • Dear Charles, 

    Thank you so much for correcting me the difference between 0x65 and 0xCA in the SLAVEADDRESS or DEVICEADDRESS. 

    Yes, You're right. 

    0xCA (0b11001010)with total of  8-bits. 

    0x65(0b1100101) with total of 7-bits without the 8-bit.  

    However, I'm unable to display any digit in the Digit from Digit 0 to Digit 7. 

    Please go through my code snippet and let me know. 

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_i2c.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/i2c.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    
    
    #define SLAVEADDRESS 0x65
    
    #define reg_noOp 0x00
    #define reg_decodeMode 0x01
    #define reg_globalIntensity 0x02
    #define reg_scanLimit 0x03
    #define reg_controlRegister 0x04
    #define reg_displayTest 0x07
    #define reg_digitType 0x0C
    #define reg_intensity10 0x10
    #define reg_internsity32 0x11
    #define reg_internsity54 0x12
    #define reg_internsity76 0x13
    
    
    
    #define USE_GLOBAL 0x00
    #define USE_DISCRETE 0x40
    #define RUN 0x02
    #define SHUTDOWN 0x00
    
    
    
    
    //extern int write(char command, int data);
    
    //extern int writeString(char* buffer);
    
    
    #define reg_digit0 0x20
    #define reg_digit1 0x21
    #define reg_digit2 0x22
    #define reg_digit3 0x23
    #define reg_digit4 0x24
    #define reg_digit5 0x25
    #define reg_digit6 0x26
    #define reg_digit7 0x27
    
    
    uint32_t ui32SysClock;
    
    void I2CSendChar(uint8_t deviceRegister, uint8_t deviceData)
    {
        I2CMasterDataPut(I2C0_BASE, deviceRegister);
    
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    
        while(I2CMasterBusy(I2C0_BASE));
    
    
        I2CMasterDataPut(I2C0_BASE, deviceData);
    
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    
    
        while(I2CMasterBusy(I2C0_BASE));
    
    }
    
    void initMAX6955(void){
    
    
    UARTprintf("MAX6955 Initialization starts....\n");
    I2CSendChar( reg_decodeMode, 0xFF);
    I2CSendChar(reg_globalIntensity, 0x08);
    UARTprintf("The slave address: %X\t register_decode: %X\t data: %X\n", SLAVEADDRESS, reg_decodeMode, 0x00);
    I2CSendChar( reg_scanLimit, 0x07);
    I2CSendChar( reg_controlRegister, 0x01);
    
    I2CSendChar(reg_displayTest, 0x00);
    I2CSendChar( reg_digitType, 0xFF);
    
    UARTprintf("MAX6955 Initialization Ends.\n");
    }
    
    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);
    }
    
    int
    main(void)
    {
    
    
    
        // PLL clock 120MHz.
    
    
        ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_240), 120000000);
    
    
    
        // The I2C0 peripheral must be enabled before use.
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
    
    
        // GPIO port B needs to be enabled so these pins can
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    
        GPIOPinConfigure(GPIO_PB2_I2C0SCL);
        GPIOPinConfigure(GPIO_PB3_I2C0SDA);
    
        // GPIO pins pins for I2C operation, setting them to
        // open-drain operation with weak pull-ups.
        //
        GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
        GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
    
            I2CMasterEnable(I2C0_BASE);
        HWREG(I2C0_BASE + I2C_O_MCR) |= 0x10;
        //
        // Enable and initialize the I2C0 master module.  Use the system clock for
        // the I2C0 module.  The last parameter sets the I2C data transfer rate.
        // If false the data rate is set to 100kbps and if true the data rate will
        // be set to 400kbps.  For this example we will use a data rate of 100kbps.
        //
    
        I2CMasterInitExpClk(I2C0_BASE, ui32SysClock, false);
    
    
    
        InitConsole();
        //
        I2CMasterSlaveAddrSet(I2C0_BASE, SLAVEADDRESS, false);
        UARTprintf("The slave address: %X\n", SLAVEADDRESS);
    
    
        initMAX6955();
    
    
    
    while(1){
    
        I2CSendChar(reg_digit0, 0x4D);
        I2CSendChar( reg_digit1, 0x41);
        I2CSendChar( reg_digit2, 0x58);
        I2CSendChar( reg_digit3, 0x49);
        I2CSendChar( reg_digit4, 0x4D);
        I2CSendChar( reg_digit5, 0x2D);
        I2CSendChar(reg_digit4, 0x49);
        I2CSendChar(reg_digit5, 0x43);
    
    
    
        }
    }
    

    Thanks

    Sai Santha

  • Hi Sai,

      Glad that you are making some progress. Please refer to this I2C app note on how to use the I2C API command. https://www.ti.com/jp/lit/an/spma073/spma073.pdf

    I have some comments on your code.

     -  In your I2CSendChar() function, you call the I2C_MASTER_CMD_BURST_SEND_START followed by I2C_MASTER_CMD_BURST_SEND_CONT. But you never release the bus with I2C_MASTER_CMD_BURST_SEND_FINISH. Could this be a problem to the MAX6955? Whether you are sending one data byte or N data bytes, you must eventually end with a STOP bit. You need to refer to the MAX6955 datasheet. I can only provide guidance on the TM4C MCU, not the MAX6955 as I'm not an expert of this third-party product. 

    You haven't answered me if you have a scope capture of the I2C. Just telling me you cannot display any digit doesn't really help me much. I don't have the MAX6955 to verify what is going on. If you provide additional information like where in the code the processor is doing will be helpful. As I mentioned, the most important thing is to look at the scope and see if the slave is acknowledging or not-acknowledge the command from the master. Therefore, the scope cap will be very helpful. 

  • Hi Charles, 

    I was able to capture the I2C SCL and SDA data in Oscilloscope. Please find the below attachment. 

    Yes, After setting the Slave Address in write mode. I want to initialize the data register for MAX6955 though SDA and 

    Finally, I want to write Alphanumeric values in each digit  from Digit 0 to Digit 8. 

    Thanks,

    Sai Santha

  • Hello,

      I can't decipher what you are showing. You need to show a full picture. Show from the beginning of a clock where the START bit starts. Perhaps you can put a breakpoint in your code so the slave address is first put out. Don't just show something in the middle of a transaction. 

  • Hi Charles,

    Please find the the snippet image for the verifying and the suggestion. 

    As you can see that. I was able to writer the slave address right. However, I can't right any data in the SDA bus. Could you please give me a insight for troubleshooting? 

    Thank,

    Sai Santha

  • Hi Sai,

      Do you have logic analyzer? As I mentioned several times, it will be a very handy tool to debug your system if you have a logic analyzer. Scope capture is fine but you must show the full picture from START. You cannot just show me a capture taken in the middle of a transaction. How will I know what that transaction correspond to your code? The MDA register will show zero. That is the way the I2C works. The data is written to the MDR but you read the register, it will show zero. This does not mean the MDR register is not written. Let me repeat again and please follow the instructions.

      1. Do you even have pull up resistors on the SCL and SDA? Please confirm. This is the requirement for I2C operation.

       2. Have either a logic analyzer (preferably) or scope capture of the SCL and SDA showing from the beginning of the START bit. Show the complete Slave Address command byte and the subsequent data bytes

      3. Do one transaction at a time. For example, put a breakpoint at the beginning of the second line shown below. We don't need to see all the data you send. We just need to see the very data transaction when you write to the reg_digit0 the first time. Don't put it in a while loop. When you put things in the while loop you just keep sending bunch of data that is more difficult to debug. 

        I2CSendChar(reg_digit0, 0x4D);
        I2CSendChar( reg_digit1, 0x41); // put breakpoint on this line so you will capture the write data to the reg_digit0 only.
      4. This comment I already gave you before. I'm just repeating. You must study the MAX6955 datasheet and understand its requirement. I said in the prior response.  
        "In your I2CSendChar() function, you call the I2C_MASTER_CMD_BURST_SEND_START followed by I2C_MASTER_CMD_BURST_SEND_CONT. But you never release the bus with I2C_MASTER_CMD_BURST_SEND_FINISH. Could this be a problem to the MAX6955? Whether you are sending one data byte or N data bytes, you must eventually end with a STOP bit. You need to refer to the MAX6955 datasheet. I can only provide guidance on the TM4C MCU, not the MAX6955 as I'm not an expert of this third-party product. "
  • Hi Charles, 

    Answers to your questions as follow.

    1) Yes, I do have external pull-up resistors each of them of 4.7K Ohms on SCL and SDA lines. 

    2) Yes, I understand that I2C protocol Start bit followed by slave address and a byte with stop bit. I have rewritten my I2C transaction function as mentioned in the below. 

    void writeI2C0(uint8_t slaveaddress, uint8_t device_register, uint8_t device_data)          // send a transaction. 
    {

    I2CMasterSlaveAddrSet(I2C0_BASE, slaveaddress, false);
    I2CMasterDataPut(I2C0_BASE, device_register);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    while(I2CMasterBusy(I2C0_BASE));
    I2CMasterDataPut(I2C0_BASE, device_data);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
    while(I2CMasterBusy(I2C0_BASE));
    }

    void initMAX6955(void)                // initializing the MAX6955
    {
    I2CMasterSlaveAddrSet(I2C0_BASE, SLAVEADDRESS_EXT, false);
    I2CMasterDataPut(I2C0_BASE, reg_decodeMode);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    while(I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, 0xFF);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, reg_globalIntensity);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, 0x07);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, reg_scanLimit);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, 0x07);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, reg_controlRegister);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, 0x01);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, reg_digitType);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, 0xFF);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, reg_displayTest);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, 0x00);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
    while(I2CMasterBusy(I2C0_BASE));
    }

    3) please find the two attached images for the reference. 

    Thanks,

    Sai Santha

  • A couple of questions:

    1. Which function ( writeI2C0 or initMAX6955) did you call that corresponds to the attached waveform? The waveform shows you are writing to slave address (0x65) followed by a data of value of 0x41. The device is acknowledging the command. So it looks like the MCU is sending the correct command. What are the values of device_register, device_data and reg_decodeMode and etc? You only show snippet of the code. I can't tell if the waveform is for the writeI2C0 or initMAX6955? Can you show the complete program?

    2. Where is the second image? I only see one attached image?

    3. Based on the first image, both the command (the slave address byte) and the data byte are both acknowledged by the device. What happens to the MAX6955 after you write to it. At least from the first image everything is correct from the MCU side. If you are not getting the digit displayed I think you will need to consult with the MAX6955 vendor or you want to go through their datasheet to check if you are generating the correct data byte sequence. 

  • Dear Charles, 

    please  find the entire program for the application development. 

    #include <stdbool.h>
    #include <stdint.h>
    #include <stdarg.h>
    #include "inc/hw_i2c.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "driverlib/gpio.h"
    #include "driverlib/i2c.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "driverlib/gpio.h"
    
    
    #define SLAVEADDRESS_EXT 0x65
    
    #define reg_noOp 0x00
    #define reg_decodeMode 0x01
    #define reg_globalIntensity 0x02
    #define reg_scanLimit 0x03
    #define reg_controlRegister 0x04
    #define reg_displayTest 0x07
    #define reg_digitType 0x0C
    #define reg_intensity10 0x10
    #define reg_internsity32 0x11
    #define reg_internsity54 0x12
    #define reg_internsity76 0x13
    
    #define USE_GLOBAL 0x00
    #define USE_DISCRETE 0x40
    #define RUN 0x02
    #define SHUTDOWN 0x00
    
    
    #define reg_digit0 0x20
    #define reg_digit1 0x21
    #define reg_digit2 0x22
    #define reg_digit3 0x23
    #define reg_digit4 0x24
    #define reg_digit5 0x25
    #define reg_digit6 0x26
    #define reg_digit7 0x27
    
    
    uint32_t ui32SysClock;
    
    
    void writeI2C0(uint8_t slaveaddress, uint8_t device_register, uint8_t device_data)
    {
    
        I2CMasterSlaveAddrSet(I2C0_BASE, slaveaddress, false);
       I2CMasterDataPut(I2C0_BASE, device_register);
       I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
       while(I2CMasterBusy(I2C0_BASE));
       I2CMasterDataPut(I2C0_BASE, device_data);
       I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
       while(I2CMasterBusy(I2C0_BASE));
    }
    
    void initMAX6955(void)
    {
        I2CMasterSlaveAddrSet(I2C0_BASE, SLAVEADDRESS_EXT, false);
        I2CMasterDataPut(I2C0_BASE, reg_decodeMode);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, 0xFF);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, reg_globalIntensity);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, 0x07);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, reg_scanLimit);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, 0x07);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, reg_controlRegister);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, 0x01);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, reg_digitType);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, 0xFF);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, reg_displayTest);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, 0x00);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
        while(I2CMasterBusy(I2C0_BASE));
    }
    
    
    void
    InitConsole(void)
    {
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        UARTStdioConfig(0, 115200, 16000000);
    }
    
    int main(void)
    {
    
        ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_240), 120000000);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C0));
        GPIOPinConfigure(GPIO_PB2_I2C0SCL);
        GPIOPinConfigure(GPIO_PB3_I2C0SDA);
        GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
        GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
        I2CMasterEnable(I2C0_BASE);
        I2CMasterInitExpClk(I2C0_BASE, ui32SysClock, false);
        IntEnable(INT_I2C0);
        I2CMasterEnable(I2C0_BASE);
        InitConsole();
    
        UARTprintf("The slave address: %X\n", SLAVEADDRESS_EXT);
        IntMasterEnable();
    
    
    
        initMAX6955();
    
    
    
    
    
    
        writeI2C0( SLAVEADDRESS_EXT,  reg_digit0, 0x41);
    
    
    
    }

    1) I have to initialize before writing to the digits from digit 0 to digit 7. 

    2) on each transaction of the data through I2C consists of   StartBit-SlaveAddress(7-bits)-WriteBit-CommandByte(8-bits)- DataByte(8-bits)-StopBit. 

    For initializing, I have used the initMAX6955() function and writing each digit would be calling the writeI2C0(Slaveaddress, deviceRegister, data) finction. 

    Thanks,
    Sai 

  • HI,

      Can you in every place where you have the while(I2CMasterBusy(I2C0_BASE)) and replace with the the below?  Does it make a difference? The reason is that the writeI2C0( SLAVEADDRESS_EXT,  reg_digit0, 0x41) is supposed to put out the reg_digit0=0x20 followed by 0x41 but I don't see the 0x20 in your scope capture. I only see the 0x41 immediately follow the slave address byte. 

    From:

     while(I2CMasterBusy(I2C0_BASE));

    To:

     while(!I2CMasterBusy(I2C0_BASE)); // Add this line before the below line to the entire program. 

     while(I2CMasterBusy(I2C0_BASE));

     

  • Hi Charles,

    Yes, You're right. I have been debugging to check the command byte in the scope. I see the command byte in the scope 0x20 is missing.  What would be the better approach to troubleshoot. 

    I have modified the code as you recommended but the scope is still the same. 

    I can view the Slave_Address and data byte in the scope but not the command byte.

    Is there any alternative to modify the code?

    Thanks,
    Sai Santha 

  • Hi,

      Can you show me your modified code (the complete program)?

  • Hi Charles,


    #include <stdbool.h>
    #include <stdint.h>
    #include <stdarg.h>
    #include "inc/hw_i2c.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "driverlib/gpio.h"
    #include "driverlib/i2c.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "driverlib/gpio.h"


    #define SLAVEADDRESS_EXT 0x65
    #define NUM_OF_I2CBYTES 255

    #define reg_noOp 0x00
    #define reg_decodeMode 0x01
    #define reg_globalIntensity 0x02
    #define reg_scanLimit 0x03
    #define reg_controlRegister 0x04
    #define reg_displayTest 0x07
    #define reg_digitType 0x0C
    #define reg_intensity10 0x10
    #define reg_internsity32 0x11
    #define reg_internsity54 0x12
    #define reg_internsity76 0x13

    #define USE_GLOBAL 0x00
    #define USE_DISCRETE 0x40
    #define RUN 0x02
    #define SHUTDOWN 0x00


    #define reg_digit0 0x20
    #define reg_digit1 0x21
    #define reg_digit2 0x22
    #define reg_digit3 0x23
    #define reg_digit4 0x24
    #define reg_digit5 0x25
    #define reg_digit6 0x26
    #define reg_digit7 0x27


    uint32_t ui32SysClock;


    void writeI2C0(uint8_t slaveaddress, uint8_t device_register, uint8_t device_data)
    {

    I2CMasterSlaveAddrSet(I2C0_BASE, slaveaddress, false);
    I2CMasterDataPut(I2C0_BASE, device_register);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    while(!I2CMasterBusy(I2C0_BASE));
    I2CMasterDataPut(I2C0_BASE, device_data);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
    while(!I2CMasterBusy(I2C0_BASE));
    }

    void initMAX6955(void)
    {
    I2CMasterSlaveAddrSet(I2C0_BASE, SLAVEADDRESS_EXT, false);
    I2CMasterDataPut(I2C0_BASE, reg_decodeMode);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    while(!I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, 0xFF);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(!I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, reg_globalIntensity);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(!I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, 0x07);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(!I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, reg_scanLimit);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(!I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, 0x07);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(!I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, reg_controlRegister);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(!I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, 0x01);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(!I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, reg_displayTest);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(!I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, 0x00);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(!I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, reg_digitType);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(!I2CMasterBusy(I2C0_BASE));

    I2CMasterDataPut(I2C0_BASE, 0xFF);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
    while(!I2CMasterBusy(I2C0_BASE));
    }


    int main(void)
    {

    ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_240), 120000000);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    GPIOPinConfigure(GPIO_PB2_I2C0SCL);
    GPIOPinConfigure(GPIO_PB3_I2C0SDA);
    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
    I2CMasterEnable(I2C0_BASE);
    I2CMasterInitExpClk(I2C0_BASE, ui32SysClock, false);
    IntEnable(INT_I2C0);
    I2CMasterEnable(I2C0_BASE);
    IntMasterEnable();
    initMAX6955();


    while(1){
    writeI2C0(SLAVEADDRESS_EXT, reg_digit0, 0x41);
    }

    }

    Regards,

    Sai 

  • No, you mistaken what I said. I said:

    From:

     while(I2CMasterBusy(I2C0_BASE));

    To:

     while(!I2CMasterBusy(I2C0_BASE)); // Add this line before the below line to the entire program. 

     while(I2CMasterBusy(I2C0_BASE));  // You need to also keep this line

    This means like the below. 

    I2CMasterSlaveAddrSet(I2C0_BASE, slaveaddress, false);
    I2CMasterDataPut(I2C0_BASE, device_register);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    while(!I2CMasterBusy(I2C0_BASE)); // Add this line

    while(I2CMasterBusy(I2C0_BASE)); // And also  keep this line

    I2CMasterDataPut(I2C0_BASE, device_data);
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
    while(!I2CMasterBusy(I2C0_BASE));

  • Hi Charles, 

    I have made changes as you recommended. please find the attached image for the reference. 

    #include <stdbool.h>
    #include <stdint.h>
    #include <stdarg.h>
    #include "inc/hw_i2c.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "driverlib/gpio.h"
    #include "driverlib/i2c.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "driverlib/gpio.h"
    
    
    #define SLAVEADDRESS_EXT 0x65
    #define NUM_OF_I2CBYTES 255
    
    #define reg_noOp 0x00
    #define reg_decodeMode 0x01
    #define reg_globalIntensity 0x02
    #define reg_scanLimit 0x03
    #define reg_controlRegister 0x04
    #define reg_displayTest 0x07
    #define reg_digitType 0x0C
    #define reg_intensity10 0x10
    #define reg_internsity32 0x11
    #define reg_internsity54 0x12
    #define reg_internsity76 0x13
    
    #define USE_GLOBAL 0x00
    #define USE_DISCRETE 0x40
    #define RUN 0x02
    #define SHUTDOWN 0x00
    
    
    #define reg_digit0 0x20
    #define reg_digit1 0x21
    #define reg_digit2 0x22
    #define reg_digit3 0x23
    #define reg_digit4 0x24
    #define reg_digit5 0x25
    #define reg_digit6 0x26
    #define reg_digit7 0x27
    
    
    uint32_t ui32SysClock;
    
    
    void writeI2C0(uint8_t slaveaddress, uint8_t device_register, uint8_t device_data)
    {
    
        I2CMasterSlaveAddrSet(I2C0_BASE, slaveaddress, false);
       I2CMasterDataPut(I2C0_BASE, device_register);
       I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
       while(!I2CMasterBusy(I2C0_BASE));
       while(I2CMasterBusy(I2C0_BASE));
       I2CMasterDataPut(I2C0_BASE, device_data);
       I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
       while(!I2CMasterBusy(I2C0_BASE));
       while(I2CMasterBusy(I2C0_BASE));
    }
    
    void initMAX6955(void)
    {
        I2CMasterSlaveAddrSet(I2C0_BASE, SLAVEADDRESS_EXT, false);
        I2CMasterDataPut(I2C0_BASE, reg_decodeMode);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
        while(!I2CMasterBusy(I2C0_BASE));
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, 0xFF);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(!I2CMasterBusy(I2C0_BASE));
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, reg_globalIntensity);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(!I2CMasterBusy(I2C0_BASE));
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, 0x07);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(!I2CMasterBusy(I2C0_BASE));
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, reg_scanLimit);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(!I2CMasterBusy(I2C0_BASE));
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, 0x07);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(!I2CMasterBusy(I2C0_BASE));
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, reg_controlRegister);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(!I2CMasterBusy(I2C0_BASE));
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, 0x01);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(!I2CMasterBusy(I2C0_BASE));
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, reg_displayTest);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(!I2CMasterBusy(I2C0_BASE));
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, 0x00);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(!I2CMasterBusy(I2C0_BASE));
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, reg_digitType);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
        while(!I2CMasterBusy(I2C0_BASE));
        while(I2CMasterBusy(I2C0_BASE));
    
        I2CMasterDataPut(I2C0_BASE, 0xFF);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
        while(!I2CMasterBusy(I2C0_BASE));
        while(I2CMasterBusy(I2C0_BASE));
    }
    
    
    int main(void)
    {
    
        ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_240), 120000000);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
        GPIOPinConfigure(GPIO_PB2_I2C0SCL);
        GPIOPinConfigure(GPIO_PB3_I2C0SDA);
        GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
        GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
        I2CMasterEnable(I2C0_BASE);
        I2CMasterInitExpClk(I2C0_BASE, ui32SysClock, false);
        IntEnable(INT_I2C0);
        I2CMasterEnable(I2C0_BASE);
        IntMasterEnable();
        initMAX6955();
    
    
    while(1){
        writeI2C0(SLAVEADDRESS_EXT, reg_digit0, 0x40);
            }
    
    }
    
    
    
    
    
    
    
    
    

  • Hi Charles, 

    As you can see above scope, The slaveAddress and data Byte are present. However, the command Byte is missing. 

    Its seems like slaveAddress and data Byte for a single transaction. Again, New dataByte is transferred without the slaveAddress. 

    Can you give me some insight for debugging? 

    Regards,
    Sai Santha

  • Can you zoom in on the area shown below. I think it is a 0x65->W->0x20->0x41. What I cannot tell from the image is after the 0x20, are you getting a NACK or not? The image is too small. As I recommended before, if you have a logic analyzer it will become so much easier. If the MAX6955 is replying NACK then you need to find out from the MAX6955. 

  • I think you scope cap shows it is putting out Start->0x65->W->0x20->0x41->Stop now. What happens to the MAX6955?

  • Hi Charles, 

    I just want to decode the pattern Start ->0x65->W->0x20->0x40->Stop. In this case, MAX6955 should show '@'

    Start ->0x65->W->0x20->0x41->Stop. In this case, MAX6955 should shows 'A'. 

    Thanks,
    Sai 

  • Hi,

      So what do you see on the MAX6955? The MCU is driving the correct Start ->0x65->W->0x20->0x41->Stop on the scope, as far as I can tell. If there is still issue, then it is probably not related to MCU. You will need to investigate on your own. I'm not familiar with the MAX6955 to know what is the correct command sequence to display the different digits. 

      I will suggest you put breakpoint to debug the system as I mentioned several times. Either single step or put breakpoint as you go through the initMAX6955(). Examine the scope capture and check if you are generating the correct initialization commands.