俩个PC机通过串行口互联,实现件的无差错传输。程序必须用中断方式来完成任务

来源:互联网 发布:装修后房子网络不通 编辑:程序博客网 时间:2024/06/14 15:30

 

课程设计(论文)任务书

一、设计题目:1、题目名称      PC机通过串行口互联     

2、题目来源                                  

二、目的和意义

俩个PC机通过串行口互联,实现件的无差错传输。程序必须用中断方式来完成任务。

三、原始资料

相关技术资料和程序原代码

四、设计说明书应包括的内容

程序代码、8250串口芯片和中断管理芯片8259的初始化依据。

五、设计应完成的图纸

软件源代码和设计报告。软件代码可以是 C语言或汇编语言,包括流程图。

六、主要参考资料

《微机原理与接口技术》周荷琴等编

七、进度要求

周一查资料;周二和周三编制程序;周四上机实验;周五15点答辩。

八、其它要求

1            PC机使用8250串口芯片。中断管理芯片还是8259。学生需要了解每一个芯片在PC机中的地址。同时了解8250串口芯片的使用方法。

2            不准带电拔插串行口插头。

3            U盘上自备TURBO  C 2.0编译环境。因为机房的计算机(CD盘要还原)安装有还原卡。

4            此任务书每人打印一份,然后认真阅读。

 5         自购DB9P 公插头二个,23脚交叉连线,5脚直接连接,焊接。电缆长度一米。

 

一、设计题目

           两台PC机之间进行串口通信。串口通信(Serial Communication) 是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式。这种通信方式使用的数据线少,在远距离通信中可以节约通信成本,但其传输速度比并行传输低。

二、设计目的与要求

 1. 两个PC机通过串行口互联,实现文件的无差错传输。程序采用中断方式来完成任务。

2. PC机使用8250串口芯片。中断管理芯片使用8259。了解每一个芯片在PC机中的地址。了解8250串口芯片的使用方法。

 三、主要原理及实现方法

1 程序流程图

程序开始

主界面

选择波特率

退出

选择端口号

发送字符

接受字符

发送完毕

接受完毕

退出

 

 

 

 

 

  

 


        

2RS-232C介绍与PC硬件:

RS-232C使用-3-25V表示数字“1”,使用3V25V表示数字“0”RS-232C在空闲时处于逻辑“1”状态,在开始传送时,首先产生一起始位,起始位为一个宽度的逻辑“0”,紧随其后为所要传送的数据,所要传送的数据有最低位开始依此送出,并以一个结束位标志该字节传送结束,结束位为一个宽度的逻辑“1”状态。

     PC机一般使用825016550作为串行通讯的控制器,使用9针或25针的接插件将串行口的信号送出。

3. 8250的初始化依据

          825016550)的寄存器如下表所示

基地址

/

寄存器缩写

  

0

Write

-

发送保持寄存器(DLAB=0

0

Read

-

接收数据寄存器(DLAB=0

0

Read/Write

-

波特率低八位(DLAB=1

1

Read/Write

IER

中断允许寄存器

1

Read/Write

-

波特率高八位(DLAB=1

2

Read

IIR

中断标识寄存器

2

Write

FCR

FIFO控制寄存器

3

Read/Write

LCR

线路控制寄存器

4

Read/Write

MCR

MODEM控制寄存器

5

Read

LSR

线路状态寄存器

6

Read

MSR

MODEM状态寄存器

7

Read/Write

-

Scratch Register

       PC机支持1-4个串行口,即COM1-COM4,其基地址在BIOS数据区00000400-00000406中描述,对应地址分别为3F8/2F8/3E8/2E8COM1COM3使用PC机中断4COM2COM4使用中断3

在上表中,8250共有12个寄存器,使用了8个地址,其中部分寄存器共用一个地址,由DLAB=0/1来区分,在DLAB=1用于设定通讯所需的波特率。        

8250的初始化步骤:

写除数寄存器高8

设置数据格式(通信控制字)

设置modern控制字

设置中断允许字

使用通信控制寄存器D7=1

 

 

 

 

 


8250的初始化流程图

4. 程序源代码的主要部分:

#include  <dos.h>

#include  <bios.h>

#include  <stdio.h>

#include  <math.h>

#include  <conio.h>

 

/*8250内部寄存器宏定义,值为对基地址的偏移量*/

#define  SER_RBR  0    /*接收缓冲寄存器RBR(读)    DLAB=0*/

#define  SER_THR  0    /*发送保持寄存器THR(写)    DLAB=0*/

#define  SER_IER  1    /*中断允许寄存器IER(读/写)    DLAB=0*/

#define  SER_IIR  2    /*中断识别寄存器IIR  (读)*/

#define  SER_LCR  3    /*通信线路控制寄存器LCR    (读/写)*/

#define  SER_MCR  4    /*Model控制寄存器MCR    (/写)*/

#define  SER_LSR  5    /*通信线路状态寄存器LSR    (读)*/

#define  SER_MSR  6    /*Modem状态寄存器MSR      (读)*/

#define  SER_DLL  0    /*除数锁存器(波特率低8位)DLL(读/写)  DLAB=1*/

#define  SER_DLH 1   /*除数锁存器(波特率高8位)DLH(读/写)  DLAB=1*/

 

/*8250使用1.8432MHz的基准时钟输入,所以除数=1843200/(B*16)*/

#define  SER_BAUD_1200    96      /*波特率为1200时,波特率因子(除数)为96*/

#define  SER_BAUD_2400    48      /*波特率为2400时,波特率因子(除数)为48*/

#define  SER_BAUD_9600    12      /*波特率为9600时,波特率因子(除数)为12*/

#define  SER_BAUD_19200    6      /*波特率为19200时,波特率因子(除数)为6*/

#define  COM_1   0x3F8  /*COM1  8250内部寄存器基地址*/

#define  COM_2   0x2F8  /*COM2  8250内部寄存器基地址*/

#define  COM_3   0x3E8  /*COM3  8250内部寄存器8250基地址*/

#define  COM_4   0x2E8  /*COM4  8250内部寄存器8250基地址*/

#define  SER_STOP_1   0    /*  1位停止位*/

#define  SER_STOP_2   4    /*  2位停止位*/

#define  SER_BITS_5   0    /*  5位数据位*/

#define  SER_BITS_6   1    /*  6位数据位*/

#define  SER_BITS_7   2    /*  7位数据位*/

#define  SER_BITS_8   3    /*  8位数据位*/

#define  SER_PARITY_NONE  0   /*无校验*/

#define  SER_PARITY_ODD   8   /*奇校验*/

#define  SER_PARITY_EVEN  24  /*偶校验*/

#define  SER_DIV_LATCH_ON  128  /*DLAB=1*/

#define  PIC_IMR      0x21    /*中断屏蔽寄存器*/

#define  PIC_ICR      0x20    /*中断控制寄存器*/

#define  INT_SER_PORT_0    0x0C    /*COM1COM3中断向量编号*/

#define  INT_SER_PORT_1     0x0B    /*COM2COM4中断向量编号*/

 

/*函数声明*/

void interrupt far Serial_Isr();

Open_Serial(int port_base, int baud, int configuration);

Close_Serial(int port_base);

 

/*全局变量定义,可在各函数间传递参数*/

void interrupt far (*Old_Isr)(); /* Old_Isr保存原来的串口中断向量*/

int old_int_mask;             /*保存原来的中断屏蔽寄存器的值*/

int open_port;                /*当前打开的串口编号*/

main()

{ 

char  ch,press;

int  done=0;

int i;

int j;

int ba[4];

int da[5];

 

ba[0]=1200;

ba[1]=2400;

ba[2]=9600;

ba[3]=19200;

 

da[0]=1016;

da[1]=760;

da[2]=1000;

da[3]=744;

 

printf("choose to use the baud rate: 0-1200,1-2400,2-9600,3-19200/n");

scanf("%d",&i);

 

printf("choose to use the port number: 0-1,1-2,2-3,3-4/n");

scanf("%d",&j);

 Open_Serial(da[j],ba[i],SER_PARITY_EVEN|SER_BITS_8|SER_STOP_1);

 printf("com:%d;bps:%d;parity:even;bits:8;stop  bit:1",j+1,ba[i]);

 printf("press  any  key  to  begin  sending");

 while(!done)

 {  delay(30);

   if(kbhit())/*如有键按下*/

   { press=getch();/*读取按键值*/

    printf("/nSend the char %c",press);

    Serial_Write(press);

    if(press==27)/*如果按下的是ESC键(ESC键的ASCII代码为27),则退出*/

      done=1;

   }

 }

 Close_Serial(da[j]);/*关闭串口COM1*/

}

 

/*-----------初始化串口---------------*/

Open_Serial(int port_base, int baud, int configuration)

{

 open_port = port_base;

 disable();/*关闭中断*/

 outp(port_base + SER_LCR, SER_DIV_LATCH_ON);/*DLAB=1*/

 outp(port_base + SER_DLL, baud);  /*通过设置波特率因子来确定波特率*/

 outp(port_base + SER_DLH, 0);

 outp(port_base + SER_LCR, configuration); /*通信方式设定,同时DLAB=0*/

 outp(port_base + SER_IER, 1);  /*允许接收数据就绪中断,关闭其它中断*/

 if(port_base == COM_1||port_base==COM_3)

 {

   /*保存串口13原来的中断向量,以便在退出程序时恢复*/

   Old_Isr =getvect(INT_SER_PORT_0);

   /*为串口设置新的中断向量,在发生中断时就会调用执行用户所指定的中断服务程序*/

   setvect(INT_SER_PORT_0, Serial_Isr);

   printf("/nOpening Com Port #1/3.../n");

 }

 else

 {

   /*功能与上面的代码类似,只是处理的对象是串口24*/

   Old_Isr =getvect(INT_SER_PORT_1);

   setvect(INT_SER_PORT_1, Serial_Isr);

   printf("/nOpening Com Port #2/4.../n");

 }

 old_int_mask = inp(PIC_IMR);/*读入中断屏蔽寄存器的值*/

 /*对应位为0则允许该中断,允许3(串口1中断)、4(串口2中断)而不影响其它中断的屏蔽状态*/

 outp(PIC_IMR, (port_base==COM_1) ? (old_int_mask & 0xEF) : (old_int_mask & 0xF7 ));

 enable();/*允许中断*/

}

 

/*-------------关闭串口--------------*/

Close_Serial(int port_base)

{

 outp(port_base + SER_MCR, 0);

 outp(port_base + SER_IER, 0);/*禁止所有串口中断*/

 outp(PIC_IMR, old_int_mask );/*恢复原来的中断屏蔽状态*/

 if(port_base == COM_1)

 {

   setvect(INT_SER_PORT_0, Old_Isr);/*恢复原来的串口中断向量*/

   printf("/nClosing Com Port #1./n");

 }

 else

 {  setvect(INT_SER_PORT_1, Old_Isr);

   printf("/nClosing Com Port #2./n");

 }

}

 

/*--------------写串口-----------------*/

Serial_Write(char ch)

{  while(!(inp(open_port + SER_LSR) & 0x20)){}/*如串口不空闲,则循环等待*/

 disable();/*当上面条件不等,说明串口空闲,退出循环*/

 outp(open_port + SER_THR, ch); /*开始发送数据*/

 enable();/*开中断*/

}

 

/*-------------串口中断服务程序-----------------*/

void interrupt far Serial_Isr()

{  char ch;

ch = inp(open_port + SER_RBR);/*从串口读出对方传来的数据*/

if(ch==27)/*如传来的是ESC*/

   printf("/nThe Sender is quit");

else

   printf("/nReceive the data %c",ch);

outp(PIC_ICR,0x20);/*写入OCW2,向8259发普通EOI指令*/

}        

 

原创粉丝点击