This entry's latest version is outdated and must be revised. Please see the documentation for the latest API.

I2C Slave in native (CPP) code by untitled

Oct. 18, 2013   |   Snippet   |   Licensed as GPL 3.0   |   1316 views

I've been working with a board that has an STM32F4... connected to my PC through a USB hub. Other peripherals are connected to the hub as well as the MPU. After my initial power-on I received errors on the PC side that there wasn't enough power for my peripherals. I had presumed, like an idiot, that my hub would provide 500mA, by default it only provides 100mA. There were pins to configure it for 500mA, but only on the larger package (I have the 28pin). During power-on reset the hub looks for an I2C flash device and attempts to read the configuration from it. So my solution was to emulate being a slave device using my STM32F4. I wired some GPIO pins to the hub and went native, the code below is the result.

I realize most people won't be working with the same USB hub I have, but I figured I'd post this code in-case some other beginner wants to emulate an I2C Slave device.

Comments or questions?   Discuss on the forum.



Author Version Date
untitled 1 10/18 '13 at 06:45pm
1 — Source
  1. GPIO_PIN SDA = (GPIO_PIN)30;
  2. GPIO_PIN SCL = (GPIO_PIN)29;
  3. GPIO_PIN RST = (GPIO_PIN)28;
  4.  
  5. void I2CSlaveWriteBit(BOOL bit)
  6. {
  7. while (!CPU_GPIO_GetPinState(SCL));
  8. CPU_GPIO_SetPinState(SDA, bit);
  9. while (CPU_GPIO_GetPinState(SCL));
  10. }
  11.  
  12. void I2CSlaveWriteByte(BYTE aData)
  13. {
  14. for (int bit = 0; bit < 8; bit++)
  15. {
  16. I2CSlaveWriteBit((BOOL)(aData & 0x80) != 0);
  17. aData <<= 1;
  18. }
  19. }
  20.  
  21. BOOL I2CSlaveReadBit()
  22. {
  23. //This method's "timeout" is based on cycles not hard time.
  24.  
  25. BOOL result = FALSE;
  26. UINT32 timeout = 0;
  27.  
  28. while (!CPU_GPIO_GetPinState(SCL))
  29. {
  30. timeout += 1;
  31. if (timeout > 6000000)
  32. {
  33. return result;
  34. }
  35. }
  36. result = CPU_GPIO_GetPinState(SDA);
  37. timeout = 0;
  38. while (CPU_GPIO_GetPinState(SCL))
  39. {
  40. timeout += 1;
  41. if (timeout > 6000000)
  42. {
  43. return result;
  44. }
  45. }
  46.  
  47. return result;
  48. }
  49.  
  50. BYTE I2CSlaveReadByte()
  51. {
  52. BYTE result = 0x00;
  53.  
  54. for (int bit = 0; bit < 8; bit++)
  55. {
  56. if (I2CSlaveReadBit())
  57. {
  58. result |= (BYTE)(1 << (7 - bit));
  59. }
  60. else
  61. {
  62. result |= (BYTE)(0 << (7 - bit));
  63. }
  64. }
  65.  
  66. return result;
  67. }
  68.  
  69. void ConfigureHub()
  70. {
  71. //Configures CY7C65634-28LTXC for 500mA of power (default is 100mA)
  72.  
  73. CPU_GPIO_EnableOutputPin(RST, TRUE);
  74. CPU_GPIO_SetPinState(RST, FALSE);
  75. HAL_Time_Sleep_MicroSeconds(10);
  76. CPU_GPIO_SetPinState(RST, TRUE);
  77.  
  78. CPU_GPIO_EnableInputPin(SCL, TRUE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP);
  79. CPU_GPIO_EnableInputPin(SDA, TRUE, NULL, GPIO_INT_NONE, RESISTOR_PULLUP);
  80.  
  81. BYTE data[] = { 0xb4,0x04,0x70,0x65,0x8e,0xfe,0x00,0x02,0xfa,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0x0f,0x43,0x49,0x44,0x20,0x42,0x69,0x6f,0x2d,0x53,0x63,0x69,0x65,0x6e,0x63,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0x43,0x49,0x2d,0x31,0x31,0x30,0x20,0x50,0x6c,0x61,0x6e,0x74,0x20,0x43,0x61,0x6e,0x6f,0x70,0x79,0x20,0x49,0x6d,0x61,0x67,0x65,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x43,0x49,0x31,0x31,0x30,0x56,0x36 };
  82.  
  83. CPU_GPIO_SetPinState(LED, TRUE);
  84.  
  85. BYTE deviceAddress = 0x00;
  86. BYTE wordAddress = 0x00;
  87.  
  88. for (INT8 di = 0; di < 120; di += 2)
  89. {
  90.  
  91. I2CSlaveReadBit(); //Start
  92.  
  93. deviceAddress = I2CSlaveReadByte(); //Device address and Write bit
  94.  
  95. I2CSlaveReadBit(); //ACK
  96.  
  97. wordAddress = I2CSlaveReadByte(); //Word address
  98.  
  99. I2CSlaveReadBit(); //ACK
  100.  
  101. I2CSlaveReadBit(); //Start
  102.  
  103. deviceAddress = I2CSlaveReadByte(); //Device address and Read bit
  104.  
  105. I2CSlaveReadBit(); //ACK
  106.  
  107. CPU_GPIO_EnableOutputPin(SDA, CPU_GPIO_GetPinState(SDA));
  108.  
  109. I2CSlaveWriteByte(data[di]); //Data to write
  110.  
  111. CPU_GPIO_EnableInputPin(SDA, CPU_GPIO_GetPinState(SDA), NULL, GPIO_INT_NONE, RESISTOR_PULLUP);
  112.  
  113. I2CSlaveReadBit(); //NACK
  114.  
  115. CPU_GPIO_EnableOutputPin(SDA, CPU_GPIO_GetPinState(SDA));
  116.  
  117. I2CSlaveWriteByte(data[di + 1]); //Data to write
  118.  
  119. CPU_GPIO_EnableInputPin(SDA, CPU_GPIO_GetPinState(SDA), NULL, GPIO_INT_NONE, RESISTOR_PULLUP);
  120.  
  121. I2CSlaveReadBit(); //NACK
  122.  
  123. }
  124. }