微机原理课程设计报告书两台PC机之间进行串口通信Word文档下载推荐.docx
《微机原理课程设计报告书两台PC机之间进行串口通信Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《微机原理课程设计报告书两台PC机之间进行串口通信Word文档下载推荐.docx(16页珍藏版)》请在冰豆网上搜索。
5
LSR
线路状态寄存器
6
MSR
MODEM状态寄存器
7
ScratchRegister
PC机支持1-4个串行口,即COM1-COM4,其基地址在BIOS数据区0000:
0400-0000:
0406中描述,对应地址分别为3F8/2F8/3E8/2E8,COM1及COM3使用PC机中断4,COM2及COM4使用中断3。
在上表中,8250共有12个寄存器,使用了8个地址,其中部分寄存器共用一个地址,由DLAB=0/1来区分,在DLAB=1用于设定通讯所需的波特率。
常用的波特率参数见下表:
速率(BPS)
波特率高八位
波特率低八位
50
09h
00h
300
01h
80h
600
C0h
2400
30h
4800
18h
9600
0Ch
19200
06h
38400
03h
57600
02h
115200
以下几个表格为8250的寄存器的功能描述:
中断允许寄存器(IER):
位
未使用
进入低功耗模式(16750)
进入睡眠模式(16750)
允许MODEM状态中断
允许接收线路状态中断
允许发送保持器空中断
允许接收数据就绪中断
Bit0置1将允许接收到数据时产生中断,Bit1置1时允许发送保持寄存器空时产生中断,Bit2置1将在LSR变化时产生中断,相应的Bit3置位将在MSR变化时产生中断。
中断识别寄存器(IIR):
Bit6:
7=00
无FIFO
7=01
允许FIFO,但不可用
7=11
允许FIFO
Bit5
允许64字节FIFO(16750)
Bit4
Bit3
16550超时中断
Bit2:
1=00
MODEM状态中断(CTS/RI/DTR/DCD)
1=01
发送保持寄存器空中断
1=10
接收数据就绪中断
1=11
接收线路状态中断
Bit0=0
有中断产生
Bit0=1
无中断产生
IIR为只读寄存器,Bit6:
7用来指示FIFO的状态,均为0时则无FIFO,此时为8250或16450芯片,为01时有FIFO但不可以使用,为11时FIFO有效并可以正常工作。
Bit3用来指示超时中断(16550/16750)。
Bit0用来指示是否有中断发生,Bit1:
2标识具体的中断类型,这些中断具有不同的优先级别,其中LSR中断级别最高,其次是数据就绪中断,然后是发送寄存器空中断,而MSR中断级别最低。
FIFO控制寄存器(FCR):
Bit7:
6=00
1Byte产生中断
6=01
4Byte产生中断
6=10
8Byte产生中断
6=11
14Byte产生中断
允许64字节FIFO
DMA模式选择
Bit2
清除发送FIFO
Bit1
清除接收FIFO
Bit0
FCR可写但不可以读,该寄存器用来控制16550或16750的FIFO寄存器。
Bit0置1将允许发送/接收的FIFO工作,Bit1和Bit2置1分别用来清除接收及发送FIFO。
清除接收及发送FIFO并不影响移位寄存器。
Bit1:
2可自行复位,因此无需使用软件对其清零。
7用来设定产生中断的级别,发送/接收中断将在发送/接收到对应字节数时产生。
线路控制寄存器(LCR):
Bit7=1
允许访问波特率因子寄存器
Bit7=0
允许访问接收/发送及中断允许寄存器
Bit6
设置间断,0-禁止,1-设置
Bit5:
3=XX0
无校验
3=001
奇校验
3=011
偶校验
3=101
奇偶保持为1
3=111
奇偶保持为0
Bit2=0
1位停止位
Bit2=1
2位停止位(数据位6-8位),1.5位停止位(5位数据位)
0=00
5位数据位
0=01
6位数据位
0=10
7位数据位
0=11
8位数据位
LCR用来设定通讯所需的一些基本参数。
Bit7为1指定波特率因子寄存器有效,为0则指定发送/接收及IER有效。
Bit6置1会将发送端置为0,这将会使接收端产生一个“间断”。
Bit3-5用来设定是否使用奇偶校验以及奇偶校验的类型,Bit3=1时使用校验,Bit4为0则为奇校验,1为偶校验,而Bit5则强制校验为1或0,并由Bit4决定具体为0或1。
Bit2用来设定停止位的长度,0表示1位停止位,为1则根据数据长度的不同使用1.5-2位停止位。
Bit0:
1用来设定数据长度。
MODEM控制寄存器(MCR):
Bit7
自动流量控制(仅16750)
环路测试
辅助输出2
辅助输出1
设置RTS
设置DSR
MCR寄存器可读可写,Bit4=1进入环路测试模式。
Bit3-0用来控制对应的管脚。
线路状态寄存器(LSR):
FIFO中接收数据错误
发送移位寄存器空
发送保持寄存器空
间断
帧格式错
奇偶错
超越错
接收数据就绪
LSR为只读寄存器,当发生错误时Bit7为1,Bit6为1时标示发送保持及发送移位寄存器均空,Bit5为1时标示仅发送保持寄存器空,此时,可以由软件发送下一数据。
当线路状态为0时Bit4置位为1,帧格式错时Bit3置位为1,奇偶错和超越错分别将Bit2及Bit1置位为1。
Bit0置位为1表示接收数据就绪。
MODEM状态寄存器(MSR):
载波检测
响铃指示
DSR准备就绪
CTS有效
DCD已改变
RI已改变
DSR已改变
CTS已改变
MSR寄存器的高4位分别对应MODEM的状态线,低4位表示MODEM的状态线是否发生了变化。
以上我们详细介绍了PC机的串行通讯硬件环境,以下将分别给出使用查询及中断驱动的方法编写的串行口驱动程序。
这些程序仅使用RXD/TXD,无需硬件握手信号。
2.程序源代码和部分注释
#include<
dos.h>
bios.h>
stdio.h>
math.h>
conio.h>
#defineSER_RBR0/*接收缓冲寄存器RBR(读)DLAB=0*/
#defineSER_THR0/*发送保持寄存器THR(写)DLAB=0*/
#defineSER_IER1/*中断允许寄存器IER(读/写)DLAB=0*/
#defineSER_IIR2/*中断识别寄存器IIR(读)*/
#defineSER_LCR3/*通信线路控制寄存器LCR(读/写)*/
#defineSER_MCR4/*Model控制寄存器MCR(读/写)*/
#defineSER_LSR5/*通信线路状态寄存器LSR(读)*/
#defineSER_MSR6/*Modem状态寄存器MSR(读)*/
#defineSER_DLL0/*除数锁存器(波特率低8位)DLL(读/写)DLAB=1*/
#defineSER_DLH1/*除数锁存器(波特率高8位)DLH(读/写)DLAB=1*/
/*8250使用1.8432MHz的基准时钟输入,所以除数=1843200/(B*16)*/
#defineSER_BAUD_120096/*波特率为1200时,波特率因子(除数)为96*/
#defineSER_BAUD_240048/*波特率为2400时,波特率因子(除数)为48*/
#defineSER_BAUD_960012/*波特率为9600时,波特率因子(除数)为12*/
#defineSER_BAUD_192006/*波特率为19200时,波特率因子(除数)为6*/
#defineCOM_10x3F8/*COM1口8250内部寄存器基地址*/
#defineCOM_20x2F8/*COM2口8250内部寄存器基地址*/*/
#defineCOM_30x3E8/*COM3口8250内部寄存器8250基地址*/
#defineCOM_40x2E8/*COM4口8250内部寄存器8250基地址*/
#defineSER_STOP_10/*1位停止位*/
#defineSER_STOP_24/*2位停止位*/
#defineSER_BITS_50/*5位数据位*/
#defineSER_BITS_61/*6位数据位*/
#defineSER_BITS_72/*7位数据位*/
#defineSER_BITS_83/*8位数据位*/
#defineSER_PARITY_NONE0/*无校验*/
#defineSER_PARITY_ODD8/*奇校验*/
#defineSER_PARITY_EVEN24/*偶校验*/
#defineSER_DIV_LATCH_ON128/*DLAB=1*/
#definePIC_IMR0x21/*中断屏蔽寄存器*/
#definePIC_ICR0x20/*中断控制寄存器*/
#defineINT_SER_PORT_00x0C/*COM1与COM3中断向量编号*/
#defineINT_SER_PORT_10x0B/*COM2与COM4中断向量编号*/
/*函数声明*/
voidinterruptfarSerial_Isr();
voidinterruptfarSerial_File();
Open_Serial(intport_base,intbaud,intconfiguration);
Close_Serial(intport_base);
/*全局变量定义,可在各函数间传递参数*/
voidinterruptfar(*Old_Isr)();
/*Old_Isr保存原来的串口中断向量*/
intold_int_mask;
/*保存原来的中断屏蔽寄存器的值*/
intopen_port;
/*当前打开的串口编号*/
unsignedchars[80];
intj=0;
charch=0;
intdone=0;
main()
{
charpress;
chari;
charfname[80];
charfn[80];
/*初始化COM1端口*/
Open_Serial(COM_1,SER_BAUD_1200,SER_PARITY_EVEN|SER_BITS_8|SER_STOP_1);
printf("
com:
1;
bps:
1200;
parity:
even;
bits:
8;
stopbit:
1"
);
pressanykeytobeginsending\n"
enable();
/*开中断*/
memset(s,0,sizeof(s));
//初始化s为零,指针指向s
while
(1)
printf("
SerialCommunication\n"
1.SendChar\n"
2.AcceptChar\n"
3.SendFile\n"
4.AcceptFile\n"
5.Exit\n"
pleaseselectnumber!
\n"
i=getch();
%c\n"
i);
switch(i)
case'
1'
:
printf("
pleaseenterachar:
press=getch();
Serial_Write(press);
break;
2'
Serial_Isr();
break;
3'
Pleaseenterthefilenametobesent:
scanf("
%s"
&
fname);
Serial_Write_File(fname);
4'
Pleaseenterthefilenametopreserve:
fn);
Serial_File(fn);
5'
exit(0);
Close_Serial(COM_1);
/*关闭串口COM1*/
default:
error!
!
"
}
/*-----------初始化串口---------------*/
Open_Serial(intport_base,intbaud,intconfiguration)
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)
{/*保存串口1、3原来的中断向量,以便在退出程序时恢复*/
Old_Isr=getvect(INT_SER_PORT_0);
/*为串口设置新的中断向量,在发生中断时就会调用执行用户所指定的中断服务程序*/
setvect(INT_SER_PORT_0,Serial_Isr);
\nOpeningComPort#1/3...\n"
}
else
/*功能与上面的代码类似,只是处理的对象是串口2、4*/
Old_Isr=getvect(INT_SER_PORT_1);
setvect(INT_SER_PORT_1,Serial_Isr);
printf("
\nOpeningComPort#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):
0xF7));
/*允许中断*/
/*-------------关闭串口--------------*/
Close_Serial(intport_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);
/*恢复原来的串口中断向量*/
\nClosingComPort#1.\n"
setvect(INT_SER_PORT_1,Old_Isr);
\nClosingComPort#2.\n"
/*--------------写串口-----------------*/
Serial_Write(charch)
while(!
(inp(open_port+SER_LSR)&
0x20)){}/*如串口不空闲,则循环等待*/
disable();
/*当上面条件不等,说明串口空闲,退出循环*/
outp(open_port+SER_THR,ch);
/*开始发送数据*/
/*-------------写文件----------------*/
Serial_Write_File()
FILE*fp;
fp=fopen(fname,"
rb"
if(fp==NULL)
{
Failuretoopenthefile!
return;
while((ch=fgetc(fp))!
=eof())
outp(open_port+SER_THR,ch);
fclose(fp);
enable();
/*-------------串口中断服务程序-----------------*/
voidinterruptfarSerial_Isr()
charch;
intx=inp(0x3fd);
//读出线路状态寄存器的值给变量X
intj=1;
disable();
while(j<
5)
x=inp(0x3fd);
if((x&
0x01)==1)
ch=inp(0x3F8);
/*开始接受数据*/
s[j]=ch;
%d----%c\n"
j,ch);
j++;
j=j%50;
j=1;
enable();
outp(PIC_ICR,0x20);
main();
/*写入OCW2,向8259发普通EOI指令*/
voidinterruptfarSerial_File()
FILE*p;
charch;
intx=inp(0x3fd);
intj=1;
p=fopen(fn,"
w"
//用写入的方式打开当前目录名为fn的文件
1000)//从1循环到999
//再次读出变化后的线路状态寄存器的值给变量X
//将值给数组s[j]j在循环
fputc(ch,p);
/*将ch中的字符输出到p指针中,也就是文件fn中*/
j++;
j=j%50;
fclose(fp);
/*写入OCW2,向8259发普通EOI指令*/
3.程序流程图
四.实训体会
经过一个星期的上机实践学习,使我对微机原理与接口技术这门课程有了更进一步的认识和了解,要想学好它要重在实践,要通过不断的对硬件操作才能更好地学习它,通过实践,我也发现我的好多不足之处,首先是自己在编程上比较差,对一些函数的认识和运用还不是很熟悉,其中曾遇到过很多问题,不过通过这次学习也有所改进;
再有对8250的一些寄存器不太了解。
通过实践,使我在这几个方面的认识有所提高。
通过实践的学习,我认到学好计算机要重视实践操作,不仅仅是学习微机原理这门课程,还是其它的课程,以及其它的计算机方面的知识都要重在实践,所以后在学习过程中,我会更加注视实践操作,使自己便好地学好计算机。
备注:
由于设计的时间比较短暂,程序功能不是很完善,请老师批评指正!
!