ใบงานที่2 7 Segment
ใบงานที่ 2
7 Segment
ผู้จัดทำ
นาย สราวุธ ชอบเพื่อน 021
นาย กฤษณะ รักธรรม 001
หลักการทำงาน
ไมโครคอนโทรลเลอร์โดยส่วนใหญ่แล้วมีขาสำหรับเป็น Digital I/O ที่จำกัด การจะนำไปกับงานที่ต้องใช้พอร์ตเยอะๆ โดยตรง ไม่ค่อยที่จะเหมาะนัก เนื่องจากจะทำให้เปลืองพอร์ต อีกทั้งยังส่งผลไม่ให้ต่อร่วมกับอุปกรณ์อื่นๆได้อีกด้วย
ไอซี 74HC595 เป็นไอซีที่ออกแบบมาสำหรับการใช้งานพอร์ตเยอะๆ เช่น การนำไปขับ 7 Segment หรือ LED Dot Matrix หรือป้ายไฟต่างๆ โดยใช้สายต่อเข้ากับพอร์ตของไมโครคอนโทรลเลอร์เพียง 3 เส้นเท่านั้น อีกทั้งการสั่งงานยังง่ายมากๆอีกด้วย
รู้จักกับ 74HC595
ไอซี 74HC595 เป็นไอซีเลื่อนบิต เมื่อมีการป้อนข้อมูลเข้าไปใหม่ บิตจะถูกเลื่อนไปตามข้อมูลที่ป้อน มีขาทั้งหมด 16 ขา เป็นขาเอาต์พุตที่ควบคุมได้ทั้งหมด 8 ขา ตั้งแต่ Q0 Q1 Q2 ... Q7 มีขา 3 ขาสำหรับการควบคุมขา Q0 - Q7
- ขา ST_CP เป็นขาควบคุมจังหวะการส่งข้อมูล เมื่อไม่มีการส่งข้อมูลจะให้สถานะขานี้เป็น HIGH แต่เมื่อมีการส่งข้อมูลจะให้ขานี้มีสถานะเป็น LOW จนกว่าจะหยุดส่งข้อมูลจึงให้ขานี้มีสถานะกลับมาเป็น HIGH อีกครั้ง
- ขา SH_CP เทียบได้กับขา Clock เป็นขาที่จะต้องป้อนสัญญาณพัลส์เข้าไปเพื่อควบคุมการรับข้อมูลเข้าไอซี โดยการป้อนสัญญาณจะต้องสัมพันธกับการป้อนข้อมูลในแต่ละบิต
- ขา DS เป็นขาสำหรับป้อนข้อมูลเข้าไปทีละบิต
และมีอีก 2 ขาสำหรับการป้อนข้อมูลลอจิกคงที่
- ขา MR ต่อให้มีสถานะเป็น HIGH หรือต่อเข้า +VCC
- ขา OE ต่อให้มีสถานะเป็น LOW หรือต่อเข้า GND
การควบคุมการทำงานไอซี 74HC595
การควบคุมการส่งข้อมูลเพื่อเปลี่ยนแปลง Q0 - Q7 มีขั้นตอนดังนี้
Step 1 เซ็ตให้ขา ST_CP มีสถานะเป็น LOW
Step 2 เซ็ตให้ขา DS เป็นข้อมูลบิตนั้นๆ
Step 3 เซ็ตให้ขา SH_CP มีสถานะเป็น HIGH
Step 4 หน่วงเวลา
Step 5 เซ็ตให้ขา SH_CP มีสถานะเป็น LOW
Step 6 หน่วงเวลา
Step 7 เริ่มกลับไปทำ Step 2 จนครบหมดทุกบิต
Step 8 เซ็ตให้ขา ST_CP มีสถานะเป็น HIGH
Timing Diagram
การส่งข้อมูลแต่ละบิตเข้าไปใหม่จะเลื่อนบิตเดิมไปทางขวาเรื่อยๆ หากส่งไปทั้งหมด 8 บิตจะทำให้ข้อมูลเก่าหายไปจนหมด และการเปลี่ยนแปลงผลจะเห็นได้ก็ต่อเมื่อ ST_CP มีสถานะกลับมาเป็น HIGH เท่านั้น
การใช้งานจริงกับหลอด LED
ในบทความนี้จะเลือกใช้บอร์ด Arduino ในการสาธิตการทำงาน สามารถต่อวงจรได้ดังนี้
ใน Arduino จะมีฟังก์ชั่น shiftOut() สำเร็จรูปอยู่แล้ว ทำให้สามารถข้ามขั้นตอนตั้งแต่ Step 2 ไปจนถึง Step 7 ได้เลย ทำให้ส่วนโค้ดจริงๆที่ใช้สำหรับส่งข้อมูลไปให้ไอซีมีแค่ส่วนนี้ (ผมเขียนเป็นฟังก์ชั่นไว้จะเรียกใช้งานได้ง่าย)
void DataOut(byte data) {
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, data);
digitalWrite(latchPin, HIGH);
}
ตัวอย่างโค้ดด้านล่างนี้เป็นโค้ดไฟวิ้งจากขวาไปซ้ายครั้งละดวง โดยใช้ชนิดตัวแปรเป็น byte แล้วเลื่อนบิตไปเรื่อยๆ
int latchPin = 8; // ST_CP
int clockPin = 12; // SH_CP
int dataPin = 11; // DS
byte tmp;
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
digitalWrite(latchPin, HIGH);
}
void loop() {
if (tmp==0||tmp==0x80) tmp=0x01;
else tmp=tmp<<1;
DataOut(tmp);
delay(500);
}
void DataOut(byte data) {
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, data);
digitalWrite(latchPin, HIGH);
}
การใช้งานจริงกับ 7 Segment
ไอซี 74HC595 เหมาะมากสำหรับการใช้งานกับ 7 Segment ถึงจะใช้งานได้ยากกว่าไอซีแปลงรหัส BCD แต่ไอซี 74HC595 ใช้สายน้อยกว่า
โค้ดด้านล่างนี้เป็นโค้ดที่ใช้หลักการคล้ายๆกับบทความที่แล้ว การใช้งาน 7 Segment กับ Arduino ตอนที่ 1 7 Segment หลักเดียว เพียงแต่คำสั่งที่ใช้ควบคุม 7 Segment เปลี่ยนจากการใช้รีจิสเตอร์ PORTD เป็นใช้ฟังก์ชั่น DataOut() ส่งไปให้ไอซี 74HC595 ขับแทน
int latchPin = 8; // ST_CP
int clockPin = 12; // SH_CP
int dataPin = 11; // DS
int num[] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F };
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
digitalWrite(latchPin, HIGH);
}
void loop() {
for (int i=0;i<10;i++) {
DataOut(~num[i]);
delay(500);
}
}
void DataOut(byte data) {
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, data);
digitalWrite(latchPin, HIGH);
}
การใช้งาน 74HC595 หลายตัว
บางครั้งพอร์ตที่เราต้องการจะใช้งานก็มีมากจนไอซี 74HC595 ตัวเดียวไม่พอใช้ จึงทำให้จะต้องใช้หลายตัวเพื่อให้มีขาใช้งานมากขึ้น
การใช้งาน 74HC595 หลายตัวสามารถทำได้โดยการต่อสาย SH_CP และ ST_CP ร่วมกับตัวแรก แต่ขา DS ให้ต่อเข้ากับขา Q7' ของตัวก่อนหน้านี้ (ดูรูปวงจรประกอบเพื่อให้เข้าใจได้ง่ายขึ้น)
การส่งข้อมูล จากเดิมที่ส่งข้อมูลไป 8 บิต ก็ต้องส่งข้อมูลไป 8 บิต * จำนวนไอซี เช่น ใช้ไอซี 74HC595 จำนวน 3 ตัว เมื่อส่งข้อมูลจะต้องส่งไปทั้งหมด 8 * 3 = 24 บิต
การใช้งานจริงกับหลอด LED โดยใช้ไอซี 74HC595 หลายตัว
ในตัวอย่างนี้จะใช้ไอซี 74HC595 จำนวน 2 ตัวในการขับ LED จำนวน 16 ดวงให้วิ้งตั้งแต่ดวงแรกไปจนถึงดวงสุดท้ายแล้วกลับมาเริ่มต้นใหม่ โดยเปลี่ยนโค้ดส่วนที่ใช้ส่งข้อมูลไปให้ไอซี 74HC595 เป็นดังนี้
void DataOut(unsigned int data) {
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, data>>8);
shiftOut(dataPin, clockPin, MSBFIRST, data&0xFF);
digitalWrite(latchPin, HIGH);
}
จากโค้ด จะเห็นว่าได้มีการใช้คำสั่ง shiftOut() จำนวน 2 ครั้ง หมายถึงการส่งข้อมูล 8 บิตหน้าให้ก่อน แล้วจึงใช้คำสั่ง shiftOut() อีกครั้งในการส่งอีก 8 บิตหลัง หรือถ้าให้เข้าใจง่ายๆ shiftOut() ตัวแรกควบคุม 74HC595 ตัวที่ 2 ส่วน shiftOut() ตัวที่ 2 ก็ควบคุม 74HC595 ตัวแรก หากใช้ไอซี 74HC595 หลายตัวมากขึ้น ก็ต้องใช้คำสั่ง shiftOut() มากขึ้น
โค้ดไฟวิ้ง 16 ดวงโดยใช้ 74HC595 2 ตัวขับแบบเต็มๆมีดังนี้
int latchPin = 8; // ST_CP
int clockPin = 12; // SH_CP
int dataPin = 11; // DS
int tmp=0;
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
digitalWrite(latchPin, HIGH);
}
void loop() {
if (tmp==0||tmp==0x8000) tmp=0x01;
else tmp=tmp<<1;
DataOut(tmp);
delay(100);
}
void DataOut(unsigned int data) {
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, data>>8);
shiftOut(dataPin, clockPin, MSBFIRST, data&0xFF);
digitalWrite(latchPin, HIGH);
}
ข้อมูลเพิ่มเติม
การต่อใช้งาน 74HC595 ร่วมกันหลายตัวต้องนำการกระทำระดับบิตเข้ามาเกี่ยวข้อง หากเลือกใช้ตัวแปรในการเก็บข้อมูลการติด-ดับของ LED เนื่องจากคำสั่ง shiftOut() สามารถส่งข้อมูลออกไปได้เพียงครั้งละ 8 บิต หรือ 1 ไบต์ จากในหัวข้อ การใช้งานจริงกับหลอด LED โดยใช้ไอซี 74HC595 หลายตัว จะเห็นได้ว่าผมได้เลือกใช้ตัวแปรชนิด unsigned int มาเก็บข้อมูล เนื่องจากตัวแปรชนิดนี้สามารถเก็บข้อมูลได้ 2 ไบต์ หรือเทียบเท่ากับการเก็บข้อมูลให้ 74HC595 จำนวน 2 ตัว
ส่งข้อมูลบิตสูงออกไปก่อนเสมอ หากดูจาก Timing Diagram จะเห็นได้ว่าเราจะต้องส่งข้อมูลบิตสูงที่สุดออกไปก่อน เป็นลักษณะการส่งข้อมูลลำดับบิตที่สูงที่สุด ลงมาจนถึงลำดับบิตที่ต่ำที่สุด ซึ่งการส่งข้อมูลบิตที่อยู่ในลำดับที่ 9-16 ไปก่อนทำได้โดยการเลื่อนให้บิตไปอยู่ลำดับที่ 1 - 8 แทน โดยใช้เครื่องหมายกระทำระดับบิต เลื่อนบิตไปทางขวา 8 ตัว (data>>8)
ลำดับบิต | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | |
ข้อมูล (data) | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | |
เลื่อนบิตไป 8 ลำดับ | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
ส่งข้อมูลบิตต่ำตามออกไป เมื่อส่งข้อมูลบิตสูงตั้งแต่บิตที่ 9 - 16 ออกไปแล้ว ต่อมาจึงส่งบิต 1 - 8 ตามออกไป แต่ในตัวแปร data มีข้อมูลแบบ 16 บิตอยู่ แต่ฟังก์ชั่น shiftOut() รองรับได้แค่ 8 บิต ดังนั้นจึงต้องตัดบิตที่ 9-16 ทิ้งไป เหลือแค่บิตที่ 1-8 ไว้ แล้วจึงส่งไปให้ฟังก์ชั่น shiftOut() ส่งข้อมูลออกไป , การตัดบิตที่ 9 - 16 ทิ้งไปทำได้ด้วยการนำมา and 0xFF (data&0xFF)
ลำดับบิต | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | |
ข้อมูล (data) | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | |
and 0xFF | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | |
ผลลัพธ์ | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 |
ในไมโครคอนโทรลเลอร์อื่นๆที่ไม่มีคำสั่ง shiftOut() ก็สามารถเขียนคำสั่ง shiftOut() เองได้ โดยอ้างอิงจาก Timing Diagram เป็นหลัก โค้ดด้านล่างนี้เป็นตัวอย่างของโค้ดไฟวิ้ง 16 ดวงใช้ 74HC595 เป็นตัวขับ ใช้ไมโครคอนโทรลเลอร์ PIC18F4550 ใช้ IDE เป็น MPLAB และใช้คอมไพลเลอร์เป็น C18
#include "p18f4550.h"
#include "delays.h"
/*
----- MAP ----
latchPin -> ST_CP
clockPin -> SH_CP
dataPin -> DS
*/
#define latchPin LATDbits.LATD2
#define clockPin LATDbits.LATD0
#define dataPin LATDbits.LATD1
void delay_ms(int ms) {
while(ms--)
Delay1KTCYx(5); // 20MHz
}
int ibit=0;
void shiftOut(char data) {
for (ibit=7;ibit>=0;ibit--) {
dataPin=(data>>ibit)&0x01;
delay_ms(1);
clockPin=1;
delay_ms(1);
clockPin=0;
}
dataPin=0;
}
void DataOut(unsigned int data) {
latchPin=0;
shiftOut(data>>8);
shiftOut(data&0xFF);
latchPin=1;
}
int tmp=0;
void main() {
TRISD=0;
LATD=0;
latchPin=1;
while(1) {
if (tmp==0||tmp==0x8000) tmp=0x01;
else tmp=tmp<<1;
DataOut(tmp);
delay_ms(100);
}
}
ทุกคนคงรู้จัก 7 Segment กันพอสมควรแล้ว เพราะเราต้องเคยเห็นในชีวิตประจำวันมาบ้าง |
7 Segment ก็คืออุปกรณ์แสดงผลตัวเลข 0-9 หรือตัวอักษรบางตัว โดยใช้หลอดไฟทั้ง 7 หลอดของมัน ,การติดหรือดับของหลอดไฟแต่ละ Segment ทำให้เกิดภาพตัวเลขหรือตัวอักษรต่างๆตามที่เราเห็นนั่นเอง |
ซึ่งจริงๆแล้ว 7 Segment ก็คือ LED 7 ดวงนี่เอง เพียงแต่มันถูกรวมอยู่ในตัวถังเดียวกัน เพราะฉะนั้น การใช้งานก็จะต้องมีการจ่ายไฟคล้ายกับ LED ทั่วไป คือมีไฟ + และไฟ - หรือ GND แต่ทั้งนี้ เพื่อไม่ให้ใช้จำนวนขาที่มากเกินไป จึงมีการออกแบบขาร่วม (Common) ขึ้นมาด้วย เพื่อประหยัดจำนวนขาใช้งานไปได้ถึงเท่าตัว โดยแบ่งออกเป็น 2 ประเภท |
• Common Anode หรือขาบวกร่วม |
• Common Cathode หรือขาลบร่วม |
จากภาพแสดงให้เห็นถึงหลักการทำงาน 7 Segment โดยไฟ LED ดวงที่ 1 - 7 (a-g) ทำหน้าที่แสดงตัวเลขหรือตัวอักษร ส่วนดวงที่ 8 (h) ทำหน้าที่แสดงจุดทศนิยม | |||||||||
โดยแบบ Common Anode และ Common Cathode มีความแตกต่างกันคือ ขาร่วมของ Common Anode จะเป็นไฟบวก และขาร่วมของ Common Cathode จะเป็นไฟลบหรือ GND ,ซึ่งความแตกต่างนี้เอง เป็นผลให้เราควบคุมการติดดับของ LED แต่ละดวงต่างกันทั้ง 2 ชนิดด้วยการควบคุมการติดดับของ LED แต่ละ Segmentการควบคุม LED แต่ละ Segment ขึ้นอยู่กับการจ่าไฟไปยัง Segment นั้นๆ แต่ไม่ได้หมายความว่า เมื่อจ่ายไฟบวกไปยัง Segment ใดๆ แล้ว Segment นั้นไฟจะติด เพราะมันขึ้นอยู่กับว่า 7 Segment ของเราเป็นแบบขาบวกร่วม หรือลบร่วม
|
ok.
ตอบลบ