原创 如何用一条I2C总线驱动多个I2C设备?

2022-5-24 08:32 6686 11 4 分类: 智能硬件 文集: 方案
应用设计中,用一条I2C总线驱动多个I2C设备师很常见,实施也很简单,本项目将连接以下I2C设备:
1x16×2 I2C LCD显示屏,地址0x27
1x 128×32 I2C OLED显示屏,地址0x3C
2x PCF8574 I2C Io扩展器,地址0x20、0x21

上述组件可使用以下库文件,通过Arduino Uno控制:
LiquidCrystal_I2C.h,控制LCD屏;
Wire.h and PCF8574.h,控制I2C IO扩展器;
Adafruit_GFX, Adafruit_SSD1306.h 和 SPI.h,控制SSD1306 128×32 OLED显示屏。

由于所有元件相距不远,没必要I2C总线使用上拉电阻,因为这些杜邦线就是组件的一部分。
本项目电路很直观,不同的是,Uno板子在顶部靠近USB适配器附近增加了一个I2C口,我们把它和A4、A5一起使用。

 

首先,将所有I2C组件的SDA引脚以串行方式连接在一起,再连接于Arduino SDA引脚(一般为A4)。
其次,将所有I2C组件的SCL引脚串联起来,再连接到Arduino SCL引脚(一般为A5)
第三,将所有5v(Vcc)引线连接到Arduino开发板的5v引脚,所有接地引线(GND)连接到Arduino板子的GND引脚。
第四,通过阻值在640-1000欧姆范围内的电阻,将4个LEDs的一个引脚连接到两个PCF8574 IO扩展器P0、P1引脚,另一个引脚接地。
本项目采用外接的5v电源供电,因为根据Uno的实际需求,没必要从稳压器获得太大的电流。
连接完成后,检查所有接线,再打开Arduino IDE中的i2c扫描工具,就会再示例中看到库 Wire.h 文件。
启动电源,将库文件上传到Uno,再打开Serial Monitor,就会看到检测到了4个I2C设备。

 

如果没有检测到4个设备,检查接线和设备地址,看看问题出在哪里,很有可能是接线问题,或者设备的地址错了。
如果一切无误,将以下代码拷入Arduino IDE,相关解释参见中间的注释。
  1. /*
  2. Multiple devices on the I2C bus
  3. Maker and Iot Ideas, MakerIoT2020
  4. */
  5. // Include the libraries that we will need
  6. #include // needed for OLED display.
  7. #include // PCF8574
  8. #include // Generic I2C library
  9. #include // for OLED display
  10. #include // for OLED display
  11. #include // For I2C LCD display
  12. // we need to define the size of the OLED screen
  13. #define OLED_WIDTH 128
  14. #define OLED_HEIGHT 32
  15. // mine does not have an onboard reset pin. If yours do, specify the
  16. // pin that it is connected to on the Arduino here. To use the
  17. // Arduino reset pin, specify -1 as below
  18. #define OLED_RESET -1
  19. // Define the OLED display, width,hight protocol and reset pin
  20. Adafruit_SSD1306 oled(OLED_WIDTH,OLED_HEIGHT, &Wire, OLED_RESET);
  21. // Define the I2C LCD screen address and pin configuration
  22. LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3,POSITIVE);
  23. // Define the PCF8574 devices ( you can have up to 8 on a bus )
  24. // but in this case, my LCD uses address 0x27, so I will have a
  25. // conflicting address if I were to use 8 of them together with the
  26. // LCD
  27. PCF8574 Remote_1(0x20);
  28. PCF8574 Remote_2(0x21);
  29. // Note the I2C addresses. You can obtain them from the i2c_scanner
  30. void setup() {
  31. // serial debugging if needed
  32. Serial.begin(115200);
  33. // Start OLED Display Init
  34. if (!oled.begin(SSD1306_SWITCHCAPVCC,0x3C)) { // Init the OLED
  35. Serial.println(F("OLED INIT FAILED"));
  36. for(;;); // Dont proceed ... loop forever
  37. }
  38. oled.display();
  39. delay(2000); // This delay is required to give display time to
  40. // initialise properly
  41. oled.clearDisplay();
  42. oled.setTextSize(0);
  43. oled.setTextColor(SSD1306_WHITE);
  44. oled.setCursor(0,0);
  45. oled.println("TEST SCREEN");
  46. oled.display();
  47. delay(2000);
  48. oled.clearDisplay();
  49. oled.setCursor(1,0);
  50. oled.println("OLED SCREEN ON");
  51. oled.display();
  52. // Start the LCD
  53. lcd.begin(16,2);
  54. // Set the initial state of the pins on the PCF8574 devices
  55. // I found that the PCF8574 library sometimes does funny things
  56. // This is also an example of how to use native i2c to set the
  57. // status of the pins
  58. Wire.begin();
  59. Wire.beginTransmission(0x20); // device 1
  60. Wire.write(0x00); // all ports off
  61. Wire.endTransmission();
  62. Wire.begin();
  63. Wire.beginTransmission(0x21); // device 2
  64. Wire.write(0x00); // all ports off
  65. Wire.endTransmission();
  66. // Set pinModes for PCF8574 devices
  67. // Note that there are two of them
  68. Remote_1.pinMode(P0,OUTPUT);
  69. Remote_1.pinMode(P1,OUTPUT);
  70. Remote_2.pinMode(P0,OUTPUT);
  71. Remote_2.pinMode(P1,OUTPUT);
  72. // Start both IO extenders
  73. Remote_1.begin();
  74. Remote_2.begin();
  75. // and set ports to low on both
  76. // you may find that if you ommit this step, they come up in an
  77. // unstable state.
  78. Remote_1.digitalWrite(P0,LOW);
  79. Remote_1.digitalWrite(P1,LOW);
  80. Remote_2.digitalWrite(P0,LOW);
  81. Remote_2.digitalWrite(P1,LOW);
  82. }
  83. void loop() {
  84. // Draw a character map on the OLED display.
  85. // This function is borrowed from the Adafruit library
  86. testdrawchar();
  87. // Write to the IO extenders
  88. Remote_1.digitalWrite(P0,HIGH);
  89. Remote_1.digitalWrite(P1,LOW);
  90. Remote_2.digitalWrite(P0,HIGH);
  91. Remote_2.digitalWrite(P1,LOW);
  92. // Display their status on the LCD
  93. lcd.setCursor(0,0);
  94. lcd.print(" R1 P0=1 P1=0");
  95. lcd.setCursor(0,1);
  96. lcd.print(" R2 P0=1 P1=0");
  97. delay(500);
  98. // Change status
  99. Remote_1.digitalWrite(P1,HIGH);
  100. Remote_1.digitalWrite(P0,LOW);
  101. Remote_2.digitalWrite(P1,HIGH);
  102. Remote_2.digitalWrite(P0,LOW);
  103. // Update LCD
  104. lcd.setCursor(0,0);
  105. lcd.print(" R1 P0=0 P1=1");
  106. lcd.setCursor(0,1);
  107. lcd.print(" R2 P0=0 P1=1");
  108. delay(500);
  109. // Do some graphics on the OLED display
  110. // Function borrowed from Adafruit
  111. testdrawrect();
  112. oled.clearDisplay();
  113. delay(500);
  114. // repeat indefinitely
  115. }
  116. void testdrawrect(void) {
  117. oled.clearDisplay();
  118. for(int16_t i=0; i
  119. oled.drawRect(i, i, oled.width()-2*i, oled.height()-2*i, SSD1306_WHITE);
  120. oled.display(); // Update screen with each newly-drawn rectangle
  121. delay(1);
  122. }
  123. delay(500);
  124. }
  125. void testdrawchar(void) {
  126. oled.clearDisplay();
  127. oled.setTextSize(1); // Normal 1:1 pixel scale
  128. oled.setTextColor(SSD1306_WHITE); // Draw white text
  129. oled.setCursor(0, 0); // Start at top-left corner
  130. oled.cp437(true); // Use full 256 char 'Code Page 437' font
  131. // Not all the characters will fit on the display. This is normal.
  132. // Library will draw what it can and the rest will be clipped.
  133. for(int16_t i=0; i<256; i++) {
  134. if(i == '\n') oled.write(' ');
  135. else oled.write(i);
  136. }
  137. oled.display();
  138. delay(500);
  139. }

作者: 硬之城Allchips, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-3975615.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
11
关闭 站长推荐上一条 /3 下一条