乐鑫技术交流
直播中

回头太晚

9年用户 737经验值
擅长:可编程逻辑 电源/新能源
私信 关注
[问答]

I2C多路复用器和RFID阅读器不能同时工作要怎么操作?

我正在尝试将 RC522 RFID 读取器与 TCA9548A i2C 多路复用器一起使用,我将五个 SH1106 OLED 显示器连接到该多路复用器。我使用的是 Wemos D1(不是迷你版)。对于 RFID,我遵循了本教程: https:
我按以下方式连接了物品:
但我只能得到一个或另一个工作:当我注释掉 LINE A 和 BLOCK C 时,显示工作。当我注释掉 BLOCK B 时,RFID 阅读器工作。当我什么都不评论时,两者都不起作用。
我究竟做错了什么?
我遇到的另一个问题是切换多路复用器后,我总是必须重新初始化显示(见 D 行)。如果我不这样做,显示器将不会显示任何内容。也许您也知道如何避免这种情况,因为每次重新初始化都会使显示闪烁一次,这对我的应用程序来说很丑陋。
提前致谢!
主要代码:
代码:全选#include
#include
#include

#include

#include "SH1106Wire.h"

#define SS_PIN D4
#define RST_PIN D0

MFRC522 rfid(SS_PIN, RST_PIN);
MFRC522::MIFARE_Key key;

// Init array that will store new NUID
byte nuidPICC[4];

DisplayService displayService;

/**
   Helper routine to dump a byte array as hex values to Serial.
*/
void printHex(byte *buffer, byte bufferSize) {
    for (byte i = 0; i < bufferSize; i++) {
        Serial.print(buffer < 0x10 ? " 0" : " ");
        Serial.print(buffer, HEX);
    }
}

/**
   Helper routine to dump a byte array as dec values to Serial.
*/
void printDec(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer < 0x10 ? " 0" : " ");
    Serial.print(buffer, DEC);
  }
}

void setup() {
    Serial.begin(115200);
    SPI.begin();
    rfid.PCD_Init(); // Init MFRC522 // <--- LINE A
}

int num = 0;
// --- BLOCK B ---
void loop() {
    for (int i = 2; i <= 6; i++) {
        SH1106Wire* display = displayService.display(i);
        display->clear();
        display->flipScreenVertically();
        display->setFont(ArialMT_Plain_24);
        display->setTextAlignment(TEXT_ALIGN_CENTER);
        display->drawString(64, 20, String(num));
        display->display();
    }
    num++;
// --- END BLOCK B ---

// --- BLOCK C ---
    // Reset the loop if no new card present on the sensor/reader. This saves
    // the entire process when idle.
    if (!rfid.PICC_IsNewCardPresent()) return;

    // Verify if the NUID has been readed
    if (!rfid.PICC_ReadCardSerial()) return;

    Serial.print(F("PICC type: "));
    MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
    Serial.println(rfid.PICC_GetTypeName(piccType));

    // Check is the PICC of Classic MIFARE type
    if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&
        piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
        piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
        Serial.println(F("Your tag is not of type MIFARE Classic."));
        return;
    }

    if (rfid.uid.uidByte[0] != nuidPICC[0] ||
        rfid.uid.uidByte[1] != nuidPICC[1] ||
        rfid.uid.uidByte[2] != nuidPICC[2] ||
        rfid.uid.uidByte[3] != nuidPICC[3]) {
        Serial.println(F("A new card has been detected."));

        // Store NUID into nuidPICC array
        for (byte i = 0; i < 4; i++) {
            nuidPICC = rfid.uid.uidByte;
        }

        Serial.println(F("The NUID tag is:"));
        Serial.print(F("In hex: "));
        printHex(rfid.uid.uidByte, rfid.uid.size);
        Serial.println();
        Serial.print(F("In dec: "));
        printDec(rfid.uid.uidByte, rfid.uid.size);
        Serial.println();
    } else
        Serial.println(F("Card read previously."));

    // Halt PICC
    rfid.PICC_HaltA();

    // Stop encryption on PCD
    rfid.PCD_StopCrypto1();
  //--- END BLOCK C ---
}


显示服务.cpp
代码:全选#include

#include "Arduino.h"
#include "DisplayService_h"
#include "SH1106Wire.h"

SH1106Wire displayInstance(0x3C, SDA, SCL);  // ADDRESS, SDA, SCL
uint8 activeDisplay = 0;

DisplayService::DisplayService() {}

SH1106Wire* DisplayService::display(uint8 displayNumber) {
    if (activeDisplay == displayNumber) {
        return &displayInstance;
    } else {
        this->changeDisplay(displayNumber);
        activeDisplay = displayNumber;
        displayInstance.init(); // <--- LINE D
        return &displayInstance;
    }
}

void DisplayService::changeDisplay(uint8 displayNumber) {
    Wire.beginTransmission(0x70);    // TCA9548A address
    Wire.write(1 << displayNumber);  // send byte to select bus
    Wire.endTransmission();
}


显示服务_h
代码:全选#ifndef DisplayService_h
#define DisplayService_h
#include "SH1106Wire.h"
class DisplayService {
   public:
    DisplayService();
    SH1106Wire* display(u_int8_t displayNumber);
   private:
    void changeDisplay(u_int8_t displayNumber);
};
#endif

回帖(1)

jjll652

2024-1-2 16:01:20
您需要在代码中添加一些逻辑来确保 RFID 阅读器和多路复用器不能同时访问 I2C 总线。例如,您可以使用一个变量来跟踪当前是 RFID 阅读器在使用 I2C,还是多路复用器在使用 I2C。当 RFID 阅读器需要访问 I2C 时,您需要将变量设置为 "RFID",并关闭多路复用器。当多路复用器需要访问 I2C 时,您需要将变量设置为 "MUX",并关闭 RFID 阅读器。

另外,如果您必须在切换多路复用器后重新初始化显示器,那么您需要在代码中添加一些逻辑来确保在每次切换后,显示器都将重新初始化。您可以使用一个布尔变量来跟踪是否需要重新初始化显示器。每次切换多路复用器时,检查这个变量。如果它是真的,那么重新初始化显示器并将变量设置为假。这样您就可以避免必须手动重新初始化显示器的问题。
举报

更多回帖

×
20
完善资料,
赚取积分