精华内容
下载资源
问答
  • 文件结束符EOF .

    2021-03-01 07:38:31
    关于文件结束符EOFEOF 是 End Of File 的缩写。在C语言中,它是在标准库中定义的一个宏。人们经常误认为EOF 是从文件中读取的一个字符(牢记)。其实,EOF 不是一个字符,它被定义为是 int 类型的一个负数(比如 -1)。...

    >> 关于文件结束符EOF

    EOF 是 End Of File 的缩写。

    在C语言中,它是在标准库中定义的一个宏。

    人们经常误认为EOF 是从文件中读取的一个字符(牢记)。其实,EOF 不是一个字符,它被定义为是 int 类型的一个负数(比如 -1)。EOF 也不是文件中实际存在的内容。EOF 也不是只表示读文件到了结尾这一状态(这种状态可以用 feof() 来检测),它还能表示 I/O 操作中的读、写错误(通常可以用 ferror() 来检测)以及其它一些关联操作的错误状态。

    一、getchar的两点总结:

    1.getchar是以行为单位进行存取的。

    当用getchar进行输入时,如果输入的第一个字符为有效字符(即输入不是文件结束符EOF,Windows下为组合键Ctrl+Z,Unix/Linux下为组合键Ctrl+D),那么只有当最后一个输入字符为换行符'/n'(也可以是文件结束符EOF,EOF将在后面讨论)时,getchar才会停止执行,整个程序将会往下执行。譬如下面程序段:

    while((c =getchar())!=EOF){

    putchar(c);

    }

    执行程序,输入:abc,然后回车。则程序就会去执行puchar(c),然后输出abc,这个地方不要忘了,系统输出的还有一个回车。然后可以继续输入,再次遇到换行符的时候,程序又会把那一行的输入的字符输出在终端上。

    对于getchar,肯定很多初学的朋友会问,getchar不是以字符为单位读取的吗?那么,既然我输入了第一个字符a,肯定满足while循环(c = getchar()) != EOF的条件阿,那么应该执行putchar(c)在终端输出一个字符a。不错,我在用getchar的时候也是一直这么想的,但是程序就偏偏不着样执行,而是必需读到一个换行符或者文件结束符EOF才进行一次输出。对这个问题的一个解释是,在大师编写C的时候,当时并没有所谓终端输入的概念,所有的输入实际上都是按照文件进行读取的,文件中一般都是以行为单位的。因此,只有遇到换行符,那么程序会认为输入结束,然后采取执行程序的其他部分。同时,输入是按照文件的方式存取的,那么要结束一个文件的输入就需用到EOF(Enf Of File). 这也就是为什么getchar结束输入退出时要用EOF的原因。

    2.getchar()的返回值一般情况下是字符,但也可能是负值,即返回EOF。

    这里要强调的一点就是,getchar函数通常返回终端所输入的字符,这些字符系统中对应的ASCII值都是非负的。因此,很多时候,我们会写这样的两行代码:

    char c;

    c =getchar();

    这样就很有可能出现问题。因为getchar函数除了返回终端输入的字符外,在遇到Ctrl+D(Linux下)即文件结束符EOF时,getchar()的返回EOF,这个EOF在函数库里一般定义为-1。因此,在这种情况下,getchar函数返回一个负值,把一个负值赋给一个char型的变量是不正确的。为了能够让所定义的变量能够包含getchar函数返回的所有可能的值,正确的定义方法如下(K&R C中特别提到了这个问题):

    int c;

    c =getchar();

    二、EOF的两点总结(主要指普通终端中的EOF)

    1.EOF作为文件结束符时的情况:

    EOF虽然是文件结束符,但并不是在任何情况下输入Ctrl+D(Windows下Ctrl+Z)都能够实现文件结束的功能,只有在下列的条件下,才作为文件结束符。

    (1)遇到getcahr函数执行时,要输入第一个字符时就直接输入Ctrl+D,就可以跳出getchar(),去执行程序的其他部分;

    (2)在前面输入的字符为换行符时,接着输入Ctrl+D;

    (3)在前面有字符输入且不为换行符时,要连着输入两次Ctrl+D,这时第二次输入的Ctrl+D起到文件结束符的功能,至于第一次的Ctrl+D的作用将在下面介绍。

    其实,这三种情况都可以总结为只有在getchar()提示新的一次输入时,直接输入Ctrl+D才相当于文件结束符。

    2.EOF作为行结束符时的情况,这时候输入Ctrl+D并不能结束getchar(),而只能引发getchar()提示下一轮的输入。

    这种情况主要是在进行getchar()新的一行输入时,当输入了若干字符(不能包含换行符)之后,直接输入Ctrl+D,此时的Ctrl+D并不是文件结束符,而只是相当于换行符的功能,即结束当前的输入。以上面的代码段为例,如果执行时输入abc,然后Ctrl+D,程序输出结果为:abcabc

    注意:第一组abc为从终端输入的,然后输入Ctrl+D,就输出第二组abc,同时光标停在第二组字符的c后面,然后可以进行新一次的输入。这时如果再次输入Ctrl+D,则起到了文件结束符的作用,结束getchar()。

    如果输入abc之后,然后回车,输入换行符的话,则终端显示为:abc         //第一行,带回车

    abc         //第二行

    //第三行

    其中第一行为终端输入,第二行为终端输出,光标停在了第三行处,等待新一次的终端输入。

    从这里也可以看出Ctrl+D和换行符分别作为行结束符时,输出的不同结果。

    EOF的作用也可以总结为:当终端有字符输入时,Ctrl+D产生的EOF相当于结束本行的输入,将引起getchar()新一轮的输入;当终端没有字符输入或者可以说当getchar()读取新的一次输入时,输入Ctrl+D,此时产生的EOF相当于文件结束符,程序将结束getchar()的执行。

    【补充】本文第二部分中关于EOF的总结部分,适用于终端驱动处于一次一行的模式下。也就是虽然getchar()和putchar()确实是按照每次一个字符进行的。但是终端驱动处于一次一行的模式,它的输入只有到“/n”或者EOF时才结束,因此,终端上得到的输出也都是按行的。

    如果要实现终端在读一个字符就结束输入的话,下面的程序是一种实现的方法(参考《C专家编程》,略有改动)

    #include

    #include

    int

    main(void)

    {

    int c;

    /* 终端驱动处于普通的一次一行模式 */

    system("stty raw");/* 现在的终端驱动处于一次一个字符模式 */

    c =getchar();putchar();

    /*终端驱动处又回到一次一行模式*/     system("stty cooked");

    return 0;

    }

    编译运行该程序,则当如入一个字符时,直接出处一个字符,然后程序结束。

    由此可见,由于终端驱动的模式不同,造成了getchar()输入结束的条件不一样。普通模式下需要回车或者EOF,而在一次一个字符的模式下,则输入一个字符之后就结束了。

    (1) 字节的读取

    在正常的情况下, getc 以 unsigned char 的方式读取文件流, 扩张为一个整数,并返

    回. 换言之, getc 从文件流中取一个字节, 并加上24个零,成为一个小于256的整数,

    然后返回.

    int c;

    while ((c = fgetc (rfp))!= -1) // -1就是 EOF

    fputc (c, wfp);

    上面 fputc 中的 c 虽然是整数, 但在 fputc 将其写入文件流之前, 又把整数的高24位

    去掉了, 因此 fgetc, putc 配合能够实现文件复制. 到目前为止, 把 c 定义为

    char仍然是可行的, 但下面我们将看到,把 c 定义为 int 是为正确判段文件是否结束.

    (2) 判断文件结束.

    多数人认为文件中有一个EOF,用于表示文件的结尾. 但这个观点实际上是错误的,在文

    件所包含的数据中,并没有什么文件结束符. 对getc 而言, 如果不能从文件中读取,

    则返回一个整数 -1,这就是所谓的EOF. 返回 EOF 无非是出现了两种情况,一是文件已

    经读完; 二是文件读取出错,反正是读不下去了.

    请注意: 在正常读取的情况下, 返回的整数均小于256, 即0x0~0xFF. 而读不出返回的

    是 0xFFFFFFFF. 但, 假如你用fputc把 0xFFFFFFFF 往文件里头写, 高24位被屏蔽,写入的将

    是 0xFF. // lixforalpha 请注意这一点

    (3) 0xFF 会使我们混淆吗?

    不会, 前提是, 接收返回值的 c 要按原型定义为 int.

    如果下一个读取的字符将为 0xFF, 则

    int c;

    c = fgetc (rfp); // c = 0x000000FF;

    if (c != -1)    // 当然不等, -1 是 0xFFFFFFFF

    fputc (wfp);   // 噢, OXFF 复制成功.

    字符0xFF, 其本身并不是EOF.

    (4) 将 c 定义 char

    假定下一个读取的字符为 0xFF 则

    char c;

    c = fgetc (rfp); // fgetc(rfp)的值为 0x000000FF, 暗中降为字节, c = 0xFF

    if (c != -1)    // 字符与整数比较? c 被带符号(signed)扩展为0xFFFFFFFF, 喔噢,

    条件成立,文件复制提前退出.

    while ((c=fgetc(rfp))!=EOF) 中的判别条件成立, 文件复制结束! 意外中止.

    (5) 将 c 定义为 unsigned char;

    当读到文件末尾, 返回 EOF 也就是 -1 时,

    unsigned char c;

    c = fgetc (rfp); // fgetc (rfp)的值为EOF,即-1,即0xFFFFFFFF, 降格为字节, c=0xFF

    if ( c!= -1)  // c 被扩展为 0x000000FF, 永远不回等于 0xFFFFFFFF

    所以这次虽然能正确复制 0xFF, 但却不能判断文件结束. 事实上,在 c 为 uchar 时,

    c != -1 是永远成立的, 一个高质量的编译器, 比如 gcc会在编译时指出这一点.

    (6) 为何需要feof?

    FILE *fp;

    fp 指向一个很复杂的数据结构, feof 是通过这个结构中的标志来判断文件是否结束的.

    如果文件用 fgetc 读取, 刚好把最后一个字符读出时, fp 中的EOF标志不会打开,这时

    用feof判断,将会得到文件尚未结束的结论.

    fgetc 返回 -1 时, 我们仍无法确信文件已经结束, 因为可能是读取错误! 这时我们

    需要 feof 和 ferror.

    总结:EOF并不是存在于文件中的,而是一种状态,当读到文件末尾或者读取出错时就会返回这个值来判断文件结束。(即即使读取错误可能也被认为文件结束,所以就需要用feof 和 ferror来判断是不是真的文件结束了)

    当用getchar(c)时,即使c定义成字符型,也可以结束,主要是c与-1比较时,c也会从char转换为整型值。

    写个小程序验证了一下

    #include 

    intmain()

    {

    charc;

    c = -1;

    printf("%x",c);

    return0;

    }#include

    int main()

    {

    char c;

    c = -1;

    printf("%x",c);

    return 0;

    }

    得到的结果为ffffffff,所以c即使定义为char型,读取文件等时还是能正常结束。

    展开全文
  • 本人小白,不懂一些协议格式,比如,头0x15,功能号0x01,结束符0x0A,这些根据什么依据而来,如果我要修改格式,应该根据哪块部分来修改求各位大神赐教,尽量说的通俗明白一点,
  • (7) 帧结束 表示数据帧结束的段。 理解数据帧的含义,请从认真理解它的定义:用于发送单元向接收单元传送数据的帧。 一般的CAN总线通信,总线上通信绝大部分时候都是数据帧。像在CANOpen协议中,用的最多的PDO过程...

    578c542c85f04af19cc31d8b679f35e9.png

    说明:

    本文原创作者『strongerHuang

    首发于微信公众号『嵌入式专栏』,同时也更新在我的个人网站:EmbeddedDevelop

    标签:CAN、 CANOpen、 CanFestival

    一、写在前面

    上一篇文章讲述了CAN收发器的重要作用,也提及了一下CAN总线的优势主要在于CAN控制器。CAN控制器在CAN网络中所处的位置如下图:

    9bdc86d31f5a6e0f9f415c2b032d31ae.png

    本文讲述的CAN控制器实现的几个重要功能:CAN总线波特率、位时序、帧类型

    二、CAN总线波特率

    CAN总线属于异步通信,因此就有通信波特率,而这个波特率发生器就位于CAN控制器内部。我们不需要了解它是如何产生的,但需要了解它的含义。这章节针对初学者讲述以下两点内容。

    2.1 异步通信

    在串行通信中,主要分异步通信和同步通信

    同步通信:通信设备之间通过同步信号(CLK时钟)来实现数据传输的通信叫同步通信。如I2C、SPI这类通信中都具有一个时钟信号,其实在STM32中USART也具有同步功能,只是我们大多数人都只用了它的异步功能。

    异步通信:简单来说,就是通信设备之间通过约定一样的时间来收发数据。而这个时间就会决定本节说的波特率。

    2.2 波特率

    很多工程师一直都没彻底搞明白什么是波特率,我这里还是结合UART波特率来简述一下其含义。

    在电子通信领域,波特(Baud)即调制速率,指的是有效数据信号调制载波的速率,即单位时间内载波调制状态变化的次数。它是对符号传输速率的一种度量,1波特即指每秒传输1个符号

    UART每秒钟传送240个字符,而每个字符格式包含10位(1个起始位,1个停止位,8个数据位),这时的波特率为240Bd,比特率为10位*240个/秒=2400bps

    从上面的描述可以总结:

    比特率:即单位时间内传送的二进制位数;

    波特率:即单位时间内传输的符号个数;

    只有在每个符号只代表一个比特信息的情况下,波特率与比特率才在数值上相等,但是它们的意义并不相同。

    三、位时序

    上一章节讲述了波特率,而决定波特率大小的就是本节说的位时序。在CAN标准中一个位可分为4段:

    ·同步段(SS)

    ·传播时间段(PTS)

    ·相位缓冲段1(PBS1)

    ·相位缓冲段2(PBS2)

    这些段又由可称为 Time Quantum(简称Tq)的最小时间单位构成。

    1位分为4个段,每个段又由若干个Tq构成,这称为位时序。

    而在STM32参考手册中,将位时序分为三段,但它将它传播段和位段1合并在一起了,如下图:

    377d7a138fc7920c29d535ecd9b3c5dc.png

    1位由多少个Tq构成、每个段又由多少个Tq构成等,可任意设定位时序。通过设定位时序,决定传输的波特率

    797a2cc3a15ca9518e0584eb6523cafb.png

    这几个参数会在以后编程中进行配置,从而决定通信的波特率。

    关于同步,还有硬件同步、再同步等操作。但初学者可以不必过多理解,掌握上面基础内容就行了。更多关于位时序的内容可以参看 ISO 11898 标准。

    四、帧类型及格式说明

    CAN总线是通过以下5种类型的帧进行通信:

    数据帧:用于发送单元向接收单元传送数据的帧。

    遥控帧:用于接收单元向具有相同 ID 的发送单元请求数据的帧。

    错误帧:用于当检测出错误时向其它单元通知错误的帧。

    过载帧:用于接收单元通知其尚未做好接收准备的帧。

    帧间隔:用于将数据帧及遥控帧与前面的帧分离开来的帧。

    数据帧和遥控帧有标准格式和扩展格式两种格式。标准格式有11个位的标识符ID,扩展格式有29个位的ID。

    4.1 数据帧

    5aa71b35684c09f26764cfac9c809af1.png

    如上图,数据帧由7个段构成:

    (1) 帧起始

    表示数据帧开始的段。

    (2) 仲裁段

    表示该帧优先级的段。

    (3) 控制段

    表示数据的字节数及保留位的段。

    (4) 数据段

    数据的内容,可发送 0~8 个字节的数据。

    (5) CRC 段

    检查帧的传输错误的段。

    (6) ACK 段

    表示确认正常接收的段。

    (7) 帧结束

    表示数据帧结束的段。

    理解数据帧的含义,请从认真理解它的定义:用于发送单元向接收单元传送数据的帧。

    一般的CAN总线通信,总线上通信绝大部分时候都是数据帧。像在CANOpen协议中,用的最多的PDO过程数据对象就是通过数据帧进行的通信。

    初学者可以先理解数据帧,然后其他就容易理解了。下面再来讲述一下数据帧7段的详情

    4.1.1 帧起始

    标准和扩展格式相同。表示帧开始的段,1个位的显性位(如下图):

    b69ce77917d0676dc046ee0022674a5d.png

    关于显性和隐性电平,请参看我上一篇文章差分信号章节。

    总线上的电平有显性电平和隐性电平两种。 总线上执行逻辑上的线“与”时,显性电平的逻辑值为“0”,隐性电平为“1”。

    “显性”具有“优先”的意味,只要有一个单元输出显性电平,总线上即为显性电平。并且,“隐性”具有“包容”的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平。(显性电平比隐性电平更强)

    4.1.2 仲裁段

    标准格式和扩展格式在此的构成有所不同。仲裁段表示该帧优先级的段,扩展格式多了18位ID(如下图):

    5946651c10126864a66db115b4f06a27.png

    RTR = 0代表数据帧,RTR = 1代表远程帧。

    为什么叫仲裁段,就是通过ID来判断总线上哪一个节点具有优先发送的权利。ID越小(0代表显性),优先级越高。

    4.1.3 控制段

    标准和扩展格式的构成有所不同。控制段由 6 个位构成(如下图):

    ed54c3a209b077af39c566c7aadaac6c.png

    它们除了都有4位表示数据段长度代码(DLC)外,标准帧有IDE(数值为0)位和r0保留位,扩展帧有r0和r1保留位。

    保留位必须全部以显性电平发送。但接收方可以接收显性、隐性及其任意组合的电平。

    4.1.4 数据段

    标准和扩展格式相同。数据段表示传输数据的内容,从 MSB(最高位)开始输出,可发送 0~8 个字节的数据,长度由前面控制段决定。

    4.1.5 CRC段

    标准和扩展格式相同。CRC段是检查帧传输错误的帧,由 15 个位的 CRC 顺序和 1 个位的 CRC 界定符(用于分隔的位)构成。

    3150163a8f779c0b3b4ac43889e8e767.png

    相比485这类通信,CAN控制器就已经把CRC校验做了,不需要你的程序再次去计算,从而节约了处理器资源。

    4.1.6 ACK段

    标准和扩展格式相同。ACK段用来确认是否正常接收。由 ACK 槽(ACK Slot)和 ACK 界定符 2 个位构成。

    b5171fc0ad1d0b7b84851a1b48e8541d.png

    A.发送单元在 ACK 段发送 2 个位的隐性位。 B.接收到正确消息的单元在 ACK 槽(ACK Slot)发送显性位, 通知发送单元正常接收结束。这称作“发送 ACK”或者“返回 ACK”。

    4.1.7 帧结束

    标准和扩展格式相同。帧结束是表示该该帧的结束的段。由 7 个位的隐性位构成。

    f6e2a6ff094e47fdda8769eb680dfaa2.png

    4.2 遥控帧

    7e33de8b8d2be6a0188190a10e338b66.png

    和数据帧相比,遥控帧是接收单元向发送单元请求发送数据所用的帧。所以,遥控帧没有数据段。因此,遥控帧由如下 6 个段组成:

    (1) 帧起始(SOF)

    表示帧开始的段。

    (2) 仲裁段

    表示该帧优先级的段。可请求具有相同 ID 的数据帧。

    (3) 控制段

    表示数据的字节数及保留位的段。

    (4) CRC 段

    检查帧的传输错误的段。

    (5) ACK 段

    表示确认正常接收的段。

    (6) 帧结束

    表示遥控帧结束的段。

    这6个段和上面数据帧的内容基本一样,这里就不一一讲述了。讲一下遥控帧和数据帧的区别:

    遥控帧的 RTR 位为隐性位,没有数据段。

    没有数据段的数据帧和遥控帧可通过 RTR 位区别开来。

    问题一:遥控帧没有数据段,数据长度码该如何表示? 遥控帧的数据长度码以所请求数据帧的数据长度码表示。

    问题二:没有数据段的数据帧有何用途? 例如,可用于各单元的定期连接确认/应答、或仲裁段本身带有实质性信息的情况下。

    4.3 错误帧

    3b13b9c14481b096c90071576549b366.png

    用于在接收和发送消息时检测出错误通知错误的帧。错误帧由错误标志和错误界定符构成。

    (1) 错误标志 错误标志包括主动错误标志和被动错误标志两种。 主动错误标志: 6 个位的显性位。 被动错误标志: 6 个位的隐性位。

    (2) 错误界定符 错误界定符由 8 个位的隐性位构成。

    4.4 过载帧

    679e430b12e29c54fb546479348f8bf2.png

    过载帧是用于接收单元通知其尚未完成接收准备的帧。过载帧由过载标志和过载界定符构成。 (1) 过载标志 6 个位的显性位。 过载标志的构成与主动错误标志的构成相同。

    (2) 过载界定符 8 个位的隐性位。 过载界定符的构成与错误界定符的构成相同。

    4.5 帧间隔

    0088a211e0806e0399f6cbe3aa37f548.png

    帧间隔是用于分隔数据帧和遥控帧的帧。数据帧和遥控帧可通过插入帧间隔将本帧与前面的任何帧(数据帧、遥控帧、错误帧、过载帧)分开。

    过载帧和错误帧前不能插入帧间隔。

    (1) 间隔

    3 个位的隐性位。

    (2) 总线空闲

    隐性电平,无长度限制(0 亦可)。 本状态下,可视为总线空闲,要发送的单元可开始访问总线。

    (3) 延迟传送(发送暂时停止)

    8 个位的隐性位。 只在处于被动错误状态的单元刚发送一个消息后的帧间隔中包含的段。

    五、说明

    1.该文档仅供个人学习使用,版权所有,禁止商用。

    2.本文由我一个人编辑并整理,难免存在一些错误。

    3.为了方便大家平时公交、地铁、外出办事也能用手机随时随地查看该教程,该教程同步更新于微信公众号『嵌入式专栏』,关注微信公众号回复【CANOpen系列教程】即可查看全系列教程。

    六、最后

    我的博客:http://www.strongerhuang.com

    我的GitHub:https://github.com/EmbeddedDevelop

    我的微信公众号(ID:strongerHuang)还在分享STM8、STM32、Keil、IAR、FreeRTOS、UCOS、RT-Thread、CANOpen、Modbus...等更多精彩内容,如果想查看更多内容,可以关注我的微信公众号『strongerHuang』。

    展开全文
  • 从上面的分析和测试可以看出,基于有限状态机的串口通信同步方法是本文中提出的3种方法中最优的,结 构清晰且系统资源利用率高。 对一个有着完整通信协议的串口中断来说,因为要比较命令头、完成校验、解析...

    下面给出该方法在Keil C5l中的示例程序:
    #include “regx52.h”

    #define HEAD1 0x00

    #define HEAD2 0x01

    #define LEN 0x02

    #define TYPE 0x03

    #define DATA 0x04

    #define CHECK 0x05

    unsigned char g_DatRev[BUFLEN];   //接收缓冲区

    unsigned char g_cmd;

    unsigned char g_RecOk;

    void main()

    {

         while(1)

    {

             if(g_RecOk)

    {

                  g_RecOk=FALSE;

                  switch(g_cmd)

    {   //相应处理程序

                  case: ...

                       break;

    case: ...

                       break;

                  ...

                  default:

                  }

             }

         }

    }

     

    void SerialComm() interrupt 4

    {

         static unsigned char RecState=HEAD1;      //接收状态

         static unsigned char len=0;               //已接收的数据长度

         static unsigned char CheckSum=0;          //校验和

         static unsigned char Len_total=0;         //包长

         if(RI)

    {

             RI=0;

             swich(RecState)

    {

             case HEAD1:

                  if(SBUF==0xAA)

    {

                       RecState=HEAD2;

                  }

                  break;

             case HEAD2:

                  if(SBUF==0x55)

    {

                       RecState=LEN;

                  }

                  else if(SBUF==0xAA)

    {

                       RecState=HEAD2;

                  }

                  break;

             case LEN:

                  RecState=TYPE;

                  Len_total=SBUF;

                  CheckSum=0xAA^0x55;

                  break;

             case TYPE:

                  RecState=DATA;

                  g_cmd=SBUF;

                  CheckSum=CheckSum^SBUF;

                  len=0;

                  break;

             case DATA:

                  g_DatRev[len]=SBUF;

                  CheckSum=CheckSum^SBUF;

                  len++;

                  if(len>=Len_total)

    {

                       RecState=CHECK;

                  }

                  break;

             case CHECK:

                  if(CheckSum==SBUF)

    {

                       g_RecOk=TRUE;

                  }

                  RecState=HEAD1;

                  break;

             default:

                  RecState=HEAD1;

                  break;

             }

         }

    }

    由于采用了状态机和消息机制的结构,上述设计思路快速有效地实现了串口通信的同步,而且程序结构清晰,便
    于维护,也易于向其他的串口通信协议移植。另外,串口中断服务子程序中需要处理的工作很少,每个串口接收
    中断平均耗时不超过20个机器周期(在单片机AT89C5l中),大大减轻了串口接收中断服务程序的压力,缓解了嵌
    入式系统有限资源与需求之间的矛盾,提高了嵌入式系统的稳定性。

     

    三、结论

    从上面的分析和测试可以看出,基于有限状态机的串口通信帧同步方法是本文中提出的3种帧方法中最优的,结
    构清晰且系统资源利用率高。

    对一个有着完整通信协议的串口中断来说,因为要比较命令头、完成校验、解析数据等需要耗费大量的机器周期
    ,所以嵌入式系统中的串口中断服务程序设计显得更为重要。在实际的串口通信程序中,可采用状态机和消息机
    制相结合的方法,仅在中断服务程序中设置一个标志,而在主程序中根据相应标志来作处理,这样就回避了某些
    中断可能需要较长处理时间的问题。在程序结构上,由于采用状态机的结构,既提高了可读性。同时又提高了运
    行速度,因而该方法不仅是一种很好的帧同步方法,还是一种很不错的串口通信程序设计方法。

    展开全文
  • ModbusRTU模式和结束符(转)

    千次阅读 2019-09-12 10:03:47
    Modbus RTU模式的协议字段 起始位 设备地址 功能码 ... 结束符 至少3.5个字符 8bit 8bit N*8bit 16bit ...

    Modbus RTU模式的协议字段

    起始位

    设备地址

    功能码

    数据

    CRC校验

    结束符

    至少3.5个字符

    8bit

    8bit

    N*8bit

    16bit

    至少3.5个字符

     

    Modbus协议RTU模式要求每一帧的起始和结束都以至少3.5个字符为间隔。

    每个字符间隔是字符位数/波特率,以1位起始位,8位数据,1位停止位,无奇偶校验位的10位数据。

    以波特率为9600b/s为例,字符间隔为1.14ms,也就是每一帧的开始和结束都伴随着至少3.5*1.14=4.01ms的时间间隔。

    在字节流中以1.5个字符时间作为帧间间隔,以上面的通信速率,则1.5*1.14=1.71ms,即字符流中出现1.71ms的间隔时可能意味着一帧数据结束。

    但必须同时满足其后的一段时间内(2个字符)不会再接收到字符,否则认为结束的该帧为错误帧。

    由于收到的每个字节都有可能成为一帧数据的最后一个字节,因此,每接收一个字节,关闭上一个已经开启的3.5个字符时间和1.5个字符时间的定时器,处理完接收到得数据后再次启动3.5个字符时间和1.5个字符时间的定时器,以检测该帧数据的结束

    这也就是上面所说的在帧间间隔后的一段时间内(2个字符)不能接收到数据,否则该帧为错误帧。1.5个字符时间和3.5个字符时间的定时起点是一致的,这是Modbus协议RTU模式的关键之处

    当然这也增加了系统的中断负荷。在发生1.5个字符时间中断后,处理其接收到得数据(这里未考虑设备地址、超时、奇偶校验等错误),计算接收到的字符数-2个字节的CRC校验和,将计算结果与接收到得最后两个字节(当做发送的CRC校验)进行比较,从而得知这是否是完整的一帧数据。CRC校验正确,说明这是一帧完整的数据,CRC校验错误,说明这是一帧错误的数据帧,数据帧不完整。

    发生1.5个字符时间中断后,如未发生3.5个字符时间中断,再次接收到字符,同样说明接收到得是一帧不完整的数据帧;如随后发生3.5个字符时间中断,则处理刚接到的完整数据帧,给予对应的应答。这里的3.5个字符时间同时也可作为下一帧数据的起始

    展开全文
  • 485通讯数据帧结束判断标志位如何判断: 在485通讯中,如何去判断一帧数据接收结束呢? 首先要知道的是,在每帧数据中,每个字节之间的数据发送间隔时间一定会小于每帧数据的之间的发送间隔时间。也就是说对于接收...
  • 关于一个开始和结束的判断

    万次阅读 2011-08-22 09:21:07
    串行通信怎么判断一数据发送完毕?设置一个时间间隔?过了这个时间间隔还没有数据来就可以判断一数据发送完成? 弄个结束字符也不保险啊!万一那个结束字符铥了怎么办?或者接收接收字符出错了怎么办? 判断...
  • 以太网

    万次阅读 2018-05-20 20:46:59
    格式  以太网(Ethernet frame)是符合以太网标准的链路层协议数据单元(PDU),其格式有Ethernet V1、Ethernet V2、RAW 802.3、IEEE 802.3/802.2 LLC和IEEE 802.3/802.2SNAP。现在大多数网络应用都使用...
  • 一、 封装数据、 二、 "数据" 附加信息、 三、 "数据" 同步、 四、 "数据" 长度、 五、 "数据" 组装方法、 六、 透明传输、 七、 字符计数法、 八、 字符填充法 ( 加转义字符 )、 九、 零比特填充法 ( 5...
  • 以太网的MAC(一)

    千次阅读 热门讨论 2020-08-02 18:53:10
    以太网MAC帧格式有两种标准...注意: MAC帧并不需要帧结束符, 因为以太网在传送帧时,各帧之间必须有一定的间隙。因此,接收端只要找到帧开始定界符,其后面连续到达的比特流就都属于同一个MAC帧,所以上图只有帧开始定
  • 最近在研究CAN总线的驱动,需要详细了解数据/标准/扩展/远程/错误这几种的详细组成格式,于是收集了一下,统一放在这里进行对比和记录,以便日后需要时查阅
  • modbus字符串的结束符介绍

    千次阅读 2019-09-12 10:01:26
    当接收到结束符时,以后再接收的字符就算是下一轮的东西了,从起始符到结束符之间的字符就是它要分析的字符! MODBUS的ASCII方式结束符是--- Chr$(13) + Chr$(10) 现在的组合是“:02030A000004FB“+ Chr$...
  • 0 前言 既然你 1 PPP的定义 1.1 点对点协议PPP (Point to Point Protocol,PPP) ...PPP的格式如下图所示,PPP的首部和尾部分别为四个字段和两个字段 . 首部的第一个字段和尾部的第二个字段都是标志字段
  • CAN解析

    千次阅读 2019-10-19 10:02:47
    版本 ...整理CAN解析 0.3 2018.06.24 整理CAN数据类型格式 0.4 2018.07.07 完善CAN解析 0.5 2018.07.22 补充CAN类型说明 0.6 2018.08.05 整理CAN仲裁 0.7 2018.09.10 整理CAN处...
  • CAN总线学习笔记--数据与遥控

    千次阅读 2020-05-15 21:26:40
    CAN总线学习笔记–数据与遥控 ​ 最近在学习can总线协议,想写一些关于接触can总线的想法,文章会参考部分正点原子的资料,但是会使用自己在notability里面做笔记时画的图来代替can手册中的图片。(文中的红色...
  • 对H.264类型判断方法

    千次阅读 2017-04-17 16:37:30
    背景描述我们经常在网络直播推流或者客户端拉流的时候,需要对获取到的H.264视频进行判断后处理,我们经常获取到各种不同的视频数据0x67 0x68 0x65 0x61,0x27 0x28 0x25 0x21,0x47 0x48 0x45 0x41,各种不同的...
  • SDH原理--2.SDH信号的结构

    千次阅读 2021-05-17 09:04:01
    SDH信号的结构和复用步骤 目标: 1.1 SDH信号——STM-N的结构 诀窍: 想一想: (1)信息净负荷(payload) 技术细节: (2)段开销(SOH) 技术细节: (3)管理单元指针(AU-PTR) 1.2 SDH的复用...
  • 开始/结束标志(F,1字节):PPP采用7EH作为一的开始和结束标志,固定值(0x7E); 地址域(A,1字节):固定值(0xFF); 控制域(C,1字节):固定值(0x03); 协议域(2字节):IP分组(0x0021),网络控制数据...
  • usb2.0 和微

    千次阅读 2020-04-27 22:46:23
    usb2.0 和微属于物理层时间基准的概念,每个长为1ms,usb高速模式,每个又分为8个微,即每个微长度为125us。 usb主机和设备控制器同步后,每个微起始点开始传输数据,在一个微时间里,usb host轮训...
  • CAN的报文格式 在总线中传送的报文,每由7部分组成。CAN协议支持两种报文格式,其唯一的...RTR位标明是数据还是请求,在请求中没有数据字节。 控制场包括标识符扩展位(IDE),指出是标准格式还是扩展格...
  • CAN总线学习笔记(2)- CAN协议数据与遥控

    万次阅读 多人点赞 2018-03-31 15:34:11
    依照瑞萨公司的《CAN入门书》的组织思路来学习CAN通信的相关知识,并结合网上相关资料以及学习过程中的领悟整理成笔记。好记性不如烂笔头,加油! 1 CAN 协议中的 ...2 数据与遥控 在CAN协议中...
  • 2. 封装成2.1 总结2.2 课后练习3. 差错检测3.1 总结3.2 课后练习 2. 封装成   封装成是指数据链路层给上层交付的协议数据单元添加头和尾,使之成为。    ⋄\diamond⋄ 在头和尾中包含有重要的...
  • 封装成

    2021-04-24 18:11:24
    封装成帧 封装成帧是指数据链路层给上层交付的协议数据单元添加帧头和帧尾使之成为帧 帧头和帧尾中包含有很多重要信息 ...以太网帧间间隔的的时间是96比特的发送时间,所以MAC帧不需要帧结束定界
  • 3.2.2 PPP协议的格式

    2021-04-02 21:44:31
    第一个和最后一个字段都是标志字段 F,规定为 0x7e,表示一个的开始和结束 标志字段就是 PPP 的定界 若连续出现两个标志字段,就表示这是一空,直接丢弃处理 地址字段 A 规定为 0xff 无实际意义,通过协商...
  • 数据链路层 PPP 协议的格式

    千次阅读 2021-10-29 08:18:31
    PPP 协议的格式 PPP 的首部和尾部分别为 4 个字段和 2 个字段。 标志字段 F = 0x7E (符号“0x”表示后面的字符是用十六进制表示。十六进制的 7E 的二进制表示是 ...F代表开始和结束,分别占用一个字节,这..
  • unity 实现同步

    万次阅读 多人点赞 2019-02-09 17:14:18
    此框架为有同步需求的游戏做一个简单的示例,实现了一个精简的框架,本文着重讲解同步游戏开发过程中需要注意的各种要点,伴随框架自带了一个小的塔防sample作为演示. 目录: 哪些游戏需要使用同步 如何实现一个...
  • 0D 0A这是自行定义的一种数据帧结束标志,不定义这个不没法判断你这一帧数据什么时候结束了,  0D 0A是什么东西咧,它就是我们的回车键的ASCII码, 0D回车,0A换行  像在windows超级终端里一条数据输入完...
  • 同步 状态同步

    千次阅读 2019-01-12 22:28:10
    什么是帧率,可能没有做过client同学并不是很清楚这个术语,我们从一个小李子来讲解一下。我记得小时候有一种小人书,快速翻看就可以看到漫画上的人物会动起来。如下面这种: 超过1M上传不删了,我也无奈 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 34,557
精华内容 13,822
关键字:

帧结束符是什么