OS_Dev
驱动中牛
驱动中牛
  • 注册日期2002-01-09
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2934回复:23

Dazzy,能看看吗?模拟串口的问题。

楼主#
更多 发布于:2002-09-30 16:27
我用一个usb芯片来模拟多个串口,就需要使用单片机的I/O引脚模拟RXD,TXD。
我的想法是这样的,比如我要模拟一个2400bps的串口,我选两条pin作为RXD和TXD。那么每一位的时间大概是0.41666毫秒。我可以利用一个定时器中断来得到这个时间。

当有数据要发送的时候,我就按照数据的各个位,每0.4166毫秒改变一次TXD引脚的电平,(当然了,在数据前还要开始位,后面还有结束位,可能有奇偶位,都按0。4166毫秒一位改变引脚电平),不知道这样的做法对不对呢?

对于数据的接收,同样,我每0.4166毫秒去读一次RXD引脚,如果发现一个开始位,就按每0.4166毫秒一次对该引脚进行采样,得到各个数据位,奇偶位等,直到一个停止位。这个方法可行吗?

如果可行,那么,会不会出现我对引脚进行采样的时候正好是在电平变换的边缘?那么读到的值可能会有影响吧?用什么方法避免呢?

如果收到数据后,发现奇偶校验不对,应怎么处理?


问题太多了,请你指点,谢谢!
I know nothing!
OS_Dev
驱动中牛
驱动中牛
  • 注册日期2002-01-09
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2002-10-16 22:21
ddk说一般只有hub和host controller会使用Class=USB。
我想自己定义一个总线类,你看怎么样?
I know nothing!
dazzy
驱动中牛
驱动中牛
  • 注册日期2001-03-23
  • 最后登录2008-08-12
  • 粉丝1
  • 关注0
  • 积分0分
  • 威望10点
  • 贡献值1点
  • 好评度10点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2002-10-15 09:29
最近工作太忙,来不及立即回答,请谅!

我说的写一个bus driver,一个串口driver,是根据ms的driver分层原则而写的。你也可以用一个driver搞定它。

当串口driver处理IoCreateDevice()时,Type为FILE_DEVICE_SERIAL_PORT。

bus driver的AddDevice处理IoCreateDevice()时,Type可以为FILE_DEVICE_USB,在处理PNP的IRP_MN_START_DEVICE时,根据所得的PortNumber来建立设备对象(DeviceObject),在此处理IoCreateDevice()时,Type为FILE_DEVICE_SERIAL_PORT。


关于inf的编写:
bus driver:
[Version]
Signature = \"$CHICAGO$\"
Class=USB
Provider=%ProviderName%
DriverVer=07/18/2001,1.2.0.0
CatalogFile=Yourdriver.CAT

其它部分为正常driver的 inf.

串口driver的inf:
[Version]
Signature = \"$CHICAGO$\"
Provider=%ProviderName%
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} ; PORTS
DriverVer=07/18/2001,1.2.0.0
CatalogFile=Yourdriver.CAT

你应加入一句(用于枚举):
HKR,,\"UpperFilters\",0x00010000,\"serenum\"

串口driver用IOCallDriver()来与bus driver通讯。
OS_Dev
驱动中牛
驱动中牛
  • 注册日期2002-01-09
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2002-10-12 02:59
dazzy大虾,这里又有问题要请教你了:

我根据你的建议,写了两个驱动,一个是bus driver,一个是串口的driver。
在串口 driver中,当IoCreateDeviceObject时,我指定设备类型为FILE_DEVICE_SERIAL_PORT。不知道是不是这样处理?

另外,这两个DRIVER的INF文件应该怎么写?
BUS DRIVER需要模拟成某个新的BUS类的总线DRIVER吗?
串口DRIVER怎么指定设备类?
I know nothing!
dazzy
驱动中牛
驱动中牛
  • 注册日期2001-03-23
  • 最后登录2008-08-12
  • 粉丝1
  • 关注0
  • 积分0分
  • 威望10点
  • 贡献值1点
  • 好评度10点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2002-10-10 12:27
如果bulk pipe不够,你可以在发送或接收数据前发送一个vendor request来指定相应的portnumber。

usb 串口还应该定义一个一个vendor request来取得每个port的特性,比如最大传输波特率等,每次最大传输字节数等。

对于windows driver,你还需将上层传来的IRP拆分为多个IRP,然后传递给usbd。
OS_Dev
驱动中牛
驱动中牛
  • 注册日期2002-01-09
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2002-10-09 14:57
一般说都是在驱动程序里做,至于怎么做,是你自己定义的,这个无所谓,每个人考虑的方法不一样,需要处理的场合不一样。
我说的那个方法只是最简单的一种,不一定适合你。反正,怎么定义这个数据结构是你自己规定的一个协议:你只要保证你的设备端的firmware能够理解驱动程序发来的数据就行了。就这么简单。
I know nothing!
x_zhao
驱动牛犊
驱动牛犊
  • 注册日期2002-07-23
  • 最后登录2002-10-23
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2002-10-09 14:51
比如说我现在需要控制用一条USB线来模拟6个串口,而我选的接口芯片只有3个端口,那只能用你说的第二种方法,这就必须在传送的真实数据前加一个字节来指定这次传输是向哪个串口进行。我想要实现这种方法是不是必须在驱动程序中做文章,由驱动程序根据情况自动添加前面的字节?但是具体怎么实现,你实现过吗?
OS_Dev
驱动中牛
驱动中牛
  • 注册日期2002-01-09
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2002-10-09 10:05
什么寻址字节?能说明白点吗?
I know nothing!
x_zhao
驱动牛犊
驱动牛犊
  • 注册日期2002-07-23
  • 最后登录2002-10-23
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2002-10-09 09:08
请问dazzy,我如何将自己的寻址字节加入USB数据中呢?是不是在驱动程序中来实现。
dazzy
驱动中牛
驱动中牛
  • 注册日期2001-03-23
  • 最后登录2008-08-12
  • 粉丝1
  • 关注0
  • 积分0分
  • 威望10点
  • 贡献值1点
  • 好评度10点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2002-10-09 08:38
os_dev说得很好,一般的usb串口都是这么做的,用bulk管道传输数据;控制管道(vendor request)传输串口的一些设置等命令(比如波特率等),它的portnumber由index指定。
OS_Dev
驱动中牛
驱动中牛
  • 注册日期2002-01-09
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2002-10-08 23:48
很多方法,对于端点较多的usb,你可以用一对端点来模拟一个串口。
对端点少的usb,你可以采用一对端点分用的方法。比如,你可以自己定义一个两个byte的数据结构,第一个byte表示操作的串口,第二个才是数据,每次都发2个byte过来,firmware自己分析。当然,这是个比喻,总之你可以随意控制,方便得很。
I know nothing!
x_zhao
驱动牛犊
驱动牛犊
  • 注册日期2002-07-23
  • 最后登录2002-10-23
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2002-10-08 22:09
请问OS_Dev,你的多个串口是如何分别与主机通讯的,也就是说主机如何表明它想与哪一个串口通讯,是不是要在传送的USB数据中包括寻址信息,你是如何做到的?
dazzy
驱动中牛
驱动中牛
  • 注册日期2001-03-23
  • 最后登录2008-08-12
  • 粉丝1
  • 关注0
  • 积分0分
  • 威望10点
  • 贡献值1点
  • 好评度10点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2002-10-08 11:35
关于STALL endpoint, usb规范上讲了一些。另外看你的实际应用了。

比如说:对于串口传输数据而言,你传输的数据要求一次传输特定的字节数(里面的数据的特定定义),如果由于设备原因(故障),你不能完成传输,这时,你需要STALL.

另外,如果你用BULK PIPE发送一个命令,device接收的命令不正确,需要STALL.

用设备PIPE BULK IN 取状态值时,状态不正常,应该STALL 此PIPE BULK IN.

如果你用BULK PIPE发送一个device不支持的命令,应该STALL此命令.

如果你的串口设备用bulk发送命令取得串口的portnumber, 而此串口不支持多portnumber, 你应该STALL.

用control pipe 发送vendor request, 如果有误,应该对其STALL.
OS_Dev
驱动中牛
驱动中牛
  • 注册日期2002-01-09
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2002-10-07 15:56
Dazzy大虾,又来麻烦你一下了。
什么时候把endpoint设为stall状态?有没有什么规律可循?谢谢
I know nothing!
OS_Dev
驱动中牛
驱动中牛
  • 注册日期2002-01-09
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2002-10-06 11:30
好像除了分,我也不能提供什么帮助给你了,呵呵

只好多次的感谢你了  :)

[编辑 -  10/6/02 by  OS_Dev]
I know nothing!
dazzy
驱动中牛
驱动中牛
  • 注册日期2001-03-23
  • 最后登录2008-08-12
  • 粉丝1
  • 关注0
  • 积分0分
  • 威望10点
  • 贡献值1点
  • 好评度10点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2002-10-06 08:04
分我无所谓的。

我知道的告诉你,能帮助你提供一点信息就行了。
OS_Dev
驱动中牛
驱动中牛
  • 注册日期2002-01-09
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2002-10-06 01:46
Dazzy大虾,你太热心了。真的应该好好谢谢你。等搞掂后给你猛加分,呵呵 (当然,如果还有问题,偶就继续请教你,呵呵)

Thank you, very much! :)
I know nothing!
dazzy
驱动中牛
驱动中牛
  • 注册日期2001-03-23
  • 最后登录2008-08-12
  • 粉丝1
  • 关注0
  • 积分0分
  • 威望10点
  • 贡献值1点
  • 好评度10点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2002-10-06 00:50
38400是对于单串口。

9600是可以达到的。 如果采用单定时器,对定时中断次数记数的方法是不错的方法,也是唯一的方法。根据不同的波特率周期采样记数值就不一样。

你完全可以采用定时查询的方式来检测起始位的。要知道你引入的6个外部中断源要占用宝贵的CPU处理时间。既然你可以采用定时查询的方式完成对起始位的检测,大可不必再加上中断方式检测起始位。
OS_Dev
驱动中牛
驱动中牛
  • 注册日期2002-01-09
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
18楼#
发布于:2002-10-05 17:47
Dazzy,你好!
你说的模拟串口能达到38400bps,是指什么情况下啊?

我现在用的20mhz单片机,5个外部中断,模拟六个串口,恐怕要达到这个速度不可能吧。要求到也不高,有4800,9600就可以了。我估计了一下,可能9600都很难,因为虽然中断源足够,但是由于要支持六个口同时全双工工作,那么时钟中断怎么也不够啊。
所以我想了一个笨办法,利用一个时钟中断,定时为最大波特率周期的四分之一,对每个串口采取不同的计数器来计算时间,都是用这一个定时器来管理,每次中断都更新这些计数器,然后根据是否达到一定的时间来决定采样时间。

你有没有更好的办法? 谢谢!
I know nothing!
dazzy
驱动中牛
驱动中牛
  • 注册日期2001-03-23
  • 最后登录2008-08-12
  • 粉丝1
  • 关注0
  • 积分0分
  • 威望10点
  • 贡献值1点
  • 好评度10点
  • 原创分0分
  • 专家分0分
19楼#
发布于:2002-10-05 01:02
你是否每个模拟串口都用独立的一个外部中断源?

你的6个串口是否允许同时传输数据?我想应该是可以的。

每个串口传输的速度是否一样?我想可以不一样。

如果多个串口数据同时传输,你是否都要保证无误接收?如果只有一个模拟串口,那么采用一个定时周期即可。对于两个或者两个以上,采用一个定时周期肯定是不行的。除非每个串口都用一个定时器。至于这个是否为1/4周期,你可以进行测定,选择合适的值。
以前的贴子我所说的方法用于“起始位不是用中断检测的“。如果起始位用中断检测,应该更简单一些。

这样做,中断确实比较频繁。但是换来的是底成本,当然软件复杂度升高,传输速度降低。这就看你如何取舍了。还得看你的CPU处理速度如何?如果快速CPU,那么是能够解决你的问题的。当然,编码时最好用汇编或者关键代码用汇编,以减少冗余代码。如果选用传统的低速51系列CPU,估计传输速度是不会让你满意的。
确定你的最大传输速度是很重要的,这要考虑多种情况。

我说的无用话可能太多,主意还的你自己拿。

祝你好运!


[编辑 -  10/5/02 by  dazzy]
上一页
游客

返回顶部