2021年2月19日 星期五

CD74HC4067 模組的使用教學

CD74HC4067 作用是通過選擇達成 1 對 16 組接腳信號的讀取與寫入。更詳細的說,根據晶片上 S0-S3 四個不同接腳的組合,讓 SIG 管腳和 C0-C15 導通。因此,最常見的用法是用來測試類比信號。比如,Arduino Uno 上面只有 6 個類比輸入,用一個 CD74HC4067 可以多擴展出來 16 個,於是可以支援 6+16-1=21 個類比接腳。













這個晶片的使用方法非常簡單,例如:S0-S3 分別是 0、0、0、0 時,SIG 就和 C0 是導通的。因此,依照個個原則,我們快速地寫出這段程式碼:

//-----Mux control pins
int s0=6;
int s1=5;
int s2=4;
int s3=3;

//-----Mux in "SIG" pin
int SIG_pin=0;
void setup()
{
        pinMode(s0,OUTPUT);
        pinMode(s1,OUTPUT);
        pinMode(s2,OUTPUT);
        pinMode(s3,OUTPUT);
        digitalWrite(s0,LOW);
        digitalWrite(s1,LOW);
        digitalWrite(s2,LOW);
        digitalWrite(s3,LOW);
        Serial.begin(9600);
}

void loop()
{
        int v;

        //-----Loop through and read all 16 values
        for(int i=0; i<16; i++)
        {
                Serial.print("Value at channel ");
                Serial.print(i);
                Serial.print(" is : ");
                v = readMux(i);
                Serial.println(v * 5.0 / 1024);
        }
        Serial.println(" ");
        delay(3000);
}

int readMux(int channel)
{
        int controlPin[] = {s0,s1,s2,s3};
        int muxChannel[16][4] =
        {
                {0, 0, 0, 0}, //-----channel 0
                {1, 0, 0, 0}, //-----channel 1
                {0, 1, 0, 0}, //-----channel 2
                {1, 1, 0, 0}, //-----channel 3
                {0, 0, 1, 0}, //-----channel 4
                {1, 0, 1, 0}, //-----channel 5
                {0, 1, 1, 0}, //-----channel 6
                {1, 1, 1, 0}, //-----channel 7
                {0, 0, 0, 1}, //-----channel 8
                {1, 0, 0, 1}, //-----channel 9
                {0, 1, 0, 1}, //-----channel 10
                {1, 1, 0, 1}, //-----channel 11
                {0, 0, 1, 1}, //-----channel 12
                {1, 0, 1, 1}, //-----channel 13
                {0, 1, 1, 1}, //-----channel 14
                {1, 1, 1, 1}  //-----channel 15
        };

        //-----loop through the 4 sig
        for(int i=0; i<4; i++)
        { 
                digitalWrite(controlPin[i], muxChannel[channel][i]);
        }

        //-----read the value at the SIG pin
        int val = analogRead(SIG_pin);

        //-----return the value
        return val;
}

發展過程中犯過的失誤或可以改進的部分

  • 可支援 digital 與 analog 的讀與寫,但必須接對接腳。例如:如果需要讀取類比訊號,那 SIG 接腳就必須要接到 A0~A5 等類比接腳。
  • 是否覺得這段程式太冗長了?
    int muxChannel[16][4] =
    {
            {0, 0, 0, 0}, //-----channel 0
            {1, 0, 0, 0}, //-----channel 1
            {0, 1, 0, 0}, //-----channel 2
            {1, 1, 0, 0}, //-----channel 3
            {0, 0, 1, 0}, //-----channel 4
            {1, 0, 1, 0}, //-----channel 5
            {0, 1, 1, 0}, //-----channel 6
            {1, 1, 1, 0}, //-----channel 7
            {0, 0, 0, 1}, //-----channel 8
            {1, 0, 0, 1}, //-----channel 9
            {0, 1, 0, 1}, //-----channel 10
            {1, 1, 0, 1}, //-----channel 11
            {0, 0, 1, 1}, //-----channel 12
            {1, 0, 1, 1}, //-----channel 13
            {0, 1, 1, 1}, //-----channel 14
            {1, 1, 1, 1}  //-----channel 15
     };
    
    //-----loop through the 4 sig
    for(int i=0; i<4; i++)
    { 
            digitalWrite(controlPin[i], muxChannel[channel][i]);
    }
    如果利用 bitRead() 我們就可以簡化程式碼。
    digitalWrite(s0,bitRead(c,0));
    digitalWrite(s1,bitRead(c,1));
    digitalWrite(s2,bitRea(c,2));
    digitalWrite(s3,bitRead(c,3));
    所以改寫後就成了這樣
    int channelSelect(int c)
    {
            //----- here is select what channel that we want to
            digitalWrite(s0,bitRead(c,0));
            digitalWrite(s1,bitRead(c,1));
            digitalWrite(s2,bitRead(c,2));
            digitalWrite(s3,bitRead(c,3));
        
            return c;
    }