微控制器三個引腳控制16路流水燈

想啥做啥發表於2021-07-06

我們先來看下最終的效果

我們先用微控制器按照74HC595手動分解的例子,來實現我們想要的結果。
首先,我們讓16個LED燈交叉亮起來

程式碼部分:

int STCP_Pin = 4;
int SHCP_Pin = 6;
int DS_Pin = 5; 


void setup ()
{
  pinMode(STCP_Pin,OUTPUT);
  pinMode(SHCP_Pin,OUTPUT);
  pinMode(DS_Pin,OUTPUT); 
}

// 我們先讓16個燈交叉亮
void loop()
{
  while(1)
  {
    digitalWrite(STCP_Pin, LOW);
    
    // 1
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, LOW);
    digitalWrite(SHCP_Pin, HIGH);
    // 2
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, HIGH);
    digitalWrite(SHCP_Pin, HIGH);
    // 3
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, LOW);
    digitalWrite(SHCP_Pin, HIGH);
    // 4
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, HIGH);
    digitalWrite(SHCP_Pin, HIGH);
    // 5
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, LOW);
    digitalWrite(SHCP_Pin, HIGH);
    // 6
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, HIGH);
    digitalWrite(SHCP_Pin, HIGH);
    
    // 7
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, LOW);
    digitalWrite(SHCP_Pin, HIGH);
    // 8
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, HIGH);
    digitalWrite(SHCP_Pin, HIGH);
    // 9
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, LOW);
    digitalWrite(SHCP_Pin, HIGH);
    // 10
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, HIGH);
    digitalWrite(SHCP_Pin, HIGH);
    // 11
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, LOW);
    digitalWrite(SHCP_Pin, HIGH);
    // 12
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, HIGH);
    digitalWrite(SHCP_Pin, HIGH);
    
    // 13
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, LOW);
    digitalWrite(SHCP_Pin, HIGH);
    // 14
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, HIGH);
    digitalWrite(SHCP_Pin, HIGH);
    // 15
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, LOW);
    digitalWrite(SHCP_Pin, HIGH);
    // 16
    digitalWrite(SHCP_Pin, LOW);
    digitalWrite(DS_Pin, HIGH);
    digitalWrite(SHCP_Pin, HIGH);
    
    digitalWrite(STCP_Pin, HIGH);    
  }
}

執行效果

然後我們再把程式碼簡化一下,使其看起來更簡潔,實用

int STCP_Pin = 4;
int SHCP_Pin = 6;
int DS_Pin = 5; 


void setup ()
{
  pinMode(STCP_Pin,OUTPUT);
  pinMode(SHCP_Pin,OUTPUT);
  pinMode(DS_Pin,OUTPUT); 
  
  digitalWrite(STCP_Pin, LOW);
}

void loop()
{
  unsigned char LED_Data;
  
  while(1)
  {
    
      LED_Data = 0xAA;
      // 第一個8位
      digitalWrite(STCP_Pin, LOW); 
      for(int i=0; i<8; i++)
      {
        if(LED_Data&0x80){ digitalWrite(DS_Pin, HIGH);}
        else             { digitalWrite(DS_Pin, LOW); }

        digitalWrite(SHCP_Pin, LOW);
        digitalWrite(SHCP_Pin, HIGH);
        LED_Data <<=1;
      } 
    
      // 第二個8位
      LED_Data = 0xAA;
      for(int i=0; i<8; i++)
      {
        if(LED_Data&0x80){ digitalWrite(DS_Pin, HIGH);}
        else             { digitalWrite(DS_Pin, LOW); }

        digitalWrite(SHCP_Pin, LOW);
        digitalWrite(SHCP_Pin, HIGH);
        LED_Data <<=1;
      } 

      digitalWrite(STCP_Pin, HIGH); 

    delay(1000);
  }
}

我們稍微改變下,讓LED燈按照我們的意思工作,封裝一下函式,然後讓中間四個燈亮起來

int STCP_Pin = 4;
int SHCP_Pin = 6;
int DS_Pin = 5; 

void HC595_Write(unsigned char data1, unsigned char data2);

void setup ()
{
  pinMode(STCP_Pin,OUTPUT);
  pinMode(SHCP_Pin,OUTPUT);
  pinMode(DS_Pin,OUTPUT); 

}

void loop()
{
  unsigned char LED_Data1 = 0x03;
  unsigned char LED_Data2 = 0xC0;
  while(1)
  {
    HC595_Write(LED_Data1, LED_Data2);
    delay(1000);
  }
}

void HC595_Write(unsigned char data1, unsigned char data2)
{       
      // 第一個8位
      digitalWrite(STCP_Pin, LOW); 
      for(int i=0; i<8; i++)
      {
        if(data1&0x80){ digitalWrite(DS_Pin, HIGH);}
        else             { digitalWrite(DS_Pin, LOW); }

        digitalWrite(SHCP_Pin, LOW);
        digitalWrite(SHCP_Pin, HIGH);
        data1 <<=1;
      } 
    
      // 第二個8位
      for(int i=0; i<8; i++)
      {
        if(data2&0x80){ digitalWrite(DS_Pin, HIGH);}
        else             { digitalWrite(DS_Pin, LOW); }

        digitalWrite(SHCP_Pin, LOW);
        digitalWrite(SHCP_Pin, HIGH);
        data2 <<=1;
      } 

      digitalWrite(STCP_Pin, HIGH); 
}

中間四個LED燈亮的效果

然後我們連貫起來搞個流水的燈玩玩

int STCP_Pin = 4;
int SHCP_Pin = 6;
int DS_Pin = 5; 

unsigned char LED_Data1[8] = { 0x01, 0x02, 0x04, 0x08,
                               0x10, 0x20, 0x40, 0x80};
unsigned char LED_Data2[8] = { 0x01, 0x02, 0x04, 0x08,
                               0x10, 0x20, 0x40, 0x80};

void HC595_Write(unsigned char data1, unsigned char data2);

void setup ()
{
  pinMode(STCP_Pin,OUTPUT);
  pinMode(SHCP_Pin,OUTPUT);
  pinMode(DS_Pin,OUTPUT); 

}

void loop()
{

  while(1)
  {
    for(int i=0; i<8; i++)
    {
        HC595_Write(0x00, LED_Data1[i]);
        delay(1000);
    }
    
    for(int i=0; i<8; i++)
    {
        HC595_Write( LED_Data2[i], 0x00);
        delay(1000);
    }
  }
}

void HC595_Write(unsigned char data1, unsigned char data2)
{       
      // 第一個8位
      digitalWrite(STCP_Pin, LOW); 
      for(int i=0; i<8; i++)
      {
        if(data1&0x80){ digitalWrite(DS_Pin, HIGH);}
        else             { digitalWrite(DS_Pin, LOW); }

        digitalWrite(SHCP_Pin, LOW);
        digitalWrite(SHCP_Pin, HIGH);
        data1 <<=1;
      } 
    
      // 第二個8位
      for(int i=0; i<8; i++)
      {
        if(data2&0x80){ digitalWrite(DS_Pin, HIGH);}
        else             { digitalWrite(DS_Pin, LOW); }

        digitalWrite(SHCP_Pin, LOW);
        digitalWrite(SHCP_Pin, HIGH);
        data2 <<=1;
      } 

      digitalWrite(STCP_Pin, HIGH); 
}

最終的流水燈實驗效果


當然arduino本身自帶了移位函式,同樣可以達到效果


int STCP_Pin = 4;
int SHCP_Pin = 6;
int DS_Pin = 5; 

unsigned char LED_Data1[8] = { 0x01, 0x02, 0x04, 0x08,
                               0x10, 0x20, 0x40, 0x80};
unsigned char LED_Data2[8] = { 0x01, 0x02, 0x04, 0x08,
                               0x10, 0x20, 0x40, 0x80};

void setup ()
{
  pinMode(STCP_Pin,OUTPUT);
  pinMode(SHCP_Pin,OUTPUT);
  pinMode(DS_Pin,OUTPUT); 
}
void loop()
{
  for(int a=0; a<8; a++)   
  {
    digitalWrite(STCP_Pin,LOW); 
    shiftOut(DS_Pin,SHCP_Pin,MSBFIRST,LED_Data1[a]);
    shiftOut(DS_Pin,SHCP_Pin,MSBFIRST,0x00);
    digitalWrite(STCP_Pin,HIGH); 
    delay(500); 
  }
  
  for(int a=0; a<8; a++)   
  {
    digitalWrite(STCP_Pin,LOW); 
    shiftOut(DS_Pin,SHCP_Pin,MSBFIRST,0x00);
    shiftOut(DS_Pin,SHCP_Pin,MSBFIRST,LED_Data2[a]);
    digitalWrite(STCP_Pin,HIGH); 
    delay(500); 
  }
}

流水的延時500ms的效果

總結:

1、複雜的功能,深入分解後背後的原理其實還是挺簡單的;

2、我們絕大部分時候都在造“輪子“,殊不知更優秀的“輪子”已經造好了;知曉“輪子”的由來,然後造出更優秀的“輪子”給自己用也是微控制器學習路上的一項重要技能。

相關文章