2013年4月8日 星期一

Arduino:四位數七段顯示器



源自於 : http://www.starfpga.com/modules/tinyd2/index.php?id=2


七段顯示器介紹
     七段顯示器,在許多產品或場合上經常可見。其內部結構是由八個發光二極體所組成,為七個筆畫與一個小數點,依順時針方向為A、B、C、D、E、F、G與DP等八組發光二極體之排列,可用以顯示0~9數字及英文數A、b、C、d、E、F。目前常用的七段顯示器通常附有小數點,如此使其得以顯示阿拉伯數之小數點部份。七段顯示器的腳位和線路圖如下圖ㄧ所示( 其第一支接腳位於俯視圖之左上角 )。
 
圖ㄧ、七段顯示器尺寸圖
     由於發光二極體只有在順向偏壓的時候才會發光。因此,七段顯示器依其結構不同的應用需求,區分為低電位動作與高電位動作的兩種型態的元件,另一種常見的說法則是共陽極( 低電位動作 )與共陰極( 高電位動作 )七段顯示器,如下圖二所示。
 
圖二、共陽極( 低電位動作 )與共陰極( 高電位動作 )


源自 :  http://macao.communications.museum/chi/exhibition/secondfloor/moreinfo/Displays.html

七段發光二極管顯示器

數字可以由具有不同基數的數系來表示。在日常生活中,我們習慣用0至9來表示數字,這種表示法稱為十進制數系,它的基數是10。在數碼電子學中,只有低電平和高電平兩種狀態,它們分別代表0和1,這種表示法稱為二進制數系,它的基數是2。二進制數的每一個數位稱為位元 (bit),它是由英文字 “binary digit” 的縮寫所構成的。
輸入A至D是用來控制顯示在LED顯示器上的數字的。輸入按 “DCBA” 的順序來表示一個4位元二進制數。它們各自的數權值如下所示:
輸入D 是最高有效位元: (MSB) 23 = 8
輸入C 是第二有效位元: (2ndSB)22 = 4
輸入B 是第三有效位元: (2rdSB)21 = 2
輸入A 是最低有效位元: (LSB) 20 = 1
4位元二進制數轉換為十進制數的公式是:
十進制數 = D x 23 + C x 22 + B x 21 + A x 20
七段發光二極管顯示器是電子學中顯示十進制阿拉伯數字的一種方式。在現今的點陣顯示器出現之前,它已被廣泛應用。七段發光二極管顯示器由七個區段組成,見圖1。每個區段都是一顆發光二極管。它們被組合起來共同顯示標準的十進制阿拉伯數字。
圖1: 七段發光二極管顯示器
BCD至七段解碼器的集成電路 (IC) 芯片把二進制輸入A至D的邏輯狀態轉換成可以驅動七段發光二極管顯示器的七個輸出訊號。BCD的全寫是Binary-Coded Decimal,意思是二進制編碼十進制。表1列出了二進制輸入、解碼器輸出和十進制數0至9之間的關係;圖2則指出顯示器七個區段的名稱。
表1: BCD至七段解碼器的真值表
圖2: 顯示模組的示意圖,內裡包含BCD至七段解碼器和七段發光二極管顯示器




四位數七段顯示器


/*
 4 digit 7 segment display:
 7 segments
 4 digits
 1 colon
 =
 12 pins required for full control 

 */

int digit0 = 11; //PWM Display pin 1
int digit1 = 10; //PWM Display pin 2
int digit2 = 9; //PWM Display pin 6
int digit3 = 6; //PWM Display pin 8

int segA = A1; //Display pin 14
int segB = 3; //Display pin 16
int segC = 4; //Display pin 13
int segD = 5; //Display pin 3
int segE = A0; //Display pin 5
int segF = 7; //Display pin 11
int segG = 8; //Display pin 15

void setup() {                
  pinMode(segA, OUTPUT);
  pinMode(segB, OUTPUT);
  pinMode(segC, OUTPUT);
  pinMode(segD, OUTPUT);
  pinMode(segE, OUTPUT);
  pinMode(segF, OUTPUT);
  pinMode(segG, OUTPUT);

  pinMode(digit0, OUTPUT);
  pinMode(digit1, OUTPUT);
  pinMode(digit2, OUTPUT);
  pinMode(digit3, OUTPUT);
  
  pinMode(13, OUTPUT);
}

void loop() {
  
  //long startTime = millis();

  displayNumber(millis()/1000);

  //while( (millis() - startTime) < 2000) {
  //displayNumber(1217);
  //}
  //delay(1000);  
}

//Given a number, we display 10:22
//After running through the 4 numbers, the display is left turned off

//Display brightness
//Each digit is on for a certain amount of microseconds
//Then it is off until we have reached a total of 20ms for the function call
//Let's assume each digit is on for 1000us
//Each digit is on for 1ms, there are 4 digits, so the display is off for 16ms.
//That's a ratio of 1ms to 16ms or 6.25% on time (PWM).
//Let's define a variable called brightness that varies from:
//5000 blindingly bright (15.7mA current draw per digit)
//2000 shockingly bright (11.4mA current draw per digit)
//1000 pretty bright (5.9mA)
//500 normal (3mA)
//200 dim but readable (1.4mA)
//50 dim but readable (0.56mA)
//5 dim but readable (0.31mA)
//1 dim but readable in dark (0.28mA)

void displayNumber(int toDisplay) {
#define DISPLAY_BRIGHTNESS  500

#define DIGIT_ON  HIGH
#define DIGIT_OFF  LOW

  long beginTime = millis();

  for(int digit = 4 ; digit > 0 ; digit--) {

    //Turn on a digit for a short amount of time
    switch(digit) {
    case 1:
      digitalWrite(digit3, DIGIT_ON);
      break;
    case 2:
      digitalWrite(digit2, DIGIT_ON);
      break;
    case 3:
      digitalWrite(digit1, DIGIT_ON);
      break;
    case 4:
      digitalWrite(digit0, DIGIT_ON);
      break;
    }

    //Turn on the right segments for this digit
    lightNumber(toDisplay % 10);
    toDisplay /= 10;

    delayMicroseconds(DISPLAY_BRIGHTNESS); 
    //Display digit for fraction of a second (1us to 5000us, 500 is pretty good)

    //Turn off all segments
    lightNumber(10); 

    //Turn off all digits
    digitalWrite(digit0, DIGIT_OFF);
    digitalWrite(digit1, DIGIT_OFF);
    digitalWrite(digit2, DIGIT_OFF);
    digitalWrite(digit3, DIGIT_OFF);
  }

  while( (millis() - beginTime) < 10) ; 
  //Wait for 20ms to pass before we paint the display again
}

//Given a number, turns on those segments
//If number == 10, then turn off number
void lightNumber(int numberToDisplay) {

#define SEGMENT_ON  LOW
#define SEGMENT_OFF HIGH

  switch (numberToDisplay){

  case 0:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_OFF);
    break;

  case 1:
    digitalWrite(segA, SEGMENT_OFF);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_OFF);
    break;

  case 2:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_OFF);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 3:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 4:
    digitalWrite(segA, SEGMENT_OFF);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 5:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_OFF);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 6:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_OFF);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 7:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_OFF);
    break;

  case 8:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 9:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_ON);
    break;

  case 10:
    digitalWrite(segA, SEGMENT_OFF);
    digitalWrite(segB, SEGMENT_OFF);
    digitalWrite(segC, SEGMENT_OFF);
    digitalWrite(segD, SEGMENT_OFF);
    digitalWrite(segE, SEGMENT_OFF);
    digitalWrite(segF, SEGMENT_OFF);
    digitalWrite(segG, SEGMENT_OFF);
    break;
  }
}

沒有留言:

張貼留言

Messaging API作為替代方案

  LINE超好用功能要沒了!LINE Notify明年3月底終止服務,有什麼替代方案? LINE Notify將於2025年3月31日結束服務,官方建議改用Messaging API作為替代方案。 //CHANNEL_ACCESS_TOKEN = 'Messaging ...