เทคนิคการขยาย Port Output ด้วย Shift Register

สำหรับ MCU เบอร์เล็กๆ ที่มีขา I/O ไม่มากนัก เช่น 89C2051 ถ้าเราต้องการขยาย Port แบบ Output ให้ได้เยอะๆ เช่นต้องการจะต่อ 7 Segment ซัก 30 ตัว ถึงจะใช้วิธี Scan Display ก็เถอะ ลองคำนวนดู ใช้ 8 bit สำหรับ data 7 segment และในแต่ละตัวก็ต้อง มีขา Common อีก สรุปว่าคงไม่พอครับ

เทคนิคหนึ่งที่นิยมใช้ก็คือใช้ Shift register ในการขยาย Port โดยเราจะใช้ขา data เพียง 3 ขาเท่านั้น Clock, Data,Strobe IC แต่ละผู้ผลิตอาจจะตั้งชื่อขาสัญญาณแตกต่างกันไปบ้างแต่หลักการเดียวกัน โดย Data จะส่งไปพร้อมกับ Clock หรือที่เรียกการส่งข้อมูลแบบนี้ว่า Synchronous

การต่อสาย 74HC595 แบบอนุกรมหลายตัว

IC ที่นิยมนำมาใช้จะเป็นเบอร์ที่ลงท้ายด้วย 595 เช่น 74HC595, 74LS595, TPIC6B595(Open Collector) การต่อใช้งานขา Data จาก MCU จะต่อเข้ากับ Data in ของตัวที่ 1 และ Data Out ของตัวที่ 1 จะต่อเข้ากับ Data in ของตัวที่ 2 เป็นอย่างนี้ไปเรื่อยๆจนถึงตัวสุดท้าย Data Out ของตัวสุดท้ายจะไม่ถูกต่อ

IC Shift register ตระกูล 595

สำหรับ Code ตัวอย่างนี้ สามารถนำไปประยุกต์ใช้ได้ทุกตระกูล MCS51, AVR, PIC หรือตระูกูลอื่นๆ

อธิบายฟังก์ชัน

Code นี้ต่อ 74HC595 ไว้ 4 ตัวอนุกรมกัน ใน 1 ตัว ตัวแปร Hc595[0] แทน 74HC595 ตัวที่ 1 ไปเรื่อยๆ จนถึง Hc595[3] แทน 74HC595 ตัวที่ 4 การเขียนข้อมูลในแต่ละ byte จะใช้ฟังก์ชัน void wrport8 (unsigned char dat) การส่งข้อมูลไปยัง 74HC595 ทั้ง 4 ตัวใช้ฟังก์ชัน void wrport() เริ่มจาก ให้ OE595 และ STR เป็น “0″ จากนั้นก็ส่งข้อมูล Hc595[0]…Hc595[3] ตอนนี้ข้อมูลจะถูกเก็บไว้ใน D-flipflop ใน 74HC595 แล้ว แต่ยังไม่ถูกส่งออกมายัง Port ข้อมูลจะถูกส่งออกมายัง Port หลังจากส่ง Pulse ไปยัง STR

Code Example

#define SCK_DDR ??DDRB.3??//????????????
#define SDO_DDR ??DDRB.2??//
#define STR_DDR ??DDRB.1??//??
#define OE595_DDR ??DDRB.0??//??#define SCK ???PORTB.3??//
#define SDO ???PORTB.2??//??
#define STR ???PORTB.1??//?????
#define OE595 ???PORTB.0??//??

//—————————————————————————
// Write serial data
//—————————————————————————
void wrport8 (unsigned char dat)
{
?unsigned char cnt,a;
?for (cnt = 0;cnt < 8;cnt++){
??if (dat & 0×80)
???SDO = 1;
??else
???SDO = 0;
??dat <<= 1;
??a = 5;?while(a)?a–;
??SCK = 1;
??a = 5;?while(a)?a–;
??SCK = 0;
?}
}
//—————————————————————————
// Write serial data
//—————————————————————————
void wrport()
{???????????
//?unsigned char a;
?OE595 = 0;
?STR = 0;

? ?wrport8(Hc595[0]);
?wrport8(Hc595[1]);
? ?wrport8(Hc595[2]);
?wrport8(Hc595[3]);?

?STR = 1;????
?STR = 1;?
?STR = 1;?
//?a = 10;?while(a)?a–;
?STR = 0;
}?

สร้างเสียงดนตรีด้วย Microcontroller MCS-51

โปรเจคนี้ผมทำขึ้นตอนที่เรียนอยู่ลาดกระบังครับ โดย อ. ให้คิดโปรเจคง่ายๆ ใช้ไมโครคอนโทรลเลอร์เขีียนโปรแกรม เลยมาเป็นโปรเจคนี้ ผมคิดว่าทุกท่านคงรู้จัก Mini organ คือมันก็คล้ายๆกับ Electone หรือ Keyboard นั่นแหล่ะเพียงแต่มันมีตัวโน๊ตไม่เยอะ ตอนที่เรียนนั้นเถียงกับ อ.แทบตาย โดยทาง อ.บอกว่าผมไม่สามารถ Generate ความถี่ออกมาที่ลำโพงได้เพราะ MCU ต้องไป Scan Key ด้วย ผมก็เถียงว่ามันทำได้

หลักการทำงาน

89C52 จะ Scan Key ไปทีละ row และ Column เมื่อเจอ Key ไหนกดก็จะสร้างสัญญาณ Logic”0″ และ Logic”1″ จากขา P3.5 เป็นสัญญาณ Square wave โดยค่า Time delay ในแต่ละปุ่มจะไม่เท่ากัน ทำให้ความถี่ของแต่ปุ่มมีเสียงเทียบได้กับตัวโน๊ตดนตรี โด เร มี ฟา ซอล ลา ที โด เมื่อสร้าง Square wave มาครบ 1 ลูกแล้ว 89C52 จะเช็คอีกว่ามีการปล่อย Key ยังถ้ายังไม่ปล่อยก็ generate เสียงต่อไป ถ้ามีการกด Key ใหม่ก็จะ Generate โทนเสียงใหม่วน loop ไปเรื่อยๆ

?

?;*********************************
;Microcontroller mini organ
;Pragrammer:Pratchaya Tongthong????
;*********************************
;P3.5 —-> SPEAKER????
MSEC??EQU??7FH
S_CODE??EQU??7DH
KEY???EQU??7CH??
S_CODE??EQU??7DH
NOTE1??EQU??7BH
NOTE2??EQU??7AH
KEYBUF??EQU??79H
PNTERHI??EQU??78H
PNTERLO??EQU??77H
DURATION?EQU??76H
;***********************************************
;Start? Scan key
;***********************************************INIT:??ACALL?SCAN?
???CJNE?A,#00,SONG
???SJMP??INIT
???
SCAN:??MOV??S_CODE,#00H???????
???MOV??P1,#0FFH???????
???SETB?P3.0
???SETB?P3.1
???SETB?P3.2??
???
???CLR ?P3.0????? ;Scan first column
???MOV??A,P1
???CJNE?A,#0FFH,CONVERT
???SETB?P3.0
???MOV??A,S_CODE?????
???ADD??A,#08
???MOV??S_CODE,A??
??????????????????????????????????????????????????
???CLR??P3.1????? ;Scan second column
???MOV??A,P1
???CJNE??? A,#0FFH,CONVERT
???SETB?P3.1????
???MOV??A,S_CODE?????
???ADD??A,#08
???MOV??S_CODE,A??
???
???CLR??P3.2????? ;Scan third column
???MOV??A,P1????
???SETB?P3.2?
???CJNE?A,#0FFH,CONVERT
???MOV??S_CODE,#00H
???SJMP??END
CONVERT:?INC??S_CODE???
???JNB??ACC.0,END
???RR??A
???SJMP?CONVERT
END:??MOV??KEY,S_CODE????
???MOV??A,KEY
???CJNE?A,#00,END1
???RET?
END1:??MOV??DPTR,#NOTE_1??
???MOV??A,KEY
???MOVC?A,@A+DPTR
???MOV??NOTE1,A? ????
???MOV??DPTR,#NOTE_2??
???MOV??A,KEY
???MOVC?A,@A+DPTR
???MOV??NOTE2,A
???RET
???
;***********************************************
;Generate Tone
;***********************************************
SONG:??CLR??P3.5
???ACALL?PERIOD
???SETB?P3.5
???ACALL?PERIOD
???MOV??P1,#0FFH
???MOV??A,P1
???CJNE?A,#0FFH,SONG
???SJMP?INIT
PERIOD:??MOV??R0,NOTE1
L1:???MOV??R1,#48
???DJNZ?R1,$
???NOP
???DJNZ?R0,L1
???MOV??R0,NOTE2
???DJNZ?R0,$
???RET
;***********************************************
;Note1 and Note2
;***********************************************??
NOTE_1:??DB??0,23,20,18,17,16,15,14,13,13,12,11,10,10,9,9,8,8,7,7,6
NOTE_2:??DB??0,20,42,27,24,23,28,33,42,08,17,32,48,18,38,11,34,9,36,14,43?

ทดสอบ

ผมลองเล่นเพลง Happy Birthday ครับ เสียงที่ออกมาก็ OK เลยไม่ผิดเพี้ยน

Download Assembly Code

การทดลองที่ 5 Scan 7 Segment

การเขียนโปรแกรมเพื่อแสดงตัวเลข 7 segment จะใช้หลักการ ให้ตัวเลขติดทีละหลัก เรียงกันไปด้วยความถี่ที่ตาคนเราแยกไม่ออก ปกติแล้วจะใช้ interrupt timer มาเป็นฐานเวลาในการสแกนตัวเลข เนื่องจากให้คาบเวลาที่แน่นอน ถ้าเขียนโปรแกรมวนลูปใน while(1) เวลาไมโครคอนโทรลเลอร์ประมวลผลอย่างอื่นไปด้วย ตัวเลข 7 segment จะกระตุก

7 Segment ที่ผมเอามาทดลองนี้ เค้าขายอยู่ข้างทางแพ๊คละสิบบาทมีอยู่ 10 ตัวหน้าตาเป็นแบบนี้ครับ แบบนี้จะ wire สายหรือทำ PCB ง่ายหน่อย เพราะ 4 หลักใช้ขา common ร่วมกัน

รูปที่ 1

เทียบกับเหรียญบาทครับ

รูปที่ 2

ในการทดลองนี้ผมเอาไปต่อกับ Key up และ Key Down เพื่อเปลี่ยนแปลงค่าตัวเลข ถ้าใครจะไปประยุกต์ใช้กับงานอื่นก็ copy ส่วนสแกน 7 segment ไปใช้ได้ครับ

หลังจากต่อวงจรเสร็จ ให้โปรแกรม HEX ลง 89S52 จะเห็นตัวเลขติด 0000 ถ้าไม่ได้ตามนี้ลองกลับไปเช็ควงจรดูนะครับ ลองกด Key up ดูครับถ้ากดแล้วปล่อยจะเพิ่มทีละ 1 ค่า ถ้ากดค้างจะเห็นตัวเลขเพิ่มขึ้นอย่างต่อเนื่อง ส่วน Key Down ก็เป็นในทางตรงกันข้ามกับ Key Up คือเมื่อกดแล้วปล่อยค่าจะลดลงทีละ 1 ค่า เมื่อกดค้างค่าจะลดลงไปเรื่อยๆ

null

รูปที่ 3 วงจรที่ใช้ในการทดลอง

รูปที่ 4 ทำการทดลองในแผ่นปริ๊นต์อเนกประสงค์

Download Code การทดลองที่ 5