PSoC4S MAX : How to use ”Cy_SCB_I2C_MasterSendStart()" API

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
MiNe_85951
Level 7
Level 7
Distributor - TED (Japan)
50 likes received 500 replies posted 50 solutions authored

Dear Sirs and Madams,

 

Please tell us how to use the ”Cy_SCB_I2C_MasterSendStart()" API of I2C interface.

 

The waveform when the function "Cy_SCB_I2C_MasterWrite (CYBSP_I2C_HW, & masterTransferCfg, & CYBSP_I2C_context)" of I2C Master.c is used is as follows.
ACK has also been confirmed, and communication is successful.

MaMi_1205306_0-1657673005378.png

When We change this function Cy_SCB_I2C_MasterWrite() to Cy_SCB_I2C_MasterSendStart(), the waveform never appears and the SCL is fixed at 'L'.

 

API that is working normally before the change:

Cy_SCB_I2C_MasterWrite (CYBSP_I2C_HW, & masterTransferCfg, & CYBSP_I2C_context)

 

API that does not work properly after change:

Cy_SCB_I2C_MasterSendStart(CYBSP_I2C_HW, I2C_SLAVE_ADDR, CY_SCB_I2C_WRITE_XFER, 1000000UL, &CYBSP_I2C_context)

 

MaMi_1205306_1-1657673523181.png

I configured it with reference to PDL, but is there a problem with how to use this "Cy_SCB_I2C_MasterSendStart()"API?

 

Regards,

1 Solution
PandaS
Moderator
Moderator
Moderator
250 replies posted 100 solutions authored 5 likes given

Hi @MiNe_85951 ,

I tried the above at my desk and I am able to see the output. Kindly take a look at my code example.

#include "cy_pdl.h"
#include "cybsp.h"

/* Assign pins for I2C on SCB1: P3[0] and P3[1] */
#define I2C_PORT      (P1_0_PORT)
#define I2C_SCL_NUM   (P1_0_NUM)
#define I2C_SDA_NUM   (P1_1_NUM)
#define HSIOM_SDA     (P1_1_SCB0_I2C_SDA)
#define HSIOM_SCL     (P1_0_SCB0_I2C_SCL)

/* Assign divider type and number for I2C */
#define I2C_CLK_DIV_TYPE  (CY_SYSCLK_DIV_16_BIT)
#define I2C_CLK_DIV_NUM   (0U)

/* I2C master desired data rate in Hz */
#define I2C_DESIRED_DATA_RATE_HZ    (100000U)

/* Buffer to write to the slave */
uint8_t buffer[] = {0x55, 0x44, 0x33};
/* Wait 100 ms until operation completion */
uint32_t timeout = 100UL;

int main(void)
{
    cy_rslt_t result;
	cy_en_scb_i2c_status_t status;
	uint32_t dataRate;

    /* Initialize the device and board peripherals */
    result = cybsp_init() ;
    if (result != CY_RSLT_SUCCESS)
    {
        CY_ASSERT(0);
    }

    /* Allocate context for I2C operation */
    cy_stc_scb_i2c_context_t i2cContext;

    /* Populate configuration structure */

	/* Master  configuration */
	const cy_stc_scb_i2c_config_t i2cConfig =
	{
		.i2cMode   = CY_SCB_I2C_MASTER,
		.useRxFifo = false,
		.useTxFifo = true,
		.slaveAddress     = 0U,
		.slaveAddressMask = 0U,
		.acceptAddrInFifo = false,
		.ackGeneralAddr   = false,
		.hsEnable         = false,          /* Only applicable for PSoC 4100S Max */
		.enableWakeFromSleep = false,
		.enableDigitalFilter = false,
		.lowPhaseDutyCycle = 8U,
		.highPhaseDutyCycle = 8U,
	};

    /* Configure I2C to operate */
    (void) Cy_SCB_I2C_Init(SCB0, &i2cConfig, &i2cContext);

    /* Connect SCB0 I2C function to pins */
    Cy_GPIO_SetHSIOM(I2C_PORT, I2C_SCL_NUM, HSIOM_SCL);
    Cy_GPIO_SetHSIOM(I2C_PORT, I2C_SDA_NUM, HSIOM_SDA);
    /* Configure pins for I2C operation */
    Cy_GPIO_SetDrivemode(I2C_PORT, I2C_SCL_NUM, CY_GPIO_DM_OD_DRIVESLOW);
    Cy_GPIO_SetDrivemode(I2C_PORT, I2C_SDA_NUM, CY_GPIO_DM_OD_DRIVESLOW);


    /* Connect assigned divider to be a clock source for I2C */
    Cy_SysClk_PeriphAssignDivider(PCLK_SCB0_CLOCK, I2C_CLK_DIV_TYPE, I2C_CLK_DIV_NUM);

    /* I2C master desired data rate is 100 kbps.
    * To support this data rate the clk_scb frequency must be in range 1.55 – 3.2 MHz.
    * Find clk_scb valid ranges in TRM section I2C sub-section Oversampling and Bit Rate.
    * For clk_hf = 48 MHz, select divider value 30 and get clk_scb = (48 MHz / 30) = 1.6 MHz.
    * This clock frequency meets requirements above.
    */
    Cy_SysClk_PeriphSetDivider   (I2C_CLK_DIV_TYPE, I2C_CLK_DIV_NUM, 29u);
    Cy_SysClk_PeriphEnableDivider(I2C_CLK_DIV_TYPE, I2C_CLK_DIV_NUM);
    /* Configure master to operate with desired data rate */
    dataRate = Cy_SCB_I2C_SetDataRate(SCB0, I2C_DESIRED_DATA_RATE_HZ, Cy_SysClk_PeriphGetFrequency(I2C_CLK_DIV_TYPE, I2C_CLK_DIV_NUM));
    if ((dataRate > I2C_DESIRED_DATA_RATE_HZ) || (dataRate == 0U))
    {
        /* Can not reach desired data rate */
        CY_ASSERT(0U);
    }

    /* Enable I2C to operate */
    Cy_SCB_I2C_Enable(SCB0, &i2cContext);

    /* Enable global interrupts */
    __enable_irq();

    for (;;)
    {
    	/* Send Start condition, address and receive ACK/NACK response from slave */
    	status = Cy_SCB_I2C_MasterSendStart(SCB0, 0x08U, CY_SCB_I2C_WRITE_XFER, timeout, &i2cContext);
    	if (CY_SCB_I2C_SUCCESS == status)
    	{
    	    uint32_t cnt = 0UL;
    	    /* Write data into the slave from the buffer */
    	    do
    	    {
    	        /* Write byte and receive ACK/NACK response */
    	        status = Cy_SCB_I2C_MasterWriteByte(SCB0, buffer[cnt], timeout, &i2cContext);
    	        ++cnt;
    	    }
    	    while((status == CY_SCB_I2C_SUCCESS) && (cnt < sizeof(buffer)));
    	}
    	/* Check status of transaction */
    	if ((status == CY_SCB_I2C_SUCCESS)           ||
    	    (status == CY_SCB_I2C_MASTER_MANUAL_NAK) ||
    	    (status == CY_SCB_I2C_MASTER_MANUAL_ADDR_NAK))
    	{
    	    /* Send Stop condition on the bus */
    	    status = Cy_SCB_I2C_MasterSendStop(SCB0, timeout, &i2cContext);
    	    if (status == CY_SCB_I2C_SUCCESS)
    	    {
    	        /* Data has been written into the slave */
    	    }
    	}

    	Cy_SysLib_Delay(1000);
    }
}

And the output for the code was observed as follows in the saleae logic analyser.

PandaS_0-1657705295503.png

Thank and Regards

Sobhit

View solution in original post

8 Replies
PandaS
Moderator
Moderator
Moderator
250 replies posted 100 solutions authored 5 likes given

Hi @MiNe_85951 ,

I tried the above at my desk and I am able to see the output. Kindly take a look at my code example.

#include "cy_pdl.h"
#include "cybsp.h"

/* Assign pins for I2C on SCB1: P3[0] and P3[1] */
#define I2C_PORT      (P1_0_PORT)
#define I2C_SCL_NUM   (P1_0_NUM)
#define I2C_SDA_NUM   (P1_1_NUM)
#define HSIOM_SDA     (P1_1_SCB0_I2C_SDA)
#define HSIOM_SCL     (P1_0_SCB0_I2C_SCL)

/* Assign divider type and number for I2C */
#define I2C_CLK_DIV_TYPE  (CY_SYSCLK_DIV_16_BIT)
#define I2C_CLK_DIV_NUM   (0U)

/* I2C master desired data rate in Hz */
#define I2C_DESIRED_DATA_RATE_HZ    (100000U)

/* Buffer to write to the slave */
uint8_t buffer[] = {0x55, 0x44, 0x33};
/* Wait 100 ms until operation completion */
uint32_t timeout = 100UL;

int main(void)
{
    cy_rslt_t result;
	cy_en_scb_i2c_status_t status;
	uint32_t dataRate;

    /* Initialize the device and board peripherals */
    result = cybsp_init() ;
    if (result != CY_RSLT_SUCCESS)
    {
        CY_ASSERT(0);
    }

    /* Allocate context for I2C operation */
    cy_stc_scb_i2c_context_t i2cContext;

    /* Populate configuration structure */

	/* Master  configuration */
	const cy_stc_scb_i2c_config_t i2cConfig =
	{
		.i2cMode   = CY_SCB_I2C_MASTER,
		.useRxFifo = false,
		.useTxFifo = true,
		.slaveAddress     = 0U,
		.slaveAddressMask = 0U,
		.acceptAddrInFifo = false,
		.ackGeneralAddr   = false,
		.hsEnable         = false,          /* Only applicable for PSoC 4100S Max */
		.enableWakeFromSleep = false,
		.enableDigitalFilter = false,
		.lowPhaseDutyCycle = 8U,
		.highPhaseDutyCycle = 8U,
	};

    /* Configure I2C to operate */
    (void) Cy_SCB_I2C_Init(SCB0, &i2cConfig, &i2cContext);

    /* Connect SCB0 I2C function to pins */
    Cy_GPIO_SetHSIOM(I2C_PORT, I2C_SCL_NUM, HSIOM_SCL);
    Cy_GPIO_SetHSIOM(I2C_PORT, I2C_SDA_NUM, HSIOM_SDA);
    /* Configure pins for I2C operation */
    Cy_GPIO_SetDrivemode(I2C_PORT, I2C_SCL_NUM, CY_GPIO_DM_OD_DRIVESLOW);
    Cy_GPIO_SetDrivemode(I2C_PORT, I2C_SDA_NUM, CY_GPIO_DM_OD_DRIVESLOW);


    /* Connect assigned divider to be a clock source for I2C */
    Cy_SysClk_PeriphAssignDivider(PCLK_SCB0_CLOCK, I2C_CLK_DIV_TYPE, I2C_CLK_DIV_NUM);

    /* I2C master desired data rate is 100 kbps.
    * To support this data rate the clk_scb frequency must be in range 1.55 – 3.2 MHz.
    * Find clk_scb valid ranges in TRM section I2C sub-section Oversampling and Bit Rate.
    * For clk_hf = 48 MHz, select divider value 30 and get clk_scb = (48 MHz / 30) = 1.6 MHz.
    * This clock frequency meets requirements above.
    */
    Cy_SysClk_PeriphSetDivider   (I2C_CLK_DIV_TYPE, I2C_CLK_DIV_NUM, 29u);
    Cy_SysClk_PeriphEnableDivider(I2C_CLK_DIV_TYPE, I2C_CLK_DIV_NUM);
    /* Configure master to operate with desired data rate */
    dataRate = Cy_SCB_I2C_SetDataRate(SCB0, I2C_DESIRED_DATA_RATE_HZ, Cy_SysClk_PeriphGetFrequency(I2C_CLK_DIV_TYPE, I2C_CLK_DIV_NUM));
    if ((dataRate > I2C_DESIRED_DATA_RATE_HZ) || (dataRate == 0U))
    {
        /* Can not reach desired data rate */
        CY_ASSERT(0U);
    }

    /* Enable I2C to operate */
    Cy_SCB_I2C_Enable(SCB0, &i2cContext);

    /* Enable global interrupts */
    __enable_irq();

    for (;;)
    {
    	/* Send Start condition, address and receive ACK/NACK response from slave */
    	status = Cy_SCB_I2C_MasterSendStart(SCB0, 0x08U, CY_SCB_I2C_WRITE_XFER, timeout, &i2cContext);
    	if (CY_SCB_I2C_SUCCESS == status)
    	{
    	    uint32_t cnt = 0UL;
    	    /* Write data into the slave from the buffer */
    	    do
    	    {
    	        /* Write byte and receive ACK/NACK response */
    	        status = Cy_SCB_I2C_MasterWriteByte(SCB0, buffer[cnt], timeout, &i2cContext);
    	        ++cnt;
    	    }
    	    while((status == CY_SCB_I2C_SUCCESS) && (cnt < sizeof(buffer)));
    	}
    	/* Check status of transaction */
    	if ((status == CY_SCB_I2C_SUCCESS)           ||
    	    (status == CY_SCB_I2C_MASTER_MANUAL_NAK) ||
    	    (status == CY_SCB_I2C_MASTER_MANUAL_ADDR_NAK))
    	{
    	    /* Send Stop condition on the bus */
    	    status = Cy_SCB_I2C_MasterSendStop(SCB0, timeout, &i2cContext);
    	    if (status == CY_SCB_I2C_SUCCESS)
    	    {
    	        /* Data has been written into the slave */
    	    }
    	}

    	Cy_SysLib_Delay(1000);
    }
}

And the output for the code was observed as follows in the saleae logic analyser.

PandaS_0-1657705295503.png

Thank and Regards

Sobhit

MiNe_85951
Level 7
Level 7
Distributor - TED (Japan)
50 likes received 500 replies posted 50 solutions authored

Sobhit-san,

 

Thank you for the sample code. We will confirm for it.

 

We refer to the sample code ”I2C_Master_EzI2C_Slave” of Modus Toolbox.

We have disabled the EZI2C used in the I2C Slave in this sample project and tested it on other slave devices.

 

We rewrote the following code in that master.c :

/* Initiate write transaction */
errorStatus = Cy_SCB_I2C_MasterWrite(CYBSP_I2C_HW, &masterTransferCfg, &CYBSP_I2C_context);

/* Changed the above code to below */

errorStatus =  Cy_SCB_I2C_MasterSendStart(CYBSP_I2C_HW, I2C_SLAVE_ADDR, CY_SCB_I2C_WRITE_XFER, 1000000UL, &CYBSP_I2C_context);

 

Do you know why SCLK is 'L' instead of the expected waveform?

I feel sorry for the frequent confirmations.

 

Regards,

0 Likes
PandaS
Moderator
Moderator
Moderator
250 replies posted 100 solutions authored 5 likes given

Hi @MiNe_85951 ,

May I know the I2C Slave and Pins used in the S Max kit.

Warm Regards

Sobhit

 

MiNe_85951
Level 7
Level 7
Distributor - TED (Japan)
50 likes received 500 replies posted 50 solutions authored

Thank you for your early response!

 

The EZI2C Slave and P1 [0: 1] in the PSoC4S MAX kit are disable.

We enable only I2C Master and connect an I2C Slave device to the outside to check.

Of course, We are using the I2C bus pull-up, so Cy_SCB_I2C_MasterWrite () API will behave normally and Cy_SCB_I2C_MasterSendStart() which changed it will remain 'L' for some reason SCL of I2C.

I don't know why, so I'm asking this community a question.

Regards,

0 Likes
MiNe_85951
Level 7
Level 7
Distributor - TED (Japan)
50 likes received 500 replies posted 50 solutions authored

The following is a brief description:

 

1. Use Modus Toolbox sample project "I2C_Master_EzI2C_Slave".

2. EZI2C slave in that project is disabled.

3. Instead, connect another I2C slave device to the I2C bus.

4. Confirm communication normally with I2CMaster.c.

5. If you change Cy_SCB_I2C_MasterWrite () API in I2CMaster.c to Cy_SCB_I2C_MasterSendStart() , you will not be able to communicate normally. For some reason SCK holds L.

0 Likes
PandaS
Moderator
Moderator
Moderator
250 replies posted 100 solutions authored 5 likes given

Hi @MiNe_85951 ,

May be the issue is due to clock stretching. Could you please share your code.

And what is the slave used? - Is it a sensor or another microcontroller 

 

Warm Regards

Sobhit

PandaS
Moderator
Moderator
Moderator
250 replies posted 100 solutions authored 5 likes given

Hi @MiNe_85951 ,

Your SendStart API call seems to have a very large timeout value, please reduced it. 

1000000ms is a too large value to check weather system went timeout. It is approximately 15mins. 

Use something like 3000ms. This will help us debug better.

 

Thanks and Regards

Sobhit

MiNe_85951
Level 7
Level 7
Distributor - TED (Japan)
50 likes received 500 replies posted 50 solutions authored

Sobhit-san,

 

Many thanks for your support.

As you might guess, the slave connected to the I2C Master of PSoC4S MAX seems to have been busy.

We would like to see the behavior of slave devices.

 

Regards,

0 Likes