日韩床上生活一级视频|能看毛片的操逼网站|色悠悠网站在线观看视频|国产免费观看A淫色免费|国产av久久久久久久|免费A级视频美女网站黄|国产毛片av日韩小黄片|热久久免费国产视频|中文字幕无码色色|成人在线视频99久久久

機電之家資源網(wǎng)
單片機首頁|單片機基礎(chǔ)|單片機應(yīng)用|單片機開發(fā)|單片機文案|軟件資料下載|音響制作|電路圖下載 |嵌入式開發(fā)
培訓(xùn)信息
贊助商
PC機與單片機的通訊程序
PC機與單片機的通訊程序
 更新時間:2008-7-26 19:45:29  點擊數(shù):3
【字體: 字體顏色

 

    以上信號在通訊過程之中可能會被全部或部分使用,最簡單的通訊僅需TXD及RXD及SG即可完成,其他的握手信號可以做適當(dāng)處理或直接懸空,至于是否可以懸空這視乎你的通訊軟件。比如說,如果使用DOS所提供的BIOS通訊驅(qū)動程序,那么,這些握手信號則需要做如下處理,因為BIOS的通訊驅(qū)動使用了這些信號。如果使用自己編寫的串行驅(qū)動程序則可以完全不使用這些握手信號(詳見下面有關(guān)章節(jié))。

      PC機一般使用8250或16550的作為串行通訊控制器,8250及16550的管腳排列如下:

      8250(16550)的寄存器如下表所示:

    PC機支持1-4個串行口,即COM1-COM4,其基地址在BIOS數(shù)據(jù)區(qū)0000:0400-0000:0406中描述,對應(yīng)地址分別為3F8/2F8/3E8/2E8,COM1及COM3使用PC機中斷4,COM2及COM4使用中斷3。

      在上表中,8250共有12個寄存器,使用了8個地址,其中部分寄存器共用一個地址,由DLAB=0/1來區(qū)分,在DLAB=1用于設(shè)定通訊所需的波特率。常用的波特率參數(shù)見下表:

 

 

      以下幾個表格為8250的寄存器的功能描述:

  中斷允許寄存器(IER):

      Bit0置1將允許接收到數(shù)據(jù)時產(chǎn)生中斷,Bit1置1時允許發(fā)送保持寄存器空時產(chǎn)生中斷,Bit2置1將在LSR變化時產(chǎn)生中斷,相應(yīng)的Bit3置位將在MSR變化時產(chǎn)生中斷。

  中斷識別寄存器(IIR):

      IIR為只讀寄存器,Bit6:7用來指示FIFO的狀態(tài),均為0時則無FIFO,此時為8250或16450芯片,為01時有FIFO但不可以使用,為11時FIFO有效并可以正常工作。Bit3用來指示超時中斷(16550/16750)。

      Bit0用來指示是否有中斷發(fā)生,Bit1:2標(biāo)識具體的中斷類型,這些中斷具有不同的優(yōu)先級別,其中LSR中斷級別最高,其次是數(shù)據(jù)就緒中斷,然后是發(fā)送寄存器空中斷,而MSR中斷級別最低。

  FIFO控制寄存器(FCR):

      FCR可寫但不可以讀,該寄存器用來控制16550或16750的FIFO寄存器。Bit0置1將允許發(fā)送/接收的FIFO工作,Bit1和Bit2置1分別用來清除接收及發(fā)送FIFO。清除接收及發(fā)送FIFO并不影響移位寄存器。Bit1:2可自行復(fù)位,因此無需使用軟件對其清零。Bit6:7用來設(shè)定產(chǎn)生中斷的級別,發(fā)送/接收中斷將在發(fā)送/接收到對應(yīng)字節(jié)數(shù)時產(chǎn)生。

  線路控制寄存器(LCR):

      LCR用來設(shè)定通訊所需的一些基本參數(shù)。Bit7為1指定波特率因子寄存器有效,為0則指定發(fā)送/接收及IER有效。Bit6置1會將發(fā)送端置為0,這將會使接收端產(chǎn)生一個“間斷”。Bit3-5用來設(shè)定是否使用奇偶校驗以及奇偶校驗的類型,Bit3=1時使用校驗,Bit4為0則為奇校驗,1為偶校驗,而Bit5則強制校驗為1或0,并由Bit4決定具體為0或1。Bit2用來設(shè)定停止位的長度,0表示1位停止位,為1則根據(jù)數(shù)據(jù)長度的不同使用1.5-2位停止位。Bit0:1用來設(shè)定數(shù)據(jù)長度。

  MODEM控制寄存器(MCR):

      MCR寄存器可讀可寫,Bit4=1進入環(huán)路測試模式。Bit3-0用來控制對應(yīng)的管腳。

  線路狀態(tài)寄存器(LSR):

      LSR為只讀寄存器,當(dāng)發(fā)生錯誤時Bit7為1,Bit6為1時標(biāo)示發(fā)送保持及發(fā)送移位寄存器均空,Bit5為1時標(biāo)示僅發(fā)送保持寄存器空,此時,可以由軟件發(fā)送下一數(shù)據(jù)。當(dāng)線路狀態(tài)為0時Bit4置位為1,幀格式錯時Bit3置位為1,奇偶錯和超越錯分別將Bit2及Bit1置位為1。Bit0置位為1表示接收數(shù)據(jù)就緒。

  MODEM狀態(tài)寄存器(MSR):

      MSR寄存器的高4位分別對應(yīng)MODEM的狀態(tài)線,低4位表示MODEM的狀態(tài)線是否發(fā)生了變化。

    以上我們詳細(xì)介紹了PC機的串行通訊硬件環(huán)境,以下將分別給出使用查詢及中斷驅(qū)動的方法編寫的串行口驅(qū)動程序。這些程序僅使用RXD/TXD,無需硬件握手信號。

(2)使用查詢方法的串行通訊程序設(shè)計:   

polling.c       

#include <dos.h>
#include <stdio.h>
#include <conio.h>
#define PortBase 0x2F8

void com_putch(unsigned char);
int com_chkch(void);

main()
{
 int c;
 unsigned char ch;

 outportb(PortBase + 1 , 0); /* Turn off interrupts - Port1 */

 /* Set COM1: 9600,8,N,1*/
 outportb(PortBase + 3 , 0x80);
 outportb(PortBase + 0 , 0x0C);
 outportb(PortBase + 1 , 0x00);
 outportb(PortBase + 3 , 0x03);

 clrscr();

 while(1) {

  c = com_chkch();
   if(c!=-1) {
   c &= 0xff; putch(c);
   if(c=='\n') putch('\r');
  }
 

  if(kbhit()) {
   ch = getch(); com_putch(ch);
  }
 }

}


void com_putch(unsigned char ch) {
 unsigned char status;

 while(1) {
  status = inportb(PortBase+5);
  if(status&0x01) inportb(PortBase+0); else break;
 }

 outportb(PortBase,ch);
}

int com_chkch(void) {
 unsigned char status;

 status = inportb(PortBase+5);
 status &= 0x01;
 if(status) return((int)inportb(PortBase+0)); else return(-1);

}

    使用查詢方式的通訊程序適合9600bps以下的應(yīng)用。

(3)使用中斷的串行通訊程序設(shè)計:   

    該程序由兩部分組成,serial.c及sercom.c,sercom.c為通訊的底層驅(qū)動,使用中斷的串行通訊程序可以工作到115.2Kbps.

serial.c   

#include <dos.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <bios.h>
#include "sercom.c"

COM *c;

main()
{
 unsigned char ch;

 c = ser_init( PORT_B,BAUD_9600,_COM_CHR8,_COM_NOPARITY,4096,4096 );

 while(1) {

  if( serhit(c)) {
   ch = getser(c);
   putchar(ch);
  }

  if(kbhit()) {
   ch = getch();
   putser(ch,c);
  }

 }
}

llio.c       

#include <stdio.h>
#include <dos.h>
#include <bios.h>
#include <malloc.h>

#define     CR 0x0d
#define     TRUE 0xff
#define     FALSE 0

#define     PORT_A     0 /* COM1 */
#define     PORT_B     1 /* COM2 */
#define     BAUD_9600  _COM_9600
#define     BAUD_4800  _COM_4800
#define     BAUD_2400  _COM_2400
#define     BAUD_1200  _COM_1200
#define     BAUD_600   _COM_600
#define     BAUD_300   _COM_300
#define     BAUD_110   _COM_110


typedef struct {
 char ready;             /* TRUE when ready */
 unsigned com_base;      /* 8250 Base Address */
 char irq_mask;          /* IRQ Enable Mask */
 char irq_eoi;           /* EOI reply for this port */
 char int_number;        /* Interrupt # used */
 void (_interrupt _far *old)( void );     /* Old Interrupt */

 /* Buffers for I/O */

 char *in_buf;             /* Input buffer */
 int in_tail;              /* Input buffer TAIL ptr */
 int in_head;              /* Input buffer HEAD ptr */
 int in_size;              /* Input buffer size */
 int in_crcnt;             /* Input <CR> count */
 char in_mt;               /* Input buffer FLAG */

 char *out_buf;            /* Output buffer */
 int out_tail;             /* Output buffer TAIL ptr */
 int out_head;             /* Output buffer HEAD ptr */
 int out_size;             /* Output buffer size */
 char out_full;            /* Output buffer FLAG */
 char out_mt;              /* Output buffer MT */
} COM;


COM     *ser_init( int port,int baud,int bit,int parity,int isize,int osize );
void     ser_close( COM *c );


int getsers( COM *c,int len,char *str );
int putsers( char *str, COM *c );
char serline( COM *c );
int getser( COM *c );
char serhit(COM *c);
char putser(char outch,COM *c);
void cntl_rts(int flag,COM *c);
void cntl_dtr(int flag,COM *c);
void clean_ser( COM *c );


#define     COM1_BASE         0x03F8
#define     COM1_IRQ_MASK     0xEF     /*11101111B IRQ 4 For COM1 */
#define     COM1_IRQ_EOI      0x64     /* IRQ 4 Spec EOI */
#define     COM1_INT_NUM      0x0C     /* Int # for IRQ4 */

#define     COM2_BASE         0x02F8
#define     COM2_IRQ_MASK     0xF7     /*11110111B IRQ 3 For COM2 */
#define     COM2_IRQ_EOI      0x63     /* IRQ 3 Spec EOI */
#define     COM2_INT_NUM      0x0B     /* Int # for IRQ3 */

/* 8250 ACE register defs */

#define     THR     0     /* Offset to Xmit hld reg (write) */
#define     RBR     0     /* Receiver holding buffer (read) */
#define     IER     1     /* Interrupt enable register */
#define     IIR     2     /* Interrupt identification reg */
#define     LCR     3     /* Line control register */
#define     MCR     4     /* Modem control register */
#define     LSR     5     /* Line status register */
#define     MSR     6     /* Modem status register */

#define     SREG(x)     ((unsigned)((unsigned)x + c->com_base))

/* 8259 Int controller registers */

#define     INTC_MASK     0x21     /* Interrupt controller MASK reg */
#define     INTC_EOI      0x20     /* Interrupt controller EOI reg */


#define     MAX_PORTS     2        /* # I/O ports (DOS limit) */
static int  count = 0;
static COM  com_list[MAX_PORTS];   /* I/O data structure */

static COM  *com1;                 /* Pointers for interrupt actions */
static COM  *com2;
static COM  *com_xfer;             /* Transfer interrupt data structure */

COM     *ser_init0(int port,char *ibuf,int isize, char *obuf,int osize);
void    ser_close0( COM *c );


void (_interrupt _far int_ser1)( void );    /* Int rtn for serial I/O COM 1 */
void (_interrupt _far int_ser2)( void );    /* Int rtn for serial I/O COM 2 */
void (_interrupt _far int_ser_sup)( void ); /* Support int actions */

COM     *ser_init( int port,int baud,int bit,int parity,int isize,int osize )
{
 unsigned status;
 char ch;
 COM *c;
 char *in_buf,*out_buf;

 status = _bios_serialcom(_COM_INIT,port,(bit | parity | _COM_STOP2| baud ));


 in_buf = malloc( isize );
 if( in_buf == NULL ) return( NULL );

 out_buf = malloc( osize );
 if( out_buf == NULL ) return( NULL );

 c = ser_init0(port,in_buf,isize,out_buf,osize );

 clean_ser(c);

 return( c );
}


void     ser_close(COM *c)
{
 int i;


 if( !c->ready ) return;

 ser_close0(c);

 free( c->in_buf );
 free( c->out_buf );

}


char     serline( COM *c )
{

 if( !c->ready ) return(FALSE);

 if( c->in_crcnt > 0 ) return( TRUE );
  else return( FALSE );
}

int     getsers( COM *c,int len,char *str )
{
 char ch;
 int i;

 i = 0;
 while( i<len ) {
  while( !serhit(c) ) {
   if(kbhit()) return( -1 );
  }

  ch = 0x7f & getser(c);
  switch( ch ) {

   case 0x0d: str[i++] = '%content%';
   return( i );

   case 0x00:
   case 0x0a: break;

   default: str[i++] = ch;
   break;
  }
 }


 str = '%content%';
 return( len );
}


int     putsers( char *str, COM *c )
{
 int n,i,j;

 n = strlen( str );

 for( i=0; i<n; i++ ) {
  while( !putser( str,c ) );
 }

 return( n );
}

char     putser( char outch, COM *c )
{
 char val;

 if( !c->ready ) return(FALSE);

 while( !c->out_mt && (c->out_head == c->out_tail) );

 if( !c->out_full ) {
  c->out_buf[c->out_head++] = outch;
  if( c->out_head == c->out_size )
   c->out_head = 0;         /* Reset buffer circularly */
 }

 if( c->out_head == c->out_tail ) {
  c->out_full = TRUE;
  return( FALSE );
 } else c->out_full = FALSE;

 val = inp( SREG(LCR) );     /* Reset DLAB for IER access */
 val &= 0x7F;                /* Clear IER access bit */
 outp(SREG(LCR),val);

 val = inp( SREG(IER) );
 if( !(val & 0x02) )         /* Interrupt ON ? */
 {

  c->out_mt = FALSE;         /* Not MT now */
  _disable();                /* Interrupts OFF NOW */
  outp(SREG(IER),0x03);      /* RX & TX interrupts ON */
  _enable();                 /* Interrupts ON again */
 }

 return( TRUE );
}


char     serhit( COM *c )
{
 if( !c->ready ) return(FALSE);

 if( !c->in_mt ) return( TRUE );
  else return( FALSE );
}

int     getser( COM *c )
{
 int ch;

 if( !c->ready ) return(FALSE);

 if( !serhit(c) ) return( 0 );

 _disable();

 ch = 0xff & c->in_buf[c->in_tail++];
 if( c->in_tail == c->in_size ) c->in_tail = 0;

 if( c->in_tail == c->in_head ) c->in_mt = TRUE;

 if( ch == CR )             /* Keep track of CR's */
  c->in_crcnt--;

 _enable();


 return( ch );
}

void     clean_ser( COM *c )
{
 _disable();

 c->in_head = 0;
 c->in_tail = 0;
 c->in_mt = TRUE;
 c->in_crcnt = 0;

 _enable();
}


void     cntl_dtr( int flag,COM *c )
{
 char val;


 if( !c->ready ) return;

 val = inp(SREG(MCR));

 if( flag ) val |= 1;
  else val &= ~1;

 outp(SREG(MCR),val);
}


void     cntl_rts( int flag, COM *c )
{
 char val;

 if( !c->ready ) return;

 val = inp(SREG(MCR));

 if( flag ) val |= 2;
  else val &= ~2;

 outp(SREG(MCR),val);
}

COM     *ser_init0(int port,char *ibuf,int isize, char *obuf,int osize)
{
 int i;
 char val;
 COM *c;

 while( port >= MAX_PORTS )   /* Get port # in range */
 port--;
 for( i=0; i<MAX_PORTS; i++ ) /* Select data structure */
 {
  if( !com_list.ready ) {
   c = &(com_list);
   break;
  }
 }
 

if( i == MAX_PORTS ) /* Not found */
 return( NULL );


 c->in_buf = ibuf;
 c->in_size = isize;
 c->in_mt = TRUE;
 c->in_head = 0;
 c->in_tail = 0;
 c->in_crcnt = 0;

 c->out_buf = obuf;
 c->out_size = osize;
 c->out_full = FALSE;
 c->out_mt = TRUE;
 c->out_head = 0;
 c->out_tail = 0;


 switch( port ) {

  case 0:         /* Here set up for COM1 */
   c->ready = TRUE;
   c->com_base = COM1_BASE;
   c->irq_mask = COM1_IRQ_MASK;
   c->irq_eoi = COM1_IRQ_EOI;
   c->int_number = COM1_INT_NUM;

   _disable();

   com1 = c;
   c->old = _dos_getvect( c->int_number );
   _dos_setvect(c->int_number,int_ser1);
  break;

 case 1:         /* Here set up for COM1 */
  c->ready = TRUE;
  c->com_base = COM2_BASE;
  c->irq_mask = COM2_IRQ_MASK;
  c->irq_eoi = COM2_IRQ_EOI;
  c->int_number = COM2_INT_NUM;

  _disable();

  com2 = c;
  c->old = _dos_getvect( c->int_number );
  _dos_setvect(c->int_number,int_ser2);
 break;

  default: return(NULL);     /* Bad port SKIP */
 }

 val = inp( INTC_MASK );
 val &= c->irq_mask;
 outp( INTC_MASK, val );

 val = inp( SREG(LSR) );     /* Read and discard STATUS */
 val = inp( SREG(RBR) );     /* Read and discard DATA */

 val = inp( SREG(LCR) );     /* Rst DLAB for IER access */
 val &= 0x7F;                /* 01111111B */
 outp( SREG(LCR),val );

 outp( SREG(IER),1);         /* Enable Data READY INT */

 outp( SREG(MCR),0xB );      /* Enable OUT2,RTS & DTR */

 _enable();

 return( c );

}

void     ser_close0( COM *c )
{
 char val;

 if( !c->ready ) return;

 _disable();

 val = inp(INTC_MASK);
 val |= ~c->irq_mask;
 outp(INTC_MASK,val);

 val = inp( SREG(LCR) );     /* Reset DLAB for IER access */
 val &= 0x7F;                /* Clear IER access bit */
 outp(SREG(LCR),val);

 val = inp( SREG(RBR) );
 val = inp( SREG(LSR));
 val = inp(SREG(IIR) );
 val = inp(SREG(IER) );
 outp(SREG(IER),0);         /* Disable 8250 Interrupts */

 outp(SREG(MCR),0);         /* Disable RTS,DTR and OUT2 */

 outp(SREG(MCR),0);         /* Disable OUT2 */

 _dos_setvect(c->int_number, c->old );

 _enable();

 c->ready = FALSE;

}

void     _interrupt _far int_ser1( void )
{

 com_xfer = com1;
 _chain_intr( int_ser_sup );
}


void     _interrupt _far int_ser2( void )
{

 com_xfer = com2;
 _chain_intr( int_ser_sup );
}


void     _interrupt _far int_ser_sup( void )
{
 char val;
 char ch;
 int ptr;
 COM *c;

 c = com_xfer;

 while( TRUE ) {
  val = inp( SREG(LSR) ); /* Read and discard STATUS */
  val = inp( SREG(IIR) ); /* Get interrupt status register */

  if( val & 0x04 ) /* Receive Interrupt */
  {

   ptr = c->in_head;
   ch = inp( SREG(RBR) );

   if( c->in_mt || ptr != c->in_tail ) {
    c->in_buf[ptr++] = ch;
    if( ptr == c->in_size ) ptr = 0;
    c->in_head = ptr;
    c->in_mt = FALSE;

    if( ch == CR )         /* Count lines */
    c->in_crcnt++;
   }
  } else {
   if( val & 0x02 ) /* Transmit Interrupt */
   {
    if( (!c->out_full) && (c->out_head == c->out_tail) ) {

     c->out_mt = TRUE;
     val = inp( SREG(LCR) );
     val &= 0x7F;
     outp(SREG(LCR),val);

     outp(SREG(IER),0x01);
/* RX interrupts ON */
    } else {

     outp(SREG(THR),
     c->out_buf[c->out_tail++]);
     if( c->out_tail == c->out_size ) c->out_tail = 0;
    }
   } else return;         /* No Interrupt */
  }

  outp(INTC_EOI,c->irq_eoi);
 }
}

(4)MCS-51串行通訊:           

    MCS-51的串行口使用起來非常簡單,因為MCS-51單片機的串行口沒有與MODEM控制相關(guān)的信號。這使得51的通訊口非常易于使用。使用查詢方式時,僅需初始化有關(guān)的寄存器即可。演示程序如下:

#include <stdio.h>
#include <reg51.h>

void putch(unsigned char);
unsigned char getch(void);

main()
{
 unsigned char ch;

 SCON = 0x50; 
 TMOD |= 0x20; 
 TH1 = 0xfd; 
 TL1 = 0xfd;
 TR1 = 1; 
 TI = 1; 
 RI = 0; 
 
 while(1) {
  ch = getch(); putch(ch);

 }
}

void putch(unsigned char ch) {

 SBUF = ch;
 TI = 0;
 while(!TI);
}

unsigned char getch(void) {

 while(!RI);
 RI = 0;
 return(SBUF);

}

    使用中斷驅(qū)動的程序比較復(fù)雜,下面為完整的MCS-51串行通訊底層驅(qū)動程序,由頭文件serint.hJ及serint.c組成!  

serint.h       

unsigned char RR_iHead;     /* receiver head index */
unsigned char RR_iTail;     /* receiver tail index */
unsigned char RR_cLev;      /* receiver buffer count */
unsigned char RR_cMax;      /* receiver buffer count */

unsigned char TR_iHead;     /* transmitter head index */
unsigned char TR_iTail;     /* transmitter tail index */
unsigned char TR_cLev;      /* transmitter buffer count */
unsigned char TR_cMax;      /* transmitter buffer count */

unsigned char UnGotCh;      /* saved char for ungetch() */

unsigned char SerFlags;     /* serial flag */

bit FlagTransIdle;          /* set when transmitter is finished */
bit FlagStripOutLF;         /* don't send linefeeds */
bit FlagCvtInCR;            /* convert incoming CR to LF */

unsigned char TestBits;

#define INRINGSIZE 128      /* must be <= 254 to avoid wraps */
#define OUTRINGSIZE 250     /* ditto */

#define T1RELOAD 253

#define CR 13
#define LF 10
#define ESC 27

#define EOF -1

unsigned char xdata RRing[INRINGSIZE];     /* receiver ring buffer */
unsigned char xdata TRing[OUTRINGSIZE];    /* receiver ring buffer */

int     putstr (const char *);
int     putch(int);
int     chkch();
int     getch();
void    SerWaitOutDone();
int     SerFlushIn();
int     putc(int TransChar);

 

serint.c       

/* CONSOLE.C -- serial I/O code */

/*---------------------------------------------------------------------------*/   
/* Initialize serial port hardware and variables */

#include <reg51.h>
#include "serint.h"

void     SerInitialize() {

 SerFlags = 0; 

 FlagTransIdle = 1;
 FlagCvtInCR = 1;         /* want to turn CRs into LFs */
 RR_iHead = RR_iTail = RR_cLev = RR_cMax = 0;
 TR_iHead = TR_iTail = TR_cLev = TR_cMax = 0;
 UnGotCh = -1;
 

/*--- set up Timer 1 to produce serial rate */

 TCON &= 0x3F;          /* clear run & interrupt flags */
 TMOD &= 0x0F;          /* flush existing Timer 1 setup */
 TMOD |= 0x20;          /* flush existing Timer 1 setup */

 SCON = 0x50;           /* flush existing Timer 1 setup */
 PCON |= 0x00; 
 TH1 = TL1 = T1RELOAD & 0x00FF;     /* flush existing Timer 1 setup */
 TR1 = 1;               /* start the timer */
 ES = 1;                /* enable serial interrupts */
}

/*---------------------------------------------------------------------------*/   
/* Serial console interrupt handler */
/* If transmitter output is disabled, we fake trans interrupts until empty */

void     SerInt() interrupt 4
{

 if(RI) {                 /* receiver interrupt active? */
  if(RR_cLev<INRINGSIZE) { /* room for newest char? */
   RRing[RR_iHead] = SBUF; /* pick up the character and stick in ring */
   RR_iHead++;             /* tick the index */
   RR_cLev++;              /* tick size counter */
   if(RR_iHead==INRINGSIZE) RR_iHead = 0;     /* hit end of array yet? */
  }
  RI = 0;                  /* indicate we have it */
 }

 if(TI) {                  /* transmitter interrupt active? */
  if(TR_cLev) {            /* anything to send? */
   SBUF = TRing[TR_iTail]; /* fetch next char and send it */
   TR_cLev--;              /* tick size counter */
   TR_iTail++;             /* tick the index */
   if(TR_iTail==OUTRINGSIZE) TR_iTail = 0;     /* hit end of array yet? */
  } else FlagTransIdle = 1;/* no, flag inactive */

  TI = 0;                  /* indicate done with it */
 }

}

/*---------------------------------------------------------------------------*/   
/* Send character to console */
/* Can strip LFs, in which case you get CR instead of LF/CR */


int     putch(int TransChar)
{
 putc(TransChar);                 /* if not LF, handle normally */
 if(TransChar=='\n') putc('\r');  /* if LF, send a CR */
}

int     putc(int TransChar)
{

 while(TR_cLev>=OUTRINGSIZE);     /* wait for space in ring */
 ES = 0;
 TRing[TR_iHead] = TransChar;     /* point to char slot */
 TR_iHead++;                      /* tick counter & index */
 TR_cLev++;
 if(TR_iHead==OUTRINGSIZE) TR_iHead = 0;
 if(FlagTransIdle) {
  FlagTransIdle = 0;              /* kickstart transmitter if idle */
  TI = 1;
 }

 ES = 1;
 return(TransChar);
}

/*---------------------------------------------------------------------------*/
/* Decide if there are any pending chars */
/* Returns nonzero if there's a char */

int     chkch() {

 return(RR_cLev);                 /* tack on current level */
}

/*---------------------------------------------------------------------------*/   
/* Wait for the serial transmitter to go idle */
/* If the transmitter is disabled, that's considered to be the same thing */

void     SerWaitOutDone() {

 while (TR_cLev);                 /* wait for ring empty */
 while(!FlagTransIdle);           /* wait for last char */


/*---------------------------------------------------------------------------*/   
/* Flush the input buffer */
/* Returns number of chars flushed */


int     SerFlushIn() {

 ES = 0;                         /* turn off serial interrupts */
 RR_iTail = 0;                   /* reset ring variables */
 RR_iHead = 0;
 RR_cLev = 0;
 ES = 1;                         /* turn on serial interrupts */

}

/*---------------------------------------------------------------------------*/   
/* Get character from console */
/* CRs turn into LFs unless we're not doing that... */


int     getch() {
 int RetVal;

 ES = 0;             /* avoid interruptions */

 if(RR_cLev) {       /* anything pending? */
  RetVal = RRing[RR_iTail];
  if(RetVal=='\r') RetVal = '\n';        /* use LF instead of CR */
  RR_iTail++;        /* tick size index & counter */
  RR_cLev--;
  if(RR_iTail==INRINGSIZE) RR_iTail = 0; /* hit end of array yet? */
 } else RetVal = -1;

 ES = 1;
 return(RetVal);
}

/*---------------------------------------------------------------------------*/   
/* Send string to console */
/* putstr(char *pString); */
/* The ?putstr entry point has *pString in DPTR */

int     putstr (char *pstring)
{
 while(*pstring) {         /* fetch character if zero done */
  putch(*pstring);
  pstring++;               /* continue... */
 }
}

      使用查詢的程序可以做到多高的波特率取決于主程序的工作量,使用中斷方式的通訊驅(qū)動程序在使用11.0592MHz晶振時可以達(dá)到57.6Kbps的速率。

(5)關(guān)于RS485   

      以上幾個方面詳細(xì)介紹了PC及MCS-51的RS-232C的串行通訊程序的設(shè)計方法,RS-485與RS-232C相類似,其區(qū)別在于使用雙端平衡驅(qū)動及半雙工模式,這些措施使RS-485傳輸距離更遠(yuǎn),同時,RS-485還可以組網(wǎng)。在同一個RS-485網(wǎng)絡(luò)中,可以多達(dá)32個模塊,某些器件可以多達(dá)256個甚至更多。相應(yīng)的,RS-485具有接收/發(fā)送控制端,RS-485的接收控制端可以在需要接收的時候打開或者一直打開以便無條件的接收線路上的數(shù)據(jù)。RS-485的發(fā)送控制端僅在需要發(fā)送時打開,平時應(yīng)關(guān)端發(fā)送器,因為在同一RS-485網(wǎng)絡(luò)中在同一時刻僅允許一個發(fā)送器工作。在數(shù)據(jù)發(fā)送完成后關(guān)閉發(fā)送器。這可以通過以下兩種方法實現(xiàn)。

      一、在數(shù)據(jù)完全移出后,對于PC機為發(fā)送移位寄存器空,對于MCS-51為TI置位。這些調(diào)件既可使用查詢的方法得到,也可以在中斷程序中實現(xiàn)。

      二、將RS-485的接收器始終打開,這樣一來,所有在RS-485上的數(shù)據(jù)均被接收回來,包括自己發(fā)送出去的數(shù)據(jù)。因此,當(dāng)自己發(fā)送的數(shù)據(jù)完全被自己接收回來時即可關(guān)閉發(fā)送器。原則上說,這一方法無論是查詢或中斷方式都適用,但實際上,由于RS-485的數(shù)據(jù)通常打包后發(fā)送,因此,使用查詢的方法并不理想。這一方法非常適合中斷方式,尤其是以數(shù)據(jù)包傳送的RS-485通訊。

 大多數(shù)的電腦設(shè)備都具有RS-232C接口,盡管它的性能指標(biāo)并非很好。在廣泛的市場支持下依然常勝不衰。就使用而言,RS-232也確實有其優(yōu)勢:僅需3根線便可在兩個數(shù)字設(shè)備之間全雙工的傳送數(shù)據(jù)。不過,RS-232C的控制要比使用并行通訊的打印機接口更難于控制。RS-232C使用了遠(yuǎn)較并行口更多的寄存器。這些寄存器用來實現(xiàn)串行數(shù)據(jù)的傳送及RS-232C設(shè)備之間的握手與流量控制。本文將分別描述PC機及單片機MCS-51的串行通訊的原理及具體的軟件設(shè)計。

(1)RS-232C介紹與PC硬件:

      RS-232C使用-3到-25V表示數(shù)字“1”,使用3V到25V表示數(shù)字“0”,RS-232C在空閑時處于邏輯“1”狀態(tài),在開始傳送時,首先產(chǎn)生一起始位,起始位為一個寬度的邏輯“0”,緊隨其后為所要傳送的數(shù)據(jù),所要傳送的數(shù)據(jù)有最低位開始依此送出,并以一個結(jié)束位標(biāo)志該字節(jié)傳送結(jié)束,結(jié)束位為一個寬度的邏輯“1”狀態(tài)。

      PC機一般使用8250或16550作為串行通訊的控制器,使用9針或25針的接插件將串行口的信號送出。該插座的信號定義如下:

DB-25DB-9信號名稱方向含    義23TXD輸出數(shù)據(jù)發(fā)送端32RXD輸入數(shù)據(jù)接收端47RTS輸出請求發(fā)送(計算機要求發(fā)送數(shù)據(jù))58CTS輸入清除發(fā)送(MODEM準(zhǔn)備接收數(shù)據(jù))66DSR輸入數(shù)據(jù)設(shè)備準(zhǔn)備就緒75SG-信號地81DCD輸入數(shù)據(jù)載波檢測204DTR輸出數(shù)據(jù)終端準(zhǔn)備就緒(計算機)229RI輸入響鈴指示
基地址讀/寫寄存器縮寫注    釋0Write-發(fā)送保持寄存器(DLAB=0)0Read-接收數(shù)據(jù)寄存器(DLAB=0)0Read/Write-波特率低八位(DLAB=1)1Read/WriteIER中斷允許寄存器1Read/Write-波特率高八位(DLAB=1)2ReadIIR中斷標(biāo)識寄存器2WriteFCRFIFO控制寄存器3Read/WriteLCR線路控制寄存器4Read/WriteMCRMODEM控制寄存器5ReadLSR線路狀態(tài)寄存器6ReadMSRMODEM狀態(tài)寄存器7Read/Write-Scratch Register
速率(BPS)波特率高八位波特率低八位5009h00h30001h80h60000hC0h240000h30h480000h18h960000h0Ch1920000h06h3840000h03h5760000h02h11520000h01h
注    釋7未使用6未使用5進入低功耗模式(16750)4進入睡眠模式(16750)3允許MODEM狀態(tài)中斷2允許接收線路狀態(tài)中斷1允許發(fā)送保持器空中斷0允許接收數(shù)據(jù)就緒中斷
注    釋Bit6:7=00無FIFOBit6:7=01允許FIFO,但不可用Bit6:7=11允許FIFOBit5允許64字節(jié)FIFO(16750)Bit4未使用Bit316550超時中斷Bit2:1=00MODEM狀態(tài)中斷(CTS/RI/DTR/DCD)Bit2:1=01發(fā)送保持寄存器空中斷Bit2:1=10接收數(shù)據(jù)就緒中斷Bit2:1=11接收線路狀態(tài)中斷Bit0=0有中斷產(chǎn)生Bit0=1無中斷產(chǎn)生
注    釋Bit7:6=001Byte產(chǎn)生中斷Bit7:6=014Byte產(chǎn)生中斷Bit7:6=108Byte產(chǎn)生中斷Bit7:6=1114Byte產(chǎn)生中斷Bit5允許64字節(jié)FIFOBit4未使用Bit3DMA模式選擇Bit2清除發(fā)送FIFOBit1清除接收FIFOBit0允許FIFO
注    釋Bit7=1允許訪問波特率因子寄存器Bit7=0允許訪問接收/發(fā)送及中斷允許寄存器Bit6設(shè)置間斷,0-禁止,1-設(shè)置Bit5:3=XX0無校驗Bit5:3=001奇校驗Bit5:3=011偶校驗Bit5:3=101奇偶保持為1Bit5:3=111奇偶保持為0Bit2=01位停止位Bit2=12位停止位(數(shù)據(jù)位6-8位),1.5位停止位(5位數(shù)據(jù)位)Bit1:0=005位數(shù)據(jù)位Bit1:0=016位數(shù)據(jù)位Bit1:0=107位數(shù)據(jù)位Bit1:0=118位數(shù)據(jù)位
注    釋Bit7未使用Bit6未使用Bit5自動流量控制(僅16750)Bit4環(huán)路測試Bit3輔助輸出2Bit2輔助輸出1Bit1設(shè)置RTSBit0設(shè)置DSR
注    釋Bit7FIFO中接收數(shù)據(jù)錯誤Bit6發(fā)送移位寄存器空Bit5發(fā)送保持寄存器空Bit4間斷Bit3幀格式錯Bit2奇偶錯Bit1超越錯Bit0接收數(shù)據(jù)就緒
注    釋Bit7載波檢測Bit6響鈴指示Bit5DSR準(zhǔn)備就緒Bit4CTS有效Bit3DCD已改變Bit2RI已改變Bit1DSR已改變Bit0CTS已改變
  • 上一篇: 12864液晶屏源程序(已經(jīng)調(diào)試通過)
  • 下一篇: “祝你平安”源程序
  • 發(fā)表評論   告訴好友   打印此文  收藏此頁  關(guān)閉窗口  返回頂部
    熱點文章
     
    推薦文章
     
    相關(guān)文章
    網(wǎng)友評論:(只顯示最新5條。)
    關(guān)于我們 | 聯(lián)系我們 | 廣告合作 | 付款方式 | 使用幫助 | 機電之家 | 會員助手 | 免費鏈接

    點擊這里給我發(fā)消息66821730(技術(shù)支持)點擊這里給我發(fā)消息66821730(廣告投放) 點擊這里給我發(fā)消息41031197(編輯) 點擊這里給我發(fā)消息58733127(審核)
    本站提供的機電設(shè)備,機電供求等信息由機電企業(yè)自行提供,該企業(yè)負(fù)責(zé)信息內(nèi)容的真實性、準(zhǔn)確性和合法性。
    機電之家對此不承擔(dān)任何保證責(zé)任,有侵犯您利益的地方請聯(lián)系機電之家,機電之家將及時作出處理。
    Copyright 2007 機電之家 Inc All Rights Reserved.機電之家-由機電一體化網(wǎng)更名-聲明
    電話:0571-87774297 傳真:0571-87774298
    杭州濱興科技有限公司提供技術(shù)支持

    主辦:杭州市高新區(qū)(濱江)機電一體化學(xué)會
    中國行業(yè)電子商務(wù)100強網(wǎng)站

    網(wǎng)站經(jīng)營許可證:浙B2-20080178-1