tag 标签: api

相关博文
  • 热度 1
    2023-11-27 08:45
    842 次阅读|
    0 个评论
    【Linux API 揭秘】module_init与module_exit Linux Version:6.6 Author:Donge Github: linux-api-insides 1、函数作用 module_init和module_exit是驱动中最常用的两个接口,主要用来注册、注销设备驱动程序。 并且这两个接口的实现机制是一样的,我们先以module_init为切入点分析。 2、module_init函数解析 2.1 module_init # ifndef MODULE /** *module_init()-driverinitializationentrypoint *@x:functiontoberunatkernelboottimeormoduleinsertion * *module_init()willeitherbecalledduringdo_initcalls()(if *builtin)oratmoduleinsertiontime(ifamodule).Therecanonly *beonepermodule. */ # define module_init(x)__initcall(x); ...... # else /*MODULE*/ ...... /*Eachmodulemustuseonemodule_init().*/ # define module_init(initfn)\ staticinlineinitcall_t__maybe_unused__inittest(void)\ {returninitfn;}\ intinit_module(void)__copy(initfn)\ __attribute__((alias(#initfn)));\ ___ADDRESSABLE(init_module,__initdata); ...... # endif 函数名称 :module_init 文件位置 : include/linux/module.h 函数解析 : 在Linux内核中,驱动程序可以以两种方式存在:内建(Builtin)和模块(Module)。内建驱动就是在编译时,直接编译进内核镜像中;而模块驱动则是在内核运行过程中动态加载卸载的。 module_init函数的定义位置有两处,使用MODULE宏作为判断依据。MODULE是一个预处理器宏,仅当该驱动作为模块驱动时,编译的时候会加入MODULE的定义。 这里难免会有疑问:为什么会有两套实现呢? 其实,当模块被编译进内核时,代码是存放在内存的.init字段,该字段在内核代码初始化后,就会被释放掉了,所以当可动态加载模块需要加载时,就需要重新定义了。 2.1.1 模块方式 当驱动作为可加载模块时,MODULE宏被定义,我们简单分析一下相关代码 # define module_init(initfn)\ staticinlineinitcall_t__maybe_unused__inittest(void)\ {returninitfn;}\ intinit_module(void)__copy(initfn)\ __attribute__((alias(#initfn)));\ ___ADDRESSABLE(init_module,__initdata); static inline initcall_t __maybe_unused __inittest(void) { return initfn; }:一个内联函数,返回传入的initfn函数。 __maybe_unused :编译器指令,用于告诉编译器,该函数可能不会使用,以避免编译器产生警告信息。 int init_module(void) __copy(initfn) __attribute__((alias(#initfn)));:init_module函数的声明 __copy(initfn):编译器指令,也就是将我们的initfn函数代码复制到init_module中, __attribute__((alias(#initfn))):编译器指令,将init_module函数符号的别名设置为initfn。 ___ADDRESSABLE(init_module, __initdata);:一个宏定义,主要用于将init_module函数的地址放入__initdata段,这样,当模块被加载时,init_module函数的地址就可以被找到并调用。 总的来说,如果是可加载的ko模块,module_init宏主要定义了init_module函数,并且将该函数与initfn函数关联起来,使得当模块被加载时,初始化函数可以被正确地调用。 2.1.2 内建方式 当模块编译进内核时,MODULE宏未被定义,所以走下面流程 # define module_init(x)__initcall(x); 2.2 __initcall # define __initcall(fn)device_initcall(fn) # define device_initcall(fn)__define_initcall(fn,6) # define __define_initcall(fn,id)___define_initcall(fn,id,.initcall##id) # define ___define_initcall(fn,id,__sec)\ __unique_initcall(fn,id,__sec,__initcall_id(fn)) # define __unique_initcall(fn,id,__sec,__iid)\ ____define_initcall(fn,\ __initcall_stub(fn,__iid,id),\ __initcall_name(initcall,__iid,id),\ __initcall_section(__sec,__iid)) # define ____define_initcall(fn,__unused,__name,__sec)\ staticinitcall_t__name__used\ __attribute__((__section__(__sec)))=fn; # define __initcall_stub(fn,__iid,id)fn /*Format: __ _ _ */ # define __initcall_id(fn)\ __PASTE(__KBUILD_MODNAME,\ __PASTE(__,\ __PASTE(__COUNTER__,\ __PASTE(_,\ __PASTE(__LINE__,\ __PASTE(_,fn)))))) /*Format:__ __ */ # define __initcall_name(prefix,__iid,id)\ __PASTE(__,\ __PASTE(prefix,\ __PASTE(__,\ __PASTE(__iid,id)))) # define __initcall_section(__sec,__iid)\ #__sec ".init" /*Indirectmacrosrequiredforexpandedargumentpasting,eg.__LINE__.*/ # define ___PASTE(a,b)a##b # define __PASTE(a,b)___PASTE(a,b) 函数名称 :__initcall 文件位置 : include/linux/init.h 函数解析 :设备驱动初始化函数 2.2.1 代码调用流程 module_init(fn) __initcall(fn) device_initcall(fn) __define_initcall(fn, 6 ) ___define_initcall(fn,id,__sec) __initcall_id(fn) __unique_initcall(fn,id,__sec,__iid) ____define_initcall(fn,__unused,__name,__sec) __initcall_stub(fn,__iid,id) __initcall_name(prefix,__iid,id) __initcall_section(__sec,__iid) ____define_initcall(fn,__unused,__name,__sec) 进行函数分析前,我们先要明白#和##的概念 2.2.2 #和##的作用 符号 作用 举例 ## ##符号 可以是连接的意思 例如 __initcall_##fn##id 为__initcall_fnid那么,fn = test_init,id = 6时,__initcall##fn##id 为 __initcall_test_init6 # #符号 可以是 字符串化的意思 例如 #id 为 "id",id=6 时,#id 为"6" 更多干货可见: 高级工程师聚集地 ,助力大家更上一层楼! 2.2.3 函数解析 下面分析理解比较有难度的函数 # define device_initcall(fn)__define_initcall(fn,6) # define __define_initcall(fn,id)___define_initcall(fn,id,.initcall##id) .initcall##id:通过##来拼接两个字符串:.initcall6 # define ___define_initcall(fn,id,__sec)\ __unique_initcall(fn,id,__sec,__initcall_id(fn)) /*Format: __ _ _ */ # define __initcall_id(fn)\ __PASTE(__KBUILD_MODNAME,\ __PASTE(__,\ __PASTE(__COUNTER__,\ __PASTE(_,\ __PASTE(__LINE__,\ __PASTE(_,fn)))))) /*Indirectmacrosrequiredforexpandedargumentpasting,eg.__LINE__.*/ # define ___PASTE(a,b)a##b # define __PASTE(a,b)___PASTE(a,b) ___PASTE:拼接两个字符串 __initcall_id: 它用于生成一个唯一的标识符,这个标识符用于标记初始化函数 。 __KBUILD_MODNAME:当前正在编译的模块的名称 __COUNTER__:一个每次使用都会递增计数器,用于确保生成名称的唯一性 __LINE__:当前代码的行号 # define __unique_initcall(fn,id,__sec,__iid)\ ____define_initcall(fn,\ __initcall_stub(fn,__iid,id),\ __initcall_name(initcall,__iid,id),\ __initcall_section(__sec,__iid)) # define ____define_initcall(fn,__unused,__name,__sec)\ staticinitcall_t__name__used\ __attribute__((__section__(__sec)))=fn; # define __initcall_stub(fn,__iid,id)fn /*Format:__ __ */ # define __initcall_name(prefix,__iid,id)\ __PASTE(__,\ __PASTE(prefix,\ __PASTE(__,\ __PASTE(__iid,id)))) # define __initcall_section(__sec,__iid)\ #__sec ".init" __unique_initcall:调用____define_initcall,关键实现部分 ____define_initcall:定义一个名为 __name 的 initcall_t 类型的静态变量,并将其初始化为 fn,并放入特定的__sec段中。 __initcall_stub:表示唯一的函数名fn __initcall_name:表示一个唯一的变量名 __initcall_section: 生成一个唯一的段名。 #__sec ".init":将两个字符串拼接起来,比如:__sec=.initcall6,拼接后的段为:.initcall6.init,该段为最终存储的段。 字段通过链接器链接起来,形成一个列表进行统一管理。 这些字段我们可以在arch/arm/kernel/vmlinux.lds中查看。 ...... __initcall6_start=.;KEEP(*(.initcall6.init))KEEP(*(.initcall6s.init)) ...... 3、module_exit函数解析 module_exit和module_init的实现机制几乎没有差别,下面就简单介绍一下。 3.1 module_exit # ifndef MODULE /** *module_exit()-driverexitentrypoint *@x:functiontoberunwhendriverisremoved * *module_exit()willwrapthedriverclean-upcode *withcleanup_module()whenusedwithrmmodwhen *thedriverisamodule.Ifthedriverisstatically *compiledintothekernel,module_exit()hasnoeffect. *Therecanonlybeonepermodule. */ # define module_exit(x)__exitcall(x); ...... # else /*MODULE*/ ...... /*Thisisonlyrequiredifyouwanttobeunloadable.*/ # define module_exit(exitfn)\ staticinlineexitcall_t__maybe_unused__exittest(void)\ {returnexitfn;}\ voidcleanup_module(void)__copy(exitfn)\ __attribute__((alias(#exitfn)));\ ___ADDRESSABLE(cleanup_module,__exitdata); ...... # endif 函数名称 :module_exit 文件位置 : include/linux/module.h 3.1.1 模块方式 作为模块方式,与module_init的实现方式一样,定义cleanup_module与exitfn函数相关联,存放在__exitdata段内。 3.1.2 内建方式 当模块编译进内核时,MODULE宏未被定义,所以走下面流程 # define module_exit(x)__exitcall(x); 3.2 __exitcall # define __exitcall(fn)\ staticexitcall_t__exitcall_##fn__exit_call=fn # define __exit_call__used__section( ".exitcall.exit" ) 函数名称 :__initcall 文件位置 : include/linux/init.h 函数解析 :设备驱动卸载函数 __exitcall_##fn:定义一个新的 exitcall_t 类型的静态变量,并赋值为fn __exit_call:__used __section(".exitcall.exit"),定义该函数存储的段 4、扩展 还记得__define_initcall的定义吗? # define pure_initcall(fn)__define_initcall(fn,0) # define core_initcall(fn)__define_initcall(fn,1) # define core_initcall_sync(fn)__define_initcall(fn,1s) # define postcore_initcall(fn)__define_initcall(fn,2) # define postcore_initcall_sync(fn)__define_initcall(fn,2s) # define arch_initcall(fn)__define_initcall(fn,3) # define arch_initcall_sync(fn)__define_initcall(fn,3s) # define subsys_initcall(fn)__define_initcall(fn,4) # define subsys_initcall_sync(fn)__define_initcall(fn,4s) # define fs_initcall(fn)__define_initcall(fn,5) # define fs_initcall_sync(fn)__define_initcall(fn,5s) # define rootfs_initcall(fn)__define_initcall(fn,rootfs) # define device_initcall(fn)__define_initcall(fn,6) # define device_initcall_sync(fn)__define_initcall(fn,6s) # define late_initcall(fn)__define_initcall(fn,7) # define late_initcall_sync(fn)__define_initcall(fn,7s) # define __initcall(fn)device_initcall(fn) 不同的宏定义,被赋予了不同的调用等级,最后将不同的驱动初始化函数统一汇总到__initcallx_start字段统一管理,形成一个有序的列表。 这样,我们在内核中,按照顺序遍历这个列表,最后执行对应的模块初始化函数fn即可实现驱动的初始化。
  • 热度 3
    2023-11-1 17:28
    1428 次阅读|
    0 个评论
    使用Skydel API构建测试方案 凭借其现代、强大且直观的API,德思特Safran GNSS模拟引擎Skydel免费提供了Python、C#、C++和Labview的开源客户端库,它具有600多条命令,并且有完善的文档与记录。 随着Skydel软件更新添加新功能,API得到改进与软件的发展相同步。了解API的功能不需要具备编程技能,但具有编码经验的高级用户将能够简单的使用API命令并做深度开发,以创建自动化测试和GNSS模拟场景 使用Skydel构建SNMP代理 有一个例子可以很好的说明API的灵活性——通过使用外部OID命令,使用SNMP网络协议来远程驱动您的设备,定制您的系统。可以使用带有特定德思特Safran Skydel API命令的Python脚本构建SNMP子代理,该子代理将成为在系统(Linux或Windows操作系统)上运行的SNMP守护程序的网关,允许SNMP管理功能。 ● SNMP: SNMP,即简单网络管理协议(Simple Network Management Protocol),是一种广泛使用的应用层协议,用于管理和监控网络元素。它由互联网架构委员会根据RFC-1157规范文档定义,用于在网络设备之间交换管理信息,并且是TCP/IP协议的一部分。使用此协议的设备需要启用并配置SNMP代理,以便它们可以与网络管理系统(NMS)进行通信。SNMP代理还负责控制管理信息库(MIB)中定义的控制变量的数据库。 ● OID: OID,即对象标识符(Object Identifier),是一种用于唯一标识网络管理信息的标识符,它类似于一个树状结构,用于表示不同类型的管理信息,例如网络设备的参数、性能统计和配置数据。SNMP使用OID来定位和获取这些管理信息。 如果你想通过使用外部OID命令来远程驱动你的设备,你需要了解目标设备支持的OID,然后使用SNMP协议发送相应的请求,以获取或设置相关信息。OID通常以一种类似于点分割的数字串的形式表示,例如1.3.6.1.2.1.1.1表示系统的描述信息。 要使用SNMP协议来远程管理设备,你需要具备一定的SNMP知识,并使用合适的工具或编程语言来发送SNMP请求,以实现设备的定制和管理。 在此配置中,任何Skydel API命令都可以成为SNMP子代理的新OID(对象标识符)。这将使得任何NMS都能将Skydel命令“转换”为SNMP集,并通过网络获取请求来驱动您的Skydel系统。 如何使用德思特Safran GSG-7/8构建SNMP代理 在此配置中,工程师将能够通过SNMP监控Skydel引擎 ,该测试场景旨在能够通过SNMP检查Skydel引擎是否正常运行,通过独特的OID使用设置命令来启动和停止引擎。 德思特Safran提供了一个基本的SNMP入门套件(Skydel SNMP Stater套件),允许用户集成并通过SNMP管理其Skydel引擎。该套件可以通过添加多个新的API命令进行定制,这些命令将转换为新的SNMP OID,以增强监管能力。使用Skydel SNMP Stater套件远程连接到由Skydel软件驱动的外部笔记本电脑上运行的MIB浏览器。 Skydel SNMP Stater套件包含: skydel_snmp.py 发挥SNMP子代理角色(Skydel API命令和SNMP OID之间的桥梁)的Python脚本,可以由用户定制以添加功能。 snmp_pass.py 仅用于全局SNMP设置的Python脚本。对于简单的情况,添加新的OID不需要进行任何更改。 Install.sh 每次出于自定义目的更改Python脚本时都必须执行的“Makefile”命令。 snmpd.conf 附加到snmpd守护程序的配置文件。 SKYDEL-MIB.txt MIB文件示例基于Skydel标准架构构建,可用于与Python脚本中创建的新OID链接进行自定义。此MIB文件还可用于提供NMS或MIB浏览器来测试您的系统。 如果需要进一步了解德思特Safran Skydel的SNMP代理或需要下载相关文档,请联系德思特技术工程师。
  • 热度 20
    2014-8-29 17:19
    892 次阅读|
    0 个评论
    这篇文章会详细描述怎样立即得到指定城市的天气状况(比如首尔),由OpenWeatherMap提供。用JSON(由OpenWeatherMap提供),XML和一个以太网模块,使WIZnet-WizFi250运行起来。 首先,在OpenWeatherMap上检查API内容。 由城市的名称调用。API用一列结果应答,来匹配一个搜索词。在JSON中: api.openweathermap.org/data/2.5/weather?q=London,uk 在XML: api.openweathermap.org/data/2.5/weather?q=Londonmode=xml http://openweathermap.org/current 然后,跟随上面的指导,在电脑上将JSON和XML格式中的首尔天气数据提取出来。下面有一个网络数据包的截屏可以作为参考。 红色高亮部分的数据是由PC发送的。我们准备消除不必要部分,并使用请求数据输入以下数据。 在这步, \r(Carriage return, 0x0d), \n(Line Feed, 0x0a)必须准确输入,并且传送数据(72 Byte, 81 Byte)也要特别注意。 * JSON GET /data/2.5/weather?q=Seoul HTTP/1.1\r\n Host: api.openweathermap.org\r\n\r\n (72 Byte) * XML GET /data/2.5/weather?q=Seoulmode=xml HTTP/1.1\r\n Host: api.openweathermap.org\r\n\r\n (81 Byte) 既然初始化设置已完成,我们将运行WizFi250.首先,在AP上建立联接。 AT+WSET=0,Team Wiki AT+WSEC=0,,12345678 AT+WNET=1 AT+WJOIN Joining : Team Wiki Successfully joined : Team Wiki IP Addr : 192.168.101.33 Gateway : 192.168.101.1 提取OpenWeatherMap API 服务器的IP地址。 AT+FDNS=api.openweathermap.org,3000 128.199.164.95 与OpenWeatherMap API 服务器连接。 AT+SCON=O,TCN,128.199.164.95,80,,0 发送JSON请求数据到 OpenWeatherMap API服务器。 AT+SSEND=0,,,72 (여기에서 위에 설명된 72 Byte를 전송하면 된다.) 然后,OpenWeatherMap API 服务器将用一个JSON回复(如下)来应答。 {0,128.199.164.95,80,857}HTTP/1.1 200 OK Server: nginx Date: Wed, 06 Aug 2014 00:06:49 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive X-Source: redis Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true Access-Control-Allow-Methods: GET, POST 221   继续阅读: http://www.iwiznet.cn/blog/?p=6406 欢迎登陆WIZnet官方网站:http://www.iwiznet.cn WIZnet官方博客:http://weibo.com/wiznet2012
  • 热度 22
    2013-5-9 14:49
    6072 次阅读|
    1 个评论
    在应用WIN32  API 对串口进行编程时, 必定会使用到DCB 结构. 下面的DCB 结构的一些介绍. 首先是DCB 结构. typedef  struct  _DCB {            DWORD DCBlength;                    DWORD BaudRate;                     DWORD fBinary:  1 ;                   DWORD fParity:  1 ;                   DWORD fOutxCtsFlow: 1 ;               DWORD fOutxDsrFlow: 1 ;               DWORD fDtrControl: 2 ;                DWORD fDsrSensitivity: 1 ;           DWORD fTXContinueOnXoff: 1 ;          DWORD fOutX:  1 ;                     DWORD fInX:  1 ;                      DWORD fErrorChar:  1 ;                DWORD fNull:  1 ;                     DWORD fRtsControl: 2 ;                DWORD fAbortOnError: 1 ;              DWORD fDummy2: 17 ;                  WORD wReserved;                              WORD XonLim;                        WORD XoffLim;                       BYTE ByteSize;                      BYTE Parity;                        BYTE StopBits;                       char  XonChar;                        char  XoffChar;                       char  ErrorChar;                      char  EofChar;                        char  EvtChar;                       WORD wReserved1;             } DCB;  在这个结构中, 共有28个变量, 我把这些成员归类为几种. 1.  串口的基本设置      1) DWORD BaudRate;                      波特率设置。        2) BYTE ByteSize;                             数据位设置。      3) DWORD fParity:  1 ;                        TRUE时, 支持奇偶检验。      4) BYTE Parity;                                 奇偶检验位的设置      5) BYTE StopBits;                             停止位的设置 2. 流控制(Flow Control) 的设置      流控制分为硬件流控制和软件流控制。 而硬件流控制又分为RTS/CTS和DTR/DSR两种。而软件流控制, 则是Xon/Xoff。       DTR/DSR 硬件流控制:      1) DWORD fOutxDsrFlow: 1 ;             TRUE时,支持DSR流控制。 当DSR为OFF时,停止发送。      2) DWORD fDtrControl: 2 ;                DTR设置。 (置高/置低...)       fDTRControl DTR_CONTROL_Disable :  使DTR为 off. DTR_CONTROL_Enable :  使DTR 为 on.  DTR_CONTROL_HANDSHAKE : DTR 硬件流控.      3) DWORD fDsrSensitivity: 1 ;            TRUE时,当DSR为OFF,则接收端忽略所有字符。        RTS/CTS 硬件流控制:      4) DWORD fOutxCtsFlow: 1 ;             TRUE时,支持CTS流控制。 当CTS为OFF时,停止发送。      5) DWORD  fRtsControl: 2 ;                RTS设置。 (置高/置低...)                                                                    fRTSControl RTS_CONTROL_DISABLE : 使RTS保持 off RTS_CONTROL_ENABLE : 使RTS保持on RTS_CONTROL_HANDSHAKE :  RTS 硬件流控 RTS_CONTROL_TOGGLE : 485通讯RTS自动流控            Xon/Xoff 软件流控制:      6) DWORD fOutX:  1 ;                       发送端支持Xon/Xoff。收到Xoff停止发送,收到Xon重新开始      7) DWORD fInX:  1 ;                          接收端支持Xon/Xoff。当FIFO中字节超过XoffLim时发送Xoff, 当FIFO中少于XonLim时发送Xon.       8) WORD XonLim;                           当接收Buffer中的字符减少到XonLim规定的字符数, 就发送Xon字符,让对方继续发送。      9) WORD XoffLim;                          接收Buffer达到XoffLim规定的字符数, 就发送Xoff字符, 让对方停止发送。      10) char  XonChar;                           Xon 字符。       11) char  XoffChar;                          Xoff 字符。      12)DWORD fTXContinueOnXoff: 1 ;  TRUE时,不管接收端是否Xoff, 本方发送端持续发送。 (也就是本方的发送端, 与本方接收端Xon/Xoff是相互独立的)。若为False 时,则当接收端buffer 达到XoffLim时,发送端发送完Xoff字符后,就停止发送。                       3.  Error 情况处理      1) DWORD fErrorChar:  1 ;              TRUE时,若fParity为TRUE, 则用ErrorChar替换Parity Check错误的字符。      2) DWORD fAbortOnError: 1 ;             TRUE时,发生错误时停止读写操作。      3) char  ErrorChar;                           Parity Check 错误时,替换的字符。           4. 其他参数      1) DWORD DCBlength;                   DCB结构的长度(以字节为单位)      2) DWORD fBinary:  1 ;                   二进制模式。(必须为1 )      3) DWORD fNull:  1 ;                        TRUE时,接收 时去掉空字节(0x0)      4) char  EofChar;                            EOF替代字符      5)  char  EvtChar;                           事件触发字符      6)  DWORD fDummy2: 17 ;                保留      7) WORD wReserved;                   保留      8) WORD wReserved1;                  保留 下一篇:   《串口编程之二:超时COMMTIMEOUTS结构》
  • 热度 17
    2010-4-13 11:13
    6478 次阅读|
    7 个评论
    《串口编程之一: WIN32 API 中串口DCB 结构的介绍》   在WIN32  API编程中,除了DCB结构之外,还需要了解COMMTIMEOUTS结构.这个结构是为了读写串口的超时而设置的. COMMTIMEOUTS结构如下:         typedef   struct   _COMMTIMEOUTS   {       DWORD   ReadIntervalTimeout;                 //任意相邻连个字符之间的超时设置   DWORD   ReadTotalTimeoutMultiplier;        //读操作总的超时时间的系数   DWORD   ReadTotalTimeoutConstant;       //读操作总的超时时间的修正常量   DWORD   WriteTotalTimeoutMultiplier;       //写操作总的超时时间的系数   DWORD   WriteTotalTimeoutConstant;       //写操作总的超时时间的修正常量   }   COMMTIMEOUTS,*LPCOMMTIMEOUTS;                      ReadIntervalTimeout:两相邻字符之间最大的延时。当读串口数据时,一旦两个字符传输的时间间隔超过该时间,读函数将返回现有的数据。设置为0表示该参数不起作用。             ReadTotalTimeoutMultiplier:读操作总的超时事件的系数。 这个变量是不能单独使用的。 必须和ReadTotalTimeoutConstant 一起使用才有效果。              ReadTotalTimeoutConstant:读操作总的超时时间的修正常量。 这个变量也是不能单独使用的。必须和ReadTotalTimeoutMultiplier一起使用才有效果。           WriteTotalTimeoutMultiplier:写操作总的超时事件的系数。 这个变量是不能单独使用的。 必须和WriteTotalTimeoutConstant 一起使用才有效果。             WriteTotalTimeoutConstant:写操作总的超时时间的修正常量。 这个变量也是不能单独使用的。必须和WriteTotalTimeoutMultiplier一起使用才有效果。        在整个串口的读写操作中, 存在着两种超时设置。一种是间隔超时, 一种是总超时。 这两种超时是独立存在,互不影响的。        间隔超时 , 只在读操作中存在。就是ReadIntervalTimeout。 当读操作中,前后两个字符之间的时间间隔超过时,读操作就结束了。举例来说,你一次读取8个字符,但是在你读取了第一个字符之后,在读取第二个字符时,间隔超时了,那么读操作就结束了, 这样整个操作就只读取了1个字节。 即使, 你的总时间没有超时。         另一种超时,就是 总超时 。 这里有一个公式。        总的读/写超时时间 = Read(Write)TotalTimeoutMultiplier x 要读/写的字节数 + Read(Write)TotalTimeoutConstant.         这里要说明的一点,要读/写的字节数是从哪里来的。 这个是从ReadFile 或者WriteFile 函数中定义的。        在读操作时, 若当前所花读取时间已经超过了总的超时设置, 则读操作就结束了。即使, 每两个字符之间的间隔没有超时。 举例来说, 若总共读取8个字节。 间隔设置为8ms, 总超时系数为3ms,总超时常数为3ms。 则总的超时时间为3*8+3=27ms。若每个字符读取的间隔为7ms, 则这次操作总共能读取4个字符。 就结束了。因为读取第5个字符时, 已经需要35ms, 超过总超时时间了。 下面来讨论一下这几个参数的设定: 将ReadIntervalTimeout设置为MAXDWORD,将ReadTotalTimeoutMultiplier   和ReadTotalTimeoutConstant设置为0,表示读操作将立即返回存放在输入缓冲区的字符。   将ReadIntervalTimeout设置为MAXDWORD,将ReadTotalTimeoutMultiplier   和ReadTotalTimeoutConstant设置为MAXDWORD, 表示读操作会一直等待直到所需要读取的字节数全部接收到为止。 (大家可以把MAXDWORD 认为是永远) 将ReadIntervalTimeout设置为0, 则不使用间隔超时, 只考虑总超时设置。
相关资源
  • 所需E币: 2
    时间: 2024-2-21 17:48
    大小: 105.71KB
    上传者: 小恶魔owo
    高德地图的API大全,收集以及验证代码的完整性,让地图、物联网、天气等等API的设计提供一个相对标准的代号,让API更加易读、易理解
  • 所需E币: 2
    时间: 2023-11-10 16:48
    大小: 5.55MB
    上传者: Argent
    SiliconLabs(芯科科技)EZRadioPROAPIRevC2A-A2A应用笔记
  • 所需E币: 1
    时间: 2023-11-10 11:50
    大小: 29.26KB
    上传者: Argent
    第35讲LinuxRegmapAPI实验
  • 所需E币: 1
    时间: 2023-7-11 17:29
    大小: 103.4KB
    上传者: 张红川
    socket编程常用API汇总.pdf
  • 所需E币: 0
    时间: 2023-6-29 15:55
    大小: 891B
    上传者: 蝴蝶结欧恩
    分享课程——SoapUI+WebServices/RestAPI测试讲解+实战演示适合人群:手工测试人员,想要学习WebService测试的人,想扩展他们在WebService上的脚本能力你将会学到:让你熟练使用如何用SoapUI进行接口手动和自动化测试,实战讲解SoapUI各种功能课程简介:在这门课里你将学到WebServices(SOAPWebService和RESTAPI)的手动测试及自动化测试,熟练使用Groovy脚本自动化测试WebService。这门课程设计的是从零基础入门开始学,然后以循序渐进的方式提升到高级水平,不需要在学习课程之前有任何关于SoapWebServices和RESTAPI的背景知识。课程是实例讲解,内容包括: •20个小时以上的API测试讲座(手工+自动化),用了7个实际的项目讲解•框架设计•GroovyScripting•SoapUIPro•API负载测试•SoapUI数据库测试•面试问题
  • 所需E币: 3
    时间: 2023-3-14 13:45
    大小: 89.43MB
    上传者: Argent
    UNIX网络编程卷1:套接字联网API(第3版)
  • 所需E币: 2
    时间: 2023-3-14 13:45
    大小: 161.9MB
    上传者: Argent
    Linux内核API完全参考手册(第2版).邱铁(详细书签)
  • 所需E币: 5
    时间: 2022-10-7 14:16
    大小: 327.2KB
    上传者: ZHUANG
    基于SkypeAPI的视频监控系统的设计与实现
  • 所需E币: 3
    时间: 2022-6-6 16:31
    大小: 494.57KB
    上传者: xyzzyxaaa
    116基于AmesimAPI的阀门自动建模分析平台.pdf
  • 所需E币: 0
    时间: 2022-3-15 00:56
    大小: 28.74MB
    上传者: samewell
    用API做原型设计,成就高数据保真度_李昊哲.pdf
  • 所需E币: 0
    时间: 2021-9-27 16:15
    大小: 624.26KB
    上传者: Argent
    电子产品日新月异,不管是硬件工程师还是软件工程师,基本的模电、数电、微机原理、信号处理等知识是必备的条件,从二极管到三极管,从单片机到多核MCU,3G网络到5G产品的普及,不管电子产品的集成度怎么高,其产品还是少不了电阻电容电感,每个元器件在电路中必然有其作用,有兴趣了解的网友,下载学习学习吧。
  • 所需E币: 1
    时间: 2021-9-27 16:55
    大小: 623.2KB
    上传者: Argent
    电子产品日新月异,不管是硬件工程师还是软件工程师,基本的模电、数电、微机原理、信号处理等知识是必备的条件,从二极管到三极管,从单片机到多核MCU,3G网络到5G产品的普及,不管电子产品的集成度怎么高,其产品还是少不了电阻电容电感,每个元器件在电路中必然有其作用,有兴趣了解的网友,下载学习学习吧。
  • 所需E币: 1
    时间: 2021-9-27 16:55
    大小: 2.98MB
    上传者: Argent
    电子产品日新月异,不管是硬件工程师还是软件工程师,基本的模电、数电、微机原理、信号处理等知识是必备的条件,从二极管到三极管,从单片机到多核MCU,3G网络到5G产品的普及,不管电子产品的集成度怎么高,其产品还是少不了电阻电容电感,每个元器件在电路中必然有其作用,有兴趣了解的网友,下载学习学习吧。
  • 所需E币: 0
    时间: 2021-9-15 18:48
    大小: 1.08MB
    上传者: Argent
    FPGA是一个技术密集型的行业,没有坚实的技术功底,很难形成有竞争力的产品。从技术上来看FPGA未来的发展有广阔的空间,嵌入式开发需要了解不同领域的产品工作原理,包括快速读懂数据手册,搜集了部分数据手册,第三方教育机构的指导性文档,希望对您有所帮助。
  • 所需E币: 1
    时间: 2021-3-31 18:08
    大小: 668.39KB
    上传者: Argent
    电子产品日新月异,不管是硬件工程师还是软件工程师,基本的模电、数电知识也是必备的条件,从二极管到三极管,从单片机到多核MCU,3G网络到5G产品的普及,不管电子产品的集成度怎么高,其产品还是少不了电阻电容电感,每个元器件在电路中必然有其作用,有兴趣了解的网友,下载学习学习吧。
  • 所需E币: 0
    时间: 2021-3-23 21:16
    大小: 208.96KB
    上传者: stanleylo2001
    ESP8266_字符串APIESP8266字符串APIintos_sprintf(char*buffer,constchar*format,[argument]…)把格式化的数据写入某个字符串缓冲区..
  • 所需E币: 5
    时间: 2021-3-20 20:59
    大小: 55.97MB
    上传者: samewell
    JDK-11中文API修订版JDK11(中文API手册)是一款根据官方的API文档翻译的一款帮助手册,在词句的翻译的全面性、准确性上是非常的不错,同时采用的是.chm文件的格式,在使用的时候是非常的...
  • 所需E币: 0
    时间: 2021-3-18 18:55
    大小: 208.96KB
    上传者: xiaosh728
    ESP8266_字符串API.zip
  • 所需E币: 0
    时间: 2021-3-8 19:39
    大小: 367.72KB
    上传者: czd886
    LIN总线核心接口管理层API的设计与应用
  • 所需E币: 0
    时间: 2020-12-27 23:39
    大小: 208.96KB
    上传者: stanleylo2001
    ESP8266_字符串API与技术资料