打印

dos下多串口通讯程序

[复制链接]
4739|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jdwang001|  楼主 | 2012-6-17 20:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
tyw| | 2012-6-17 20:56 | 只看该作者
pc机DOS串口编程.pdf (133.58 KB)

第二章
端口设置
IBM PC 和80x86 兼容机可以连接4 个串行端口,即COM1~COM4,相应的BIOS 中的编
号为COM0~COM3,但程序每次只能对其中一个端口进行存取。计算机启动时,自检程序
就会测试4 个COM 端口是否存在,并把每个COM 端口的I/O 地址写到BIOS 的数据区
0040:0000~0040:0007 共8 个字节,每个COM 地址占用2 个字节。如果系统没有连接串行
端口,BIOS 数据区的这几个单元内容就成为0。用debug 可以查看COM 端口地址。
C>debug
-d 0040:0000 L08
0040:0000 F8 03 F8 02 E8 03 E8 02
上例查看结果表明系统中有4 个COM 端口,对应I/O 地址分别为3F8,2F8,3E8,2E8。
每个COM 端口都包括一组8 位的寄存器,这四个地址都叫做基地址,也就是第一个寄存器
的I/O 地址,其他寄存器的地址按照递增的顺序排列。COM1 的基地址是3F8,COM2 的基
地址是2F8,COM3 的基地址是3E8,COM4 的基地址是2E8。我们通过这些寄存器编程控
制数据接收或者发送。
COM1 及COM3 使用PC 机中断4,COM2 及COM4 使用中断3。

使用特权

评论回复
板凳
jdwang001|  楼主 | 2012-6-18 09:14 | 只看该作者
2# tyw
t叔神勇,等我看完这本秘籍再来讨教。

使用特权

评论回复
地板
jdwang001|  楼主 | 2012-6-18 10:10 | 只看该作者
这个还是没有介绍多个串口怎么使用而不冲突的问题啊,我再看看。。。。。。

使用特权

评论回复
5
tyw| | 2012-6-18 11:10 | 只看该作者
6
jdwang001|  楼主 | 2012-6-18 13:49 | 只看该作者
现在的问题是,将两个串口程序分开来写,任意一个都可以运行,而将两个程序合在一块却只能接收一个端口的数据,这个问题是在??有大神出来解救下啊。。。。。。

使用特权

评论回复
7
jdwang001|  楼主 | 2012-6-18 15:40 | 只看该作者
求助的......精疲力尽了。。。。。。

使用特权

评论回复
8
tyw| | 2012-6-18 16:59 | 只看该作者
本帖最后由 tyw 于 2012-6-18 17:07 编辑

单机通讯时,从机请求通讯,你主机在干什么?不外乎是查询方式或中断方式检查接收端,看有没有起始信号,若有起始信号,主机是怎么响应的?有空就......,没空就......
多机通讯无非是多一个地址识别.
你2个串口分开运行,都能通过,同时运行上能接收一个端口,说明地址识别有问题,只认一个com口,这部分的动作你是怎么做的?3F8,2F8,3E8,2E8 这4个地址你是怎么处理的?

啃书吧!
Visual C TurboC串口通信编程实践 568页 52.4M 高清书签版.part1.rar
Visual C TurboC串口通信编程实践 568页 52.4M 高清书签版.part2.rar  
Visual C TurboC串口通信编程实践 568页 52.4M 高清书签版.part3.rar


IBM PC 和80x86 兼容机可以连接4 个串行端口,即COM1~COM4,相应的BIOS 中的编
号为COM0~COM3,但程序每次只能对其中一个端口进行存取。计算机启动时,自检程序
就会测试4 个COM 端口是否存在,并把每个COM 端口的I/O 地址写到BIOS 的数据区
0040:0000~0040:0007 共8 个字节,每个COM 地址占用2 个字节。如果系统没有连接串行
端口,BIOS 数据区的这几个单元内容就成为0。用debug 可以查看COM 端口地址。
C>debug
-d 0040:0000 L08
0040:0000 F8 03 F8 02 E8 03 E8 02
上例查看结果表明系统中有4 个COM 端口,对应I/O 地址分别为3F8,2F8,3E8,2E8。
每个COM 端口都包括一组8 位的寄存器,这四个地址都叫做基地址,也就是第一个寄存器
的I/O 地址,其他寄存器的地址按照递增的顺序排列。COM1 的基地址是3F8,COM2 的基
地址是2F8,COM3 的基地址是3E8,COM4 的基地址是2E8。我们通过这些寄存器编程控
制数据接收或者发送。
COM1 及COM3 使用PC 机中断4,COM2 及COM4 使用中断3。

使用特权

评论回复
9
jdwang001|  楼主 | 2012-6-18 19:13 | 只看该作者
对双串口处理的思路是,将串口初始化,中断函数程序做成双份,引发中断时分别指向不同的中断函数。也可以观察到设置的串口都打开了,可是在执行中断函数时却出现了问题。只能接收最后一个初始化的串口中断。书里面没有讲到这方面的内容,我也查了好多。真的累了啊。。。。。。

使用特权

评论回复
10
jdwang001|  楼主 | 2012-6-18 19:13 | 只看该作者
对双串口处理的思路是,将串口初始化,中断函数程序做成双份,引发中断时分别指向不同的中断函数。也可以观察到设置的串口都打开了,可是在执行中断函数时却出现了问题。只能接收最后一个初始化的串口中断。书里面没有讲到这方面的内容,我也查了好多。真的累了啊。。。。。。

使用特权

评论回复
11
jdwang001|  楼主 | 2012-6-18 19:27 | 只看该作者
现在发现,中断向量指向了最后一个初始化的端口,
即若
com1_init();
com3_init();
即使向com1发送数据,可是中断向量却指向了com3的中断处理函数。

使用特权

评论回复
12
tyw| | 2012-6-18 19:47 | 只看该作者
http://www.hqew.com/tech/sheji/111398.html
基于PC/104的多串口通讯的设计

作者Email: liang_yue0625@sohu.com
摘    要:提出了一种在PC/104上进行多串口通讯的设计方法,介绍了多串口通讯在DOS平台上的软件设计,采用C语言进行编程,可以方便的移植到其他的平台上。
关 键 字:串行通讯;PC104;
0 引 言
    目前,最先进的嵌入式工业计算机PC/l04,以其优良的品质、高可靠性及模块化,广泛应用于工业控制、航空航天、军事、医疗、消防设备、智能仪器仪表、导航、通讯、数控、自动化生产设备的数据采集、便携式计算机等领域。而在实际的应用中,有时需要借助微机的数据处理能力和丰富的软件资源,使组成的系统功能更为强大。这样必须实现PC机与PC104之间的通讯,在通常实时性要求不高,数据量不大的情况下,可以采用串口进行通讯,但通常一般的PC机只配有两个串口,在控制领域有时候是不够的,而基于PC/104结构的嵌入式系统可以根据实际的要求通过简单的搭积木的方法进行配置,其功能模块比较丰富,当进行多串口控制时可以选用基于PC104的多串口卡(一般扩展4~6个串口)。
    本文采用的是HXL-COM4A的4串口扩展板,该板上集成了高性能的16C554控制芯片(相当于4个16C550),每个通道有独立的16字节接收缓冲器和16字节发送缓冲器,可以达到更高的通讯速率而无需占用过多的CPU资源,并且每个串口可配制成RS232RS422RS485模式。
1  多串口通讯软件的设计:
    由于大部分的基于PC/104软件的设计都是在DOS平台上的,所以本文以BRAODLORD C为编译环境进行设计多串口通讯软件的设计。程序框图见图1
    一般情况下串口的地址是:COM1:3F8 COM2:2F8 COM3:3E8 COM4:2E8 COM5:3A8   COM6:2A8, 如有区别参照多串口卡的手册。
    1.1串口波特率和数据格式的设置:
    首先向LCR(线路设置寄存器)的高位写入1,然后在设置波特率:在基地址和基地址+1的地方写入的数据为1843200/(16*波特率)。然后设置LCR,最后设置Modem控制寄存器和中断允许寄存器。
    代码如下:
void init_com(int com_X)
{ outportb(com_X+3,0x80);
outportb(com_X,0x06);
outportb(com_X+1,0x00);//波特率为19200
outportb(com_X+3,0x0b);//数据格式:8个数据位,一个停止位,奇校验
outportb(com_X+4,0x0b);//允许将中断信号送到系统总线
outportb(com_X+1,0x01);}//允许接收产生中断
    1. 2中断的允许和禁止:
    一般情况下,串口通常配置成接收产生中断,发送不产生中断。在PC/104上的设计可以参照PC机的设计方式,中断控制器为两片8259,一片为主片,另一片为从片。当串口所用的中断为8以下时,设置主片8259的IMR(中断屏蔽寄存器)。当中断为8以上时,要设置从片的8259的IMR。
    代码如下:
void OpenInterrupt(unsigned char IntNum)//开中断
{
int mask;
char ControlWord[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
mask=inportb(0x21);
if(IntNum<8) outportb(0x21,mask&ControlWord[IntNum]);
else
{ outportb(0xa1,inportb(0xa1)&ControlWord[IntNum-8]);
  outportb(0x21,inportb(0x21)&0xfb);
}
}
  void CloseInterrupt(unsigned char IntNum) file://关中断
{
char
ControlWord[8]={0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80};
if(IntNum<8){outportb(0x21,inportb(0x21)|ControlWord[IntNum]);}
else outportb(0xa1,inportb(0xa1)|ControlWord[IntNum-8]);
}
    串口的中断可以在PC/104的板子上参照手册,进行跳线设计。
    1. 3串口通讯的中断向量设置:
    当中断小于8时,中断向量地址为中断号加8,当中断大于8时,中断向量地址为中断号加0x68。
下面是完整的串口初始化程序(以COM1为例)
void int_setup(unsigned char comPort,char control)
{
static void interrupt (*old_int)(void);
static void interrupt (*new_int)(void);
int baseAdd;
if(comPort<8) baseAdd=8;
else baseAdd=0x68;
disable();
if(control!=0)//当control为1时是串口的初始化,为0时是恢复系统状态
{init_com(comBaseAddr[comPort]);
switch (comPort)
{case 4: old_int = oldhandler_com1;
  new_int = handler_com1;
  break; }
old_int = getvect(baseAdd+comPort);
setvect(baseAdd+comPort, new_int); file://保存旧中断向量地址,并设置新的中断向量地址
OpenInterrupt(comPort);}
else
{CloseInterrupt(comPort);
setvect(baseAdd+comPort,old_int);}//恢复中断向量地址
enable();}
    1. 4串口数据的发送和接收:
    当串口需要发送数据时,只要将待发送的数据以字符串的形式依次写入基地址中即可。当接收数据时,由于每接收到一个字符便产生一个中断,因此要在中断服务子程序的最后向8259写入20H到地址20H即可,如果中断号大于8,还要向从片8259写入20H到地址A0H。
2 串口的硬件设计
    目前较为常用的串口有9针串口(DB9)和25针串口(DB25),通信距离较近时(<12m),可以用电缆线直接连接标准RS232端口。若距离较远,需附加调制解调器(MODEM)。最为简单且常用的是三线制接法,即地、接收数据和发送数据三脚相连,只需要如图2进行连接即可。
    目前较为常用的串口有9针串口(DB9)和25针串口(DB25),通信距离较近时(<12m),可以用电缆线直接连接标准RS232端口。若距离较远,需附加调制解调器(MODEM)。最为简单且常用的是三线制接法,即地、接收数据和发送数据三脚相连,只需要如图2进行连接即可。
    3 结束语:
本文较全面介绍了基于PC/104的多串口卡的通讯软件的设计,提出了串口通讯应注意的问题,并将此串口通讯软件应用在大庆油田的数据采集系统中,系统工作稳定,可靠。


使用特权

评论回复
13
tyw| | 2012-6-18 19:53 | 只看该作者
本帖最后由 tyw 于 2012-6-18 19:57 编辑

转录了一段东西,参考一下.


想在TC下,用一个C程序中同时使用COM1和COM3接受数据,用的是中断法,由于COM1的中断向量为IRQ4而COM3的中断向量默认也是IRQ4,所以会产生冲突,只能有一个串口能接受到数据。

http://topic.csdn.net/u/20100603/22/6711b0d1-262b-4adf-8670-28fa2e55fd7b.html

想在TC下,用一个C程序中同时使用COM1和COM3接受数据,用的是中断法,由于COM1的中断向量为IRQ4而COM3的中断向量默认也是IRQ4,所以会产生冲突,只能有一个串口能接受到数据。
  如果分别给COM1和COM3编程接受数据,用的也是同一个中断向量却是能接受到数据的,不知为什么,望达人能指教。
  另外,按照PC104的BIOS设置将COM3的中断向量号改成IRQ7或IRQ5仍然接受不到数据,仍然只能是将COM3的中断向量号取成IRQ4才能接受到。因此怀疑BIOS的设置没有生效,但是在设备管理器里却可以看到各个串口对应的中断向量已经改变了(我在PC104上装的是XP)。非常纠结。
  请各位不吝赐教。
  谢谢!

貌似是这样的。我换作DOS下就可以运行得到结果了。

使用特权

评论回复
14
jdwang001|  楼主 | 2012-6-19 08:20 | 只看该作者
这些我也都看了。我等会儿再PC\104下测试测试,希望能通过。。。

使用特权

评论回复
15
Tinnal| | 2012-6-20 18:07 | 只看该作者
jdwang001,刚看到你的贴。你的问题解决没有?

对于那两个共用中段的串串口,不能写两个中断服务程序,因为一个中断只能对应一个中断服务程序。如果多次安装同一个中断的中断服务程序,后一个就会覆盖前一个。因此就出现你说的“只能接收最后一个初始化的串口中断”。
对于具有共同中断的多个串口,只能由一个统一的驱动,统一的中断服务程序来外理。此时,任何一个串口有数据,就都会调用这个中断服务程序。中断服务程序接下去需要自己轮训复用中断线的各个串口的状态寄存器,看看哪个是真正产生中断的串口(产生中断的串口的状态寄存器是有标记位的),确定这个串口后,就可以和单串口的驱动一样往下操作了。

其实,一般来于,驱动只会按类别来编写,像你这样,就算我有COM1~4 4个串口,我也只会写一个驱动、一个中断处理程序。除非一个是ISA串口, 一个是PCI串口,这样情况下就属于不同类别了,操作方法都不一样,就得写两个驱动了。

另外,这个复用中断线的方式你一写要熟悉起来。因为PCI设备经常复用。LINUX等系统里头有大量共享中断的需求,毕竟,中断是很珍贵的一种资源。
ps:如果你以后还开发其它驱动,你会发现比中断还珍贵的是DMA。因少而珍贵。

使用特权

评论回复
16
jdwang001|  楼主 | 2012-6-24 13:07 | 只看该作者
15# Tinnal
非常感谢TInnal大哥的指点,有了这方向,估计很快就能搞定。
真的麻烦了。。。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

316

帖子

1

粉丝