Page 98 - 22-0722 EBOOK
P. 98
วารสารราชบััณฑิิตยสภา
ปีีที่่� ๔๖ ฉบัับัที่่� ๓ กัันยายน-ธัันวาคม ๒๕๖๔
88 การแลกเปล่�ยนข้้อมููลแบบอนุกรมูระหว่่างไมูโครคอนโทรลเลอร์โดยใช้้เกณฑ์์ว่ิธี่ข้องแผงแป้นอักข้ระ
ในี้การรับข้้อมูล ไมโครคอนี้โทรลเลอร์ PIC16F627A จะเปล้�ยนี้ทิศทางข้องข้้อมูลท้�ข้า RB0
และ RB1 จากออกเป็นี้เข้้า เพิ่�อให้สายสัญญาณนี้าฬิิกา (CLK) และสายสัญญาณข้้อมูล (DAT) ไปอยู่ในี้
ความควบคุมข้องแผงวงจรตััวหลัก จากนี้ั�นี้จ่งใช้้กระบวนี้คำาสั�ง ChkHstReq คอยตัรวจดูว่า แผงวงจร
ตััวหลักพิร้อมท้�จะส่งข้้อมูลแล้วหร่อไม่ เม่�อพิบว่าแผงวงจรตััวหลักพิร้อมแล้ว ก็เริ�มรับข้้อมูลแตั่ละไบตั์
ตัามเกณฑ์์วิธี้ท้�แสดงไว้ในี้ภาพิท้� ๓ โดยเข้้าควบคุมสายสัญญาณนี้าฬิิกาเส้ยเอง และอาศัยกระบวนี้คำาสั�ง
RcvHdat (ซ่�งในี้ตัอนี้ท้ายจะส่งบิตั ACK ไปยังแผงวงจรตััวหลักเพิ่�อย่นี้ยันี้ว่าได้รับบิตัตั่าง ๆ ครบแล้ว)
หลังจากท้�ได้รับข้้อมูลแตั่ละไบตั์ แผงวงจรตััวรองก็จะแสดงไบตั์ข้้อมูลทางไดโอดเปล่งแสงท้�ตั่อกับข้า
RB7-RB0 โดยอาศัยกระบวนี้คำาสั�ง ShowDat เพิ่�อจะได้ทวนี้สอบกับไบตั์ข้้อมูลท้�แผงวงจรตััวหลักส่งมา
ในี้การสิ�นี้สุดการทำางานี้หลังจากได้รับข้้อมูลครบตัามจำานี้วนี้ท้�กำาหนี้ดไว้ (ในี้ท้�นี้้�ค่อ ๑๑ ไบตั์)
ไมโครโพิรเซสเซอร์ PIC16F627A จะใช้้วิธี้เข้้าสู่วงวนี้ไม่รู้จบในี้กระบวนี้คำาสั�ง QuitProg ในี้ตัอนี้ท้าย
ข้องชุ้ดคำาสั�งหลัก ซ่�งจะแสดงแสงกะพิริบจากไดโอดเปล่งแสงท้�ตั่ออยู่กับข้า RB7-RB0 พิร้อมกันี้ไปด้วย
//Page 1/3 of Fig.9 //Page 2/3 of Fig.9
//Serial-data exchange int ChkHstReq(void) //test if CLK=hi & DAT=lo
//between uC PIC16F627A and uC 8088 //return 0 => uC 8088 ready to send bit0
//Program name: PIC16FKB.C //return -1 => uC 8088 not ready
//Date: April 15, 2021 { int tcnt=0;
//To be used with PIC16F627A at 8 MHz INTCON = 0x00; //prevent all INTs
//use MikroC IDE to compile and link TRISA.F0 = 1; //RA0 <= DAT sense input
//with _HS_OSC = $3FEE in Project configuration TRISA.F1 = 1; //RA1 <= CLK sense input
//put PIC16KB.HEX into PIC16F627A by using
//WinPic software with Config Word#1 = 3F6A and //count until CLK=hi
//Config Word#2 = 3FFF in “Device Config” pane while (PORTA.F1==0) {Delay_us(4); tcnt++;}
//RA0->DAT line (I/O)->100 ohm->PA4 of uC 8088 //case of CLK=0 duration too long
//RA1->CLK line (out)->100 ohm->PA7 of uC 8088 if (tcnt > 19) return (-1);
//RB7-RB0 used for data byte display via LEDs tcnt = 0; //reset time count
//count until DAT=lo
unsigned char buf[32]; while (PORTA.F0!=0) {Delay_us(4); tcnt++;}
unsigned char bits[] = {1,2,4,8,16,32,64,128}; //case of DAT=hi duration too long
if (tcnt > 19) return (-1);
void ShowDat(unsigned char ch0) //Now CLK=hi & DAT=lo (Startbit)
//display char data on RB7-RB0 LEDs return (0); //8088 ready to send bit0
{ TRISB = 0x00; //RB7-RB0 => outputs } //ChkHstReq
PORTB = ch0; //ch0 shown on PORTB LEDs
Delay_ms(500); //0.5-sec delay unsigned char RcvHdat(void)
PORTB = 0x00; //all PORTB LEDs off //receive data from uC 8088
Delay_ms(500); //after its request to send: CLK=lo->hi
} //ShowDat { unsigned char clk, start, dat[10], stop;
unsigned char par, calpar=1, cmd=0;
void SendKdat(unsigned char ch1) int i;
//CLK period = 100 us; CLK freq = 10 kHz //When CLK=hi and Startbit=lo,
//send data with sync clock to uC 8088 //prepare to receive 10 bits from uC 8088
{ int k; Delay_us(100);
unsigned char ref = 0x01; TRISA.F0 = 1; //RA0 <= DAT input
TRISA.F0 = 0; //RA0 => DAT output TRISA.F1 = 0; //RA1 => CLK output
TRISA.F1 = 0; //RA1 => CLK output //bring CLK=lo during Startbit
PORTA.F1 = 0; Delay_us(50);
//Startbit = 0
PORTA.F0 = 0; Delay_us(10); //bring DAT=lo //get 8 data bits + Parity bit + Stopbit
PORTA.F1 = 0; Delay_us(50); //bring CLK=lo for (i=0; i < 10; i++)
PORTA.F1 = 1; Delay_us(40); //let CLK=lo->hi { //set CLK=hi for uC 8088 to send data
PORTA.F1 = 1; Delay_us(50);
ภาพท่� ๙ ซอฟตั์แวร์การส่ง-รับข้้อมูลแบบอนีุ้กรมข้องไมโครคอนี้โทรลเลอร์ PIC16F627A
//next 8 work data bits //read data bit during CLK=hi
for (k=0; k<8; k++) dat[i] = PORTA.F0;
{ if ((ch1 & ref)==0) { PORTA.F0 = 0; } //bring CLK=lo to end current bit read
else { PORTA.F0 = 1; } PORTA.F1 = 0; Delay_us(50);
Delay_us(10); }
//bring CLK=lo, let uC 8088 read bit par = dat[8]; stop = dat[9];
PORTA.F1 = 0; Delay_us(50);
//set CLK=hi, prepare to change bit //Now send ACK=lo bit to uC 8088
PORTA.F1 = 1; Delay_us(40); TRISA.F0 = 0; //RA0 => DAT output
ref = ref << 1; //for next higher bit //DAT=lo for ACK
} //end for PORTA.F0 = 0; Delay_us(10);
//CLK=hi for 50 us
//Parity bit = 0 (for simple demo) PORTA.F1 = 1; Delay_us(50);
PORTA.F0 = 0; Delay_us(10); //bring DAT=lo //CLK=lo, let uC 8088 read ACK bit
PORTA.F1 = 0; Delay_us(50); //bring CLK=lo PORTA.F1 = 0; Delay_us(50);
PORTA.F1 = 1; Delay_us(40); //let CLK=lo->hi
//release CLK & DAT lines
//Stopbit = 1 PORTA.F1 = 1; Delay_us(20); //CLK=hi
//set RA0=hi, release DAT line PORTA.F0 = 1; //DAT=hi => Idle State
PORTA.F0 = 1; Delay_us(10); //calculate parity (skipped here)
//bring RA1=CLK=lo //for (i=0; i < 8; i++)
PORTA.F1 = 0; Delay_us(50); //{ calpar = calpar^dat[i]; }
//let RA1=lo->hi, release CLK line ////case of parity error
PORTA.F1 = 1; Delay_us(40); //if (calpar!=par) {QuitProg(0x07);}
} //SendKdat ////case of Stopbit error
//if (stop==0) {QuitProg(0x0F);}
void QuitProg(unsigned char errcode) //assemble code from dat[i], i=0, 1, ...,7
//get in endless loop for (i=0; i < 8; i++)
{ while(1) { showdat(errcode); } { if (dat[i]!=0) { cmd=cmd + bits[i]; }; }
} //QuitProg return cmd;
} //RcvHdat
//Page 3/3 of Fig.9
void main()
{ unsigned char ch1;
unsigned int i, j, ReqFlag, tcnt=0;
//turn off comparators on RA3-RA0
CMCON = 0x07; //PORTA=digital I/O port
//at start, turn 8 LEDs ON and OFF 5 times
for (j=0; j<5; j++) ShowDat(0xFF);
// *********************************
//Send 10 bytes to uC 8088
INTCON = 0x00; //prevent all INTs
//put 10 bytes (ASCIIs ’0’-‘9’) in buffer
for (i=0; i<10; i++)
{ buf[i]=(unsigned char)(48+i); } //(0x30+i)
for (j=0; j<10; j++)
{ //wait for Idle State (CLK=DAT=hi)
TRISA.F0 = 1; //RA0 <= DAT sense input
TRISA.F1 = 1; //RA1 <= CLK sense input
while (PORTA.F1==0) { } //wait for CLK=hi
while (PORTA.F0==0) { } //wait for DAT=hi
//show and send data in buf[]
ShowDat(buf[j]); SendKdat(buf[j]);
//wait 2 s for 8088 to show received data
Delay_ms(2000);
} //end for
//allow 1 sec for 8088 to settle down