- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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)
I configured it with reference to PDL, but is there a problem with how to use this "Cy_SCB_I2C_MasterSendStart()"API?
Regards,
Solved! Go to Solution.
- Labels:
-
PSoC 4 MCU
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Thank and Regards
Sobhit
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Thank and Regards
Sobhit
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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,