上图就是西门子品牌的电传打字机,怎么样,帅吧。还是拆了看下里面的电路板吧,你要是有兴趣的话,还可以找一找串口在哪里。
时光荏苒,个人计算机出现了,这些已有的串口设备毫无疑问地成为了最初的外设,自然而然地RS232标准被个人计算机采纳。但是设备制造商倾向于体积更小,成本更低的接口,因此,将DB25中未使用的和支持同步模式的引脚去掉,形成DB9。
最初的情况相当混乱,因为DB9只定义了信号,却没有指定信号和引脚的对应关系,各个制造商只能自行定义。幸运的是,IBM的PC成了工业标准,DB9逐渐统一到IBM的定义上来。
DB9只有9根线,遵循RS232标准。定义如下:
DTR,DSR------DTE设备准备好/DCE设备准备好。主流控信号。
RTS,CTS------请求发送/清除发送。用于半双工时,收发切换。属于辅助流控信号。半双工的意思是说,发的时候不收,收的时候不发。那么怎么区分收发呢?缺省时是DCE向DTE发送数据,当DTE决定向DCE发数据时,先有效RTS,表示DTE希望向DCE发送,一般DCE不能马上转换收发状态,DTE就通过监测CTS是否有效来判断可否发送,这样避免了DTE在DCE未准备好时发送所导致的数据丢失。
全双工时,这两个信号一直有效即可。
后来,计算机普及了,很多非RS232的串口也要接入PC机,如果为每一种新出现的串口都增加一个新的I/O口显然不现实,因为PC后面板位置有限,因此,将RS232串口和非RS232串口都通过RS232口接入是最佳方案。UART的U(通用)指的就是这个意思。
早期ROM BIOS和DOS里的通信软件都是为RS232设计的,在没有检测到DCD有效前不会发送数据,因此,就连发送一个字符这样朴素的应用也要给出DCD、DTR、DSR等控制信号。因此,串口接头上要将一些控制线短接,或者干脆绕过系统软件自己写通信程序。
下面给出一个当年的DOS下编写的串口驱动,大家体会下串口的具体操作过程。
#include <stdio.h>
#include "dos.h"
#include "conio.h"
#define BUFFLEN 1024
void InitCOM();/* 初始化串口 */
void OpenPort();/* 打开串口 */
void ClosePort();/* 关闭串口,释放串口资源 */
void interrupt asyncint();/* 新的中断函数 */
void interrupt(*asyncoldvect)();/* 中断向量:用于保护中断现场 */
unsigned char Buffer[BUFFLEN];
int buffin = 0;
int buffout = 0;
void OpenPort()
{
unsigned char ucTemp;
InitCOM();
asyncoldvect = getvect(0x0c);
disable();
inportb(0x3f8);
inportb(0x3fe);
inportb(0x3fb);
inportb(0x3fa);
outportb(0x3fc, 0x08|0x0b);
outportb(0x3f9, 0x01);
ucTemp = inportb(0x21)&0xef;
outport(0x21, ucTemp);
setvect(0x0c, asyncint);
enable();
}
void interrupt asyncint()
{
Buffer[buffin++] = inportb(0x3f8);
if(buffin >= BUFFLEN) buffin = 0;
outportb(0x20, 0x20);
}
void ClosePort(void)
{
disable();
outportb(0x3f9, 0x00);
outportb(0x3fc, 0x00);
outportb(0x21, inportb(0x21)&0x10);
enable();
setvect(0x0c, asyncoldvect);
}
void InitCOM()
{
outportb(0x3fb, 0x80);
outportb(0x3f8, 0x0c);/* 波特率设置为9600 */
outportb(0x3f9, 0x00);
outportb(0x3fb, 0x03);
outportb(0x3fc, 0x08|0x0b);
outportb(0x3f9, 0x01);
}
unsigned char read_char(void)
{
unsigned unch;
if(buffout != buffin)
{
unch = Buffer[buffout];
buffout++;
if(buffout >= BUFFLEN) buffout = 0;
return(unch);
}
else
return(0xff);
}
void send_char(unsigned char unch)
{
while(((inp(0x3f8+5)) & 0x40) ==0);
outportb(0x3f8, unch);
}
void main()
{
unsigned char unChar;
short bExit_Flag = 0;
OpenPort();
fprintf(stdout, "\n\nReady to Receive DATA\n"
"Press [SEC] to quit...\n\n");
do
{
if(kbhit())
{
unChar = getch();
switch(unChar)
{
case 0x1b:
bExit_Flag = 1;
break;
}
if(!bExit_Flag)
send_char(unChar);
}
unChar = read_char();
if(unChar!= 0xff)
{
fprintf(stdout,"%c", unChar);
}
}while(!bExit_Flag);
ClosePort();
}
到此为止,UART的涵义就可以总结为:通用的 异步 (串行) I/O口。
就在UART冠以通用二字,准备一统江湖的时候,制造商们不满于它的速度、体积和灵活性(软件可配置),推出了USB和1394串口。目前,台式机和笔记本上的UART串口有被取消的趋势,有串口的计算机主板已经是凤毛麟角了,因而有资深的网友发出了“没有串口,吾谁与归”的慨叹,古今多少事,都付笑谈中,USB取代UART是后话,暂且不表。