เขียนโปรแกรม MCS-51 ขยาย Port Input แบบไม่จำกัดด้วย CD4021

ในการออกแบบให้ microcontroller รับอินพุตดิจิตอลวิธีที่ตรงไปตรงมาที่สุดคือการต่อกับ Port ของ microcontroller โดยตรง แต่ถ้าอินพุตมีจำนวนมากซัก 10-20 อินพุต เราจะทำยังไง หลายคนอาจจะใช้วิธี Scan Keyboard เอา วิธีนี้มีข้อจำกัดตรงที่แต่ละอินพุตไม่อิสระต่อกัน เพราะต่อแบบ matrix

แล้วมีวิธีที่ดีกว่านี้อีกไหม? คำตอบคือมีครับ คือใช้ Shift register รับข้อมูลแบบขนาน แล้วให้สัญญาณออกมาเป็นแบบอนุกรม (Parallet in/ Serial put) โดยใช้ IC CD4021 ภายใน IC จะประกอบไปด้วย flip-flop เมื่อเราส่ง clock ไป 1ลูก data ที่ flip-flop จะส่งไปยังตัวถัดไป ถ้าเราส่ง clock ไป 8 ลูก เราก็จะได้ data จาก 8 อินพุต

จากรูปจะเห็นว่าเอาต์พุตของ flip-flop ตัวซ้าย จะเป็นอิพุตของ flip-flop ตัวขวาไปเรื่อยๆ สำหรับ data จะอยู่ที่ขา Q6, Q7, Q8 เวลาใช้งานจริงเราต่อที่ Q8 ตัวเดียวก็พอครับ ส่วน Q6, Q7 ก็ปล่อยลอยไว้ IC CD4021 1 ตัวจะต่ออินพุตได้ 8 อินพุต แต่เราสามารถต่อ IC CD4021อนุกรมกันไปได้เรื่อยๆ โดยต่อ Q8 เข้ากับ Serial input ไปเรื่อยๆ

ทีนี้มาดูในส่วนของการเขียนโปรแกรมกัน โปรแกรมตัวอย่างจะใช้ 89S52 MCS-51 เบอร์ยอดนิยมของผม

ด้านล่างจะเป็น function อ่านค่าจาก CD4021 ที่ที่อ่านได้จะ return กลับมา

//===============================================//
//??? ??? ??? ??? ??? ??? ??? ??? ?? Read data from CD4021
//===============================================//
unsigned char read_cd4021()
{
unsigned char i,a,inport,dat;

STR = 1;
STR = 0;
a = 4;??? while(a)??? a–;
dat = 0;
for (i=0;i<8;i++)
{
inport = DAT;
dat <<= 1;
dat |= inport;

CLK = 1; ??? a = 4;??? while(a)??? a–;
CLK = 0;??? ??? a = 4;??? while(a)??? a–;

}
STR = 1;

return(dat);
}

อันนี้ main()

//———————————————————–//
// Main
//———————————————————–//
void main()
{
init();
dmsec(200);??? ??? ??? //at least 100 mS
init_lcd();
dmsec(200);??? ??? ??? //at least 100 mS

show_portval_lcd();
while(1)
{
port_present = read_cd4021();
if(port_last!=port_present)
{
port_last = port_present;
show_portval_lcd();
dmsec(200);
}
}
}

ในการทดลองนี้ผมจะต่อ LCD 16×2 แสดงผลค่าที่อ่านได้จาก port โดยใช้อินพุตเป็น DIP Switch ขนาด 8 สวิตช์ มาดูส่วนของวงจรกันต่อ

การทดลองนี้ต่อ IC CD4021 ลง Proto board ครับ ทดลองเสร็จก็ไปใช้งานอื่นๆได้ต่อสะดวกดี ต่ออุปกรณ์เสร็จแล้ว ทดลองกันเลยดีกว่า

ในตอนสวิตช์ไม่สับลง GND ก็แสดงค่า 255 อันนี้ถูกต้องครับ ต่อมาสับสวิตช์ 1 และ 2 ไปที่ GND ถ้าเทียบเป็นเลขฐาน 2 จะได้ 11111100 = 252 สังเกตุว่าเท่ากับที่หน้าจอ LCD แสดงผล เป็นอันว่าอ่านค่าได้ถูกต้อง

Download

datasheet CD4021

source code CD4021(zip)

รวมคำถาม-คำตอบ ไมโครคอนโทรลเลอร์ที่ถามกันบ่อย

บทความนี้ผมจะรวบรวมคำถามที่เจอบ่อยๆในหมวด Microcontroller,? Electronics มาตอบให้ตามความรู้และประสบการณ์ของผม หากสงสัยอะไรก็ comment ด้านล่างมาถามได้ครับ หากตอบได้ก็จะตอบให้ หรือไม่รู้ก็จะพยายามหามาตอบให้ครับ

1. ทำไมต้องใช้คริสตอลความถี่ 11.0592 MHz ในวงจร Microcontroller MCS-51 ด้วย

- เพราะเป็นค่า XTAL ที่คำนวน Baud rate ในการรับ/ส่งข้อมูลแบบ Asynchronous (UART) ได้เลขที่ลงตัว เช่น Baud rate 19,200 9,600 4,800 2,400 bps

2. Microcontroller ตระกูลไหนดีที่สุด

- ในความเป็นจริง ไม่มีตัวไหนดีที่สุดในทุกๆด้าน แต่ละตระกูลก็มีจุดเด่นจุดด้วยต่างกันไป เช่น ตระกูล MCP ของ Texus Instrument (TI) มีจุดเด่นเรื่องกินไฟต่ำ แต่ develepe tool ไม่แพร่หลาย มีคนใช้น้อย, ตระกูล MCS-51 ใช้งานง่ายเป็นที่แพร่หลาย ราคาถูก แต่ไม่ทน noise ต้องต่ออุปกรณ์ interface มาก ฯลฯ

3. จริงไหมที่ Microcontroller MCS-51 ไม่ทน noise

- จากประสบการณ์ การทำงานของผม ทำเครื่องมือวัดในโรงงานอุตสาหกรรมซึ่งมี noise รบกวนมาก ถ้าให้ออกแบบเครื่องมือวัดที่ทำงานเหมือนกัน ออกแบบดีที่สุดเหมือนกัน MCS-51 จะไม่ค่อยผ่าน noise แต่ถ้าเป็นพวก PIC, AVR จะทำงานได้

เมื่อเจอ noise MCS-51 จะแฮงค์ แต่ข้อดีของ MCS-51 คือเวลาต่อไฟกลับขั้วหรือไฟเกินมานิดหน่อยจะไม่พัง ในขณะที่ PIC จะพังทันที

4. สถาปัตยกรรมแบบ CISC (Complex Instruction SetComputer) เป็นยังไง

- เป็นสถาปัตยกรรมที่มีคำสั่งใช้งานมากเป็นร้อยคำสั่ง เป็นสถาปัตยกรรมในยุคแรกของคอมพิวเตอร์ ในแต่ละคำสั่งจะใช้ cycle ในการประมวลผลไม่เท่ากัน ตามความซับซ้อนของการประมวลผล ข้อดีคือมีคำสั่งให้เลือกใช้มาก การพัฒนาด้วยภา๋ษา Assemble จะทำได้ง่ายกว่าสถาปัตยกรรมแบบ RISC

5. สถาปัตยกรรมแบบ RISC (Reduced Instruction Set Computing) เป็นยังไง

- เป็นสถาปัตยกรรมที่มีคำสั่งใช้งานน้อย ส่วนมากจะไม่กี่สิบคำสั่ง เช่นคำสั่งบวก, ลบ, (บางตระกูลก็ไม่มีคูณและหาร), กระโดด (jump), เปรียบเทียบ (compare) ด้วยเหตุที่ว่ามีชุดคำสั่งน้อยทำให้มีโครงสร้าง Microcontroller ไม่ซับซ้อน ผลที่ได้ตามมาคือกินไฟน้อย และทำงานได้เร็ว Microcontroller แบบ RISC จะมีเทคนิคที่เพิ่มความเร็วในการประมวลผลเรียกว่า Pipeline โดยจะทำการประมวลผลคำสั่งแบบขนานกันไป

สมมุติว่า 1 คำสั่งใช้เวลา 5 cycle ในการประมวลผล ในขณะที่กำลังจบ cycle 1 ของคำสั่ง 1 ใน cycle ต่อไปจะประมวลผล cycle 2 ของคำสั่ง 1 และ cycle 1 ของคำสั่ง 2 ขนานกันไป n ชั้น โดนที่ n คือจำนวนชั้นของ Pipeline ที่มี Microcontroller นั้น

ข้อเสียของ RISC คือทำให้ผู้ใช้งานเขียน code ยากขึ้น (ถ้าใช้ assembly) เนื่องจากต้องใช้หลายคำสั่ง เช่น PIC ตระกูล 16Fxxx ไม่มีคำสั่งคูณ ต้องใช้วิธี Shift bit เอาหรือไม่ก็บวกกันหลายๆที ทำให้เปลือง memory ด้วย

ในอนาคตมีแนวโน้มจะไปพัฒนาสถาปัตยกรรมทางด้าน RISC มากกว่า CISC

Watchdog Timer สำหรับ 89S52 ใน Keil

ถ้าพูดถึงไมโครคอนโทรลเลอร์ตระกูล MCS-51 ที่ผมชอบใช้ ก็เป็นเบอร์ 89S52 เนื่องจากมีราคาที่ถูกมาก และที่ถูกอกถูกใจคือผมไม่ต้องถอด IC มา burn เหมือนแต่ก่อนแล้ว ผมต่อสายจาก parallel port มา burn IC ได้เลย (ISP Programming) สะดวกกว่า ICD2 ของ Microchip เสียอีก

เอาละมาเข้าเรื่องกันดีกว่า มันมีอยู่งานนึงที่ผมใช้ 89S52 แต่มันเป็นงานที่ทำตลอด 24 ชั่วโมง ฉะนั้นมันแฮงค์ไม่ได้เลย ผมจำได้ว่า 89S52 มันมี Watchdog Timer ในตัวด้วย เลยไม่รอช้าเปิด datasheet มาดู เค้าบอกว่าอย่างนี้

การที่จะ Enable ให้ Watchdog ทำงานนั้นให้เขียนข้อมูล 0x1E และ 0xE1 ลงไปใน register WDTRST ต้องเขียนต่อกันเลยนะถึงจะใช้ได้ ส่วน Watchdog Timer ตัวนี้เป็น Counter 13 บิตแล้วจะนับขึ้นทุก machine cycle แล้วถ้าปล่อยให้นับได้ถึง 8191 (0x1FFF) เมื่อไหร่ละก็ จะเกิดการรีเซต ฉะนั้นเราต้องเขียนโปรแกรมไปคอยเคลียร์ไม่ให้ Watchdog Timer มันนับไปถึงค่า Overflow 8191

การเคลียร์ Watchdog Timer ก็ทำเหมือนกับ enable นะแหล่ะ ก็เขียนข้อมูล 0x1E และ 0xE1 ลงไปใน register WDTRST ถ้าอยากรู้ว่า 8191machine cycle นี่นานขนาดไหนมาลองคำนวนเล่นๆกันดีกว่า

ตัวอย่าง สมมุติว่าใช้ XTAL 11.0592 MHz แล้ว clock 12 ลูกจะได้ 1 machine cycle

T = (8191*12)/(11059200) = 8.887 mS ฉะนั้นเราต้องไปเคลียร์ Watchdog Timer ทุกๆ 8.8 mS เป็นอย่างน้อย หรือใครจะเคลียร์ทุกๆ 1 mS ก็ยิ่งดี ส่วนตัวเลข 8191 นี่เค้ากำหนดมาตายตัว เราไม่สามารถ scale ได้

ลองดู code ที่จะนำไปใช้กับ Compiler keil ดู

อันดับแรกเราก็ต้องประกาศ sfr (Speacial Function Register) ก่อนเพราะใน AT89X52.h ไม่ได้ประกาศ register WDTRST มาให้

sfr WDTRST = 0xa6;
sfr AUXR = 0x8e;

จากนั้นก็ Enable และ เคลียร์ด้วย Sub void kickdog()

void kickdog()??????????????????????????????? //every 8191 Machine Cycle
{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //~8 ms
WDTRST = 0x1e;
WDTRST = 0xe1;
}

จากนั้นเราก็หาที่วาง void kickdog() ใน function ต่างๆ (แนะนำว่าควรวางใน loop while(1) )? เพียงเท่านี้ 89S52 ของเราก็ทำงานได้นานแสนนาน โดยที่ไม่แฮงค์ (ถึงแฮงค์ก็รีเซตตัวเองขึ้นใหม่ได้)