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
   93   94   95   96   97   98   99   100   101   102   103