Arduino 4位數7段LED數字顯示器

最近做了幾個專案都使用Arduino, 有位同仁也對Arduino產生了學習的興趣, 他自己嘗試用74HC595移位器可以驅動一位數7段LED, 但在4位數的就是動不了, 要我幫忙看一下。

所以整理這幾日看的資料:

1. 7段LED的原理:
以下這個連結的文章, 寫得不錯!
介紹1位數7段LED原理
  (1) 原來是用7個LED燈, 加上小數點就是8個LED燈來組成數字
  (2) 有分共陽(common anode), 共陰(common cathode)兩種作法
  (3) 所以會用掉Arduino的8個數位輸出

2. 4位數7段的LED:
這篇介紹4位數的部份, 4位數7段LED(common anode)
  (1) 說明4位數的作法是多工的方式, 和原本一位數的作法一樣, 也是要8個數位輸出
  (2) 但是只再多使用D1, D2, D3, D4(4位數7段LED的腳位)共四個腳位, 用來指示要將8個segment的輸出送到那一個位數。
  (3) 使用電晶體(NPN)來加大輸出的電流能力, up side switch (sourcing current)
  (4) 會用掉Arduino的所有數位輸出腳位

這篇的作法有點不一樣, (common cathode)
http://www.electroschematics.com/10512/arduino-4-digit-7-segment-led-display/
  (1) 一樣加入4個電晶體(NPN), 但是做成down side switch(sinking current)
  (2) 程式寫法幾乎和前一篇的相同, showDigit()裡的作法改成common cathode

3. 減少使用Arduino數位輸出的方法, 使用74HC595
這篇文章有詳細的說明: Arduino_74HC595
  (1) 595可以讓Arduino只使用3支腳就可以控制8個LED燈
  (2) 還可以用串2個595的方式, 增加到可以控制16個LED燈

4. Arduino內建支援595的使用函數
這篇文章有介紹: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/

5. 整合以上
  電路部份主要依  4位數7段LED(common anode)
  但是 因拿到的4位數7段LED為common cathode
  所以電晶體接法採用 http://www.electroschematics.com/10512/arduino-4-digit-7-segment-led-display/
  另外加入74HC595以減少使用Arduino數位輸出腳位
  稍為有調整使用到的腳位

  搭配的Arduino程式碼如下:

const int sensorPin= 0;//The analog sensor is connected to analog pin 0 of the arduino

//ABCDEFG,dp
const int numeral[10]= {
B11111100, //0
B01100000, //1
B11011010, //2
B11110010, //3
B01100110, //4
B10110110, //5
B00111110, //6
B11100000, //7
B11111110, //8
B11100110, //9
};

//pins for decimal point and each segment
//dp, G, F, E, D, C, B, A
const int segmentPins[]= { 13, 7, 8, 6, 5, 3, 2, 4};

const int numberofDigits=4;

const int digitPins[numberofDigits] = { 9, 10, 11, 12}; //digits 1, 2, 3, 4

//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 7;
////Pin connected to DS of 74HC595
int dataPin = 6;

void setup()
{
  //for (int i=0; i < 8; i++)
  //  pinMode(segmentPins[i], OUTPUT); //set segment and DP pins to output

  //sets the digit pins as outputs
  for (int i=0; i < numberofDigits; i++)
    pinMode(digitPins[i], OUTPUT);

  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

void loop()
{
  /*
  for (int i=0; i<=9999; i++) {
    //for (int j=0; j<4 j="" p="">    for (int k=0; k<50 k="" p="">      showNumber(i);
      //showDigit(2, j);
    }
    //}
  }
  */
  int value= analogRead(sensorPin);
  for (int k=0; k<100 k="" p="">    showNumber(value);
  }
  //delay(100);
}

void showNumber (int number)
{
  if (number == 0)
    showDigit (0, numberofDigits-1); //display 0 in the rightmost digit
  else
  {
    for (int digit= numberofDigits-1; digit >=0; digit--)
    {
      if (number > 0)
      {
        showDigit(number % 10, digit);
        number= number/10;
      }
    }
  }
}

//Displays given number on a 7-segment display at the given digit position
void showDigit (int number, int digit)
{
  //pinMode(digitPins[digit], OUTPUT);
  digitalWrite(digitPins[digit], HIGH);

  //ground latchPin and hold low for as long as you are transmitting
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, numeral[number]);
    //return the latch pin high to signal chip that it
    //no longer needs to listen for information
    digitalWrite(latchPin, HIGH);
 
  /*
  for (int segment= 1; segment < 8; segment++)
  {
    boolean isBitSet= bitRead(numeral[number], segment);

   // isBitSet= ! isBitSet; //remove this line if common cathode display
    digitalWrite(segmentPins[segment], isBitSet);
  }
  */
  delay(5);
  digitalWrite(digitPins[digit], LOW);
  //pinMode(digitPins[digit], INPUT);
}

留言

這個網誌中的熱門文章

D-BUS學習筆記

Cisco Switch學習筆記: EtherChannel

Cisco Switch學習筆記: interface的封包錯誤統計