ReadMe.txt 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. ========================================================================
  2. 动态链接库:TCLCommand 项目概述
  3. ========================================================================
  4. 应用程序向导已为您创建了此 TCLCommand DLL。
  5. 本文件概要介绍组成 TCLCommand 应用程序的
  6. 的每个文件的内容。
  7. TCLCommand.vcproj
  8. 这是使用应用程序向导生成的 VC++ 项目的主项目文件,
  9. 其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
  10. TCLCommand.cpp
  11. 这是主 DLL 源文件。
  12. 此 DLL 在创建时不导出任何符号。因此,在生成此 DLL 时
  13. 将不会产生 .lib 文件。如果希望此项目
  14. 成为其他某个项目的项目依赖项,则需要
  15. 添加代码以从 DLL 导出某些符号,
  16. 以便产生一个导出库,或者,也可以在项目“属性页”对话框中的
  17. “链接器”文件夹中,将“常规”属性页上的
  18. “忽略输入库”属性设置为“是”。
  19. /////////////////////////////////////////////////////////////////////////////
  20. 应用程序向导创建了下列资源:
  21. TCLCommand.rc
  22. 这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。
  23. 此文件可以直接在 Microsoft Visual C++ 中进行编辑。
  24. Resource.h
  25. 这是标准头文件,可用于定义新的资源 ID。
  26. Microsoft Visual C++ 将读取并更新此文件。
  27. /////////////////////////////////////////////////////////////////////////////
  28. 其他标准文件:
  29. StdAfx.h, StdAfx.cpp
  30. 这些文件用于生成名为 TCLCommand.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
  31. /////////////////////////////////////////////////////////////////////////////
  32. 其他注释:
  33. 应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
  34. /////////////////////////////////////////////////////////////////////////////
  35. 读写超时是在 调用 ReadFile 和 WriteFile 函数读写串口的时候系统提供的超时机制
  36. typedef struct _COMMTIMEOUTS {
  37. DWORD ReadIntervalTimeout; /* Maximum time between read chars. */
  38. DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */
  39. DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */
  40. DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */
  41. DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */
  42. } COMMTIMEOUTS,*LPCOMMTIMEOUTS;
  43. 读超时 有两只计算方法
  44. 1:(间隔超时)ReadIntervalTimeout 指定了在接收字符间的最大时间,如果超过了这个时间,ReadFile立即返回。
  45. 2:(总超时)基于要接收的字符数量
  46. ReadTotalTimeoutMultiplier表示平均读一个字节的时间上限
  47. ReadTotalTimeoutConstant表示读数据总时间常量
  48. 读数据总超时:ReadTotalTimeoutConstant +(ReadTotalTimeoutMultiplier*要读的字节数)
  49. 读数据超时,两种超时同时有效,当出现任何一种超时时,ReadFile都将返回。
  50. 写超时:
  51. WriteTotalTimeoutMultiplier表示平均写一个字节的时间上限
  52. WriteTotalTimeoutConstant表示写数据总超时常量
  53. 写数据总超时 :WriteTotalTimeoutConstatn +(WriteTotalTimeoutMultiplier *要写的字节数)
  54. 具体超时设置
  55. 1:有读间隔超时、读总超时、写总超时,将COMMTIMEOUTS结构5个成员设置为对应值。
  56. 2:没有读间隔超时,有读总超时和写总超时,将RealIntervalTimeou设置为0,其他参数设置为对应值。
  57. 3:不管是否有数据要读取,ReadFile立即返回,将RealIntervalTimeout设置为MAX_DWORD,
  58. 将ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都设置为0
  59. (不立即返回的时候,可以在超时时间内等串口中有新的数据?然后读取,直到超时时间)
  60. 4:ReadFile没有超时设置,直到有适当的字符数返回或者错误发生,函数才返回。
  61. 将 ReadIntervalTimeout、ReadTotalTimeoutMultiplier、ReadTotalTimeoutConstant都设置为0
  62. 5:WriteFile没有超时设置:将WriteTotalTimeoutMultiplier和WriteTotalTimeoutConstant设置为0
  63. /////////////////////////////////////////////////////////////////////////////
  64. COMMTIMEOUTS 结构体被用在SetCommTimeouts和GetCommTimeouts 函数中,以便设置和查询通讯设备的超时参数。这个参数决定ReadFile, WriteFile, ReadFileEx, 和WriteFileEx 操作设备的行为。
  65. typedef struct _COMMTIMEOUTS {
  66. DWORD ReadIntervalTimeout;
  67. DWORD ReadTotalTimeoutMultiplier;
  68. DWORD ReadTotalTimeoutConstant;
  69. DWORD WriteTotalTimeoutMultiplier;
  70. DWORD WriteTotalTimeoutConstant;} COMMTIMEOUTS, *LPCOMMTIMEOUTS;
  71. 成员
  72. ReadIntervalTimeout
  73. 在通讯过程中接收两个字符之间的最长超时时间,按毫秒计算。在ReadFile操作,当接收到第一个字符时,开始一个计时周期。如果接收任意两个字符之间的时隔超过本限制,ReadFile操作将完成并返回任何已缓冲的数据。0代表本参数未设置。
  74. 如果设置为MAXDWORD, 并且ReadTotalTimeoutConstant和ReadTotalTimeoutMultiplier成员为0,代表读取操作立即返回那些已接收的数据,即使没有收到任何字符。(两个字符之间的接收间隔)
  75. ReadTotalTimeoutMultiplier
  76. 乘数用于计算读取操作的总超时时间,按毫秒计算。对于每个读取操作,这个值将乘以要读取的字节数。(读取单个字符的最大超时)
  77. ReadTotalTimeoutConstant
  78. 一个用于计算对于读取操作的总超时周期的常数,按毫秒计算。对每次读取操作,实际总超时时间为ReadTotalTimeoutMultiplier 成员与请求的字节数年的乘积加此值。
  79. ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant成员为0代表总读取总超时时间无效(读取所有字节的时间为ReadTotalTimeoutMultiplier*BytesToRead+ReadTotalTimeoutConstant)。
  80. WriteTotalTimeoutMultiplier
  81. 乘数用来计算写操作的总超时周期,按毫秒计算。对每个写操作,这个值将乘以要写入的字节数。(写单个字符的最大超时)
  82. WriteTotalTimeoutConstant
  83. 一个用于计算写入操作的总超时周期的常数,按毫秒计算。对于每一次写入操作,实际总超时时间为WriteTotalTimeoutMultiplier 成员与要写入字节的乘积再加此值.
  84. WriteTotalTimeoutMultiplier和WriteTotalTimeoutConstant成员为0代表总写入时间无效(写入所有字节的时间为WriteTotalTimeoutMultiplier*BytesToWrite+WriteTotalTimeoutConstant)。
  85. 备注
  86. 如果一个应用程序设置ReadIntervalTimeout和ReadTotalTimeoutMultiplier为 MAXDWORD并且设置ReadTotalTimeoutConstant 为一个大于零且小于MAXDWORD的值, 在调用ReadFile时将会发生如下现象:
  87. 如果在输入缓冲区中有任何字符,ReadFile 立即返回缓冲区中的内容。
  88. 如果在缓冲区中没有任何字符,ReadFile 将等待接收到一个字符并立即返回.
  89. 如果在ReadTotalTimeoutConstant指定的时间值内无任何字节返回,ReadFile超时.
  90. /////////////////////////////////////////////////////////////////////////////
  91. 串口读取事件分为两个阶段(我以Win32 API函数ReadFile读取串口过程来说明一下)
  92. 第一个阶段是:串口执行到ReadFile()函数时,串口还没有开始传输数据,所以串口缓冲区的第一个字节是没有装数据的,这时候总超时起作用,如果在总超时时间内没有进行串口数据的传输,ReadFile()函数就返回,当然 没有读取到任何数据。而且,间隔超时并没有起作用。
  93. 第二阶段:假设总超时为20秒,程序运行到ReadFile(),总超时开始从0 计时,如果在计时到达10秒时,串口开始了数据的传输,
  94. 那么从接收的第一个字节开始,间隔超时就开始计时,假如间隔超时为1ms,那么在读取完第一个字节后,串口开始等待1ms,
  95. 如果1ms之内接收到了第二个字节,就读取第二个字节,间隔超时重置为0并计时,等待第三个字节的到来,
  96. 如果第三个字节到来的时间超过了1ms,那么ReadFile()函数立即返回,这时候总超时计时是没到20秒的。
  97. 如果在20秒总计时时间结束之前,所有的数据都遵守数据间隔为1ms的约定并陆陆续续的到达串口缓冲区,那么就成功进行了一次串口传输和读取;
  98. 如果20秒总计时时间到,串口还陆陆续续的有数据到达,即使遵守字节间隔为1ms的约定,ReadFile()函数也会立即返回,这时候总超时就起作用了。
  99. 总结起来,总超时在两种情况下起作用
  100. 第一:串口没进行数据传输,等待总超时时间那么长ReadFile()才返回。非正常数据传输
  101. 第二:数据太长,总超时设置太短,数据还没读取完就返回了。读取的数据是不全的
  102. 间隔超时触发是有条件的
  103. 第一:在总超时时间内。
  104. 第二:串口进行了数据的传输。
  105. 成功的进行一次串口数据的传输和读取,只有总超时和间隔超时相互参与配合才能完成
  106. /////////////////////////////////////////////////////////////////////////////
  107. Command.data文件格式说明,键值对形式存在[key=value]:
  108. Key说明:
  109. name 表示命令名称;
  110. option 表示命令类型
  111. 1、Get 表示指令用于查询,不用传入外部数据,需要返回查询结果。
  112. 2、Set 表示指令用于设置,需要传入外部数据,需要返回设置结果。
  113. 3、None 表示指令不是查询指令,不用传入外部数据,无查询结果返回;也不是设置指令,不用传入外部数据,无设置结果返回。
  114. 更确切的说,Get不用传数据,Set要传入数据;
  115. Get和Set都要返回除“AB 05 0A DF 4E”外的第二段串口数据(失败除外),而None只返回一段“AB 05 0A DF 4E”的数据。
  116. head 表示命令的协议头,以十六进制字符表示,多个字节以空格隔开;
  117. cmd 表示命令的具体指令,以十六进制字符表示,只有有且一个字节;
  118. param 表示命令的具体指令所附加参数,以十六进制字符表示,多个字节以空格隔开;
  119. returnParam 与param关联使用,表示指令返回结果时,是否会将param一起返回。
  120. readWaitTime 表示指令在串口Write之后,多久才开始串口Read指令结果
  121. cmdWaitTime 表示当前指令完成串口Read后,等待多久进行下一条指令操作。
  122. /////////////////////////////////////////////////////////////////////////////