multiplexer.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #include "multiplexer.h"
  2. #include "ti/driverlib/dl_i2c.h"
  3. #include "ti_msp_dl_config.h"
  4. #include <stdio.h>
  5. #include <stdint.h>
  6. /*
  7. Multiplexer TCA9548A:
  8. Address:0x70
  9. The TCA9548A is example of a single-register device, which is controlled via I2C commands. Since it has 1 bit to enable or disable a channel, there is only 1 register
  10. needed, and the controller merely writes the register data after the target address, skipping the register number.
  11. ADC connected to channel 0
  12. Both SDA and SL lines of the multiplexer is connected to VIN through pull-up resistors
  13. The following is the general procedure for a controller to access a target device:
  14. 1. If a controller wants to send data to a target:
  15. • Controller-transmitter sends a START condition and addresses the target-receiver.
  16. • Controller-transmitter sends data to target-receiver.
  17. • Controller-transmitter terminates the transfer with a STOP condition.
  18. 2. If a controller wants to receive or read data from a target:
  19. • Controller-receiver sends a START condition and addresses the target-transmitter.
  20. • Controller-receiver sends the requested register to read to target-transmitter.
  21. • Controller-receiver receives data from the target-transmitter.
  22. • Controller-receiver terminates the transfer with a STOP condition.
  23. The TCA9548A is example of a single-register device, which is controlled via I2C commands. Since it has 1 bit to enable or disable a channel,
  24. there is only 1 register needed, and the controller merely writes the register data after the target address, skipping the register number.
  25. */
  26. /*
  27. Scans all the addresses of the peripherals:
  28. */
  29. void I2C_scanBus() {
  30. printf("Scanning I2C Bus...\n");
  31. // **Step 1: Reset I2C Controller if Busy**
  32. if (DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS) {
  33. printf("I2C Bus Busy! Resetting I2C Controller...\n");
  34. DL_I2C_disableController(I2C_controller_INST); // Disable I2C
  35. delay_cycles(20000);
  36. DL_I2C_enableController(I2C_controller_INST); // Re-enable I2C
  37. delay_cycles(20000);
  38. }
  39. // **Step 2: Scan I2C Bus**
  40. for (uint8_t addr = 0x08; addr < 0x78; addr++) { // Valid I2C Address Range
  41. DL_I2C_startControllerTransfer(I2C_controller_INST, addr, DL_I2C_CONTROLLER_DIRECTION_RX, 1);
  42. delay_cycles(5000);
  43. if (!(DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_ERROR)) {
  44. printf("Device found at: 0x%02X\n", addr);
  45. }else {
  46. // Clear the error by resetting the I2C controller
  47. DL_I2C_disableController(I2C_controller_INST);
  48. DL_I2C_enableController(I2C_controller_INST);
  49. }
  50. }
  51. printf("I2C Scan Complete!\n");
  52. }
  53. /*Function for Multiplexer*/
  54. void Multiplexer_SelectChannel(uint8_t channel)
  55. {
  56. if (channel > 7) {
  57. printf("ERROR: Invalid Multiplexer Channel! Must be 0-7.\n");
  58. return;
  59. }
  60. uint8_t data = (channel);
  61. printf("Selecting Multiplexer I2C Channel: 0x%02X\n", data);
  62. // Ensure bus is idle before starting communication
  63. while (DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
  64. // SEND Command to Multiplexer
  65. DL_I2C_startControllerTransfer(I2C_controller_INST, MULTIPLEXER_I2C_ADDR, DL_I2C_CONTROLLER_DIRECTION_TX, 1);
  66. DL_I2C_fillControllerTXFIFO(I2C_controller_INST, &data, 1);
  67. // **Ensure STOP condition is sent**
  68. while (DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
  69. // **Slightly Increase Delay for Multiplexer to Process Command**
  70. delay_cycles(30000);
  71. // Verify Multiplexer Response:
  72. //uint8_t response= 0x00;
  73. DL_I2C_startControllerTransfer(I2C_controller_INST, MULTIPLEXER_I2C_ADDR, DL_I2C_CONTROLLER_DIRECTION_RX, 1);
  74. // Wait for a response from the multiplexer
  75. while (DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
  76. //uint8_t response = DL_I2C_receiveControllerData(I2C_controller_INST);
  77. // **Debug: Print Expected vs. Received Response**
  78. //printf("Multiplexer Response: 0x%02X (Expected: 0x%02X)\n", response, data);
  79. // **CHECK FOR ADDRESS ACKNOWLEDGMENT**
  80. //(if (!(DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_ERROR)) {
  81. // printf("Multiplexer detected at 0x70.\n");
  82. // return;
  83. //} else{
  84. // printf("ERROR: Multiplexer (0x70) detected.\n");
  85. //}
  86. // Wait for transaction completion
  87. //while (DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
  88. //if(response != data){
  89. // printf("ERROR: Multiplexer did not set the correct channel!\n");
  90. // **Retry Mechanism: Attempt to Set the Channel Again**
  91. // delay_cycles(10000);
  92. // Multiplexer_SelectChannel(channel);
  93. //} else {
  94. // printf("Multiplexer Active Channel: 0x%X\n", data);
  95. // return;
  96. //}
  97. }
  98. void Reset_I2C_Bus() {
  99. printf("I2C Bus is stuck! Resetting...\n");
  100. // Disable I2C Controller
  101. DL_I2C_disableController(I2C_controller_INST);
  102. delay_cycles(50000);
  103. // Re-enable I2C Controller
  104. DL_I2C_enableController(I2C_controller_INST);
  105. delay_cycles(50000);
  106. // Check if bus is free now
  107. uint32_t status = DL_I2C_getControllerStatus(I2C_controller_INST);
  108. printf("I2C Bus Status After Reset: 0x%08X\n", status);
  109. }