发新帖本帖赏金 100.00元(功能说明)我要提问
12下一页
返回列表
打印
[MM32生态]

MM32F3270通讯板之通过RS232接口实现Kermit协议传输

[复制链接]
1881|30
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
#申请原创#   @21小跑堂




Kermit协议是由哥伦比亚大学开发的,它是一个面向数据包的协议,在各种结构不兼容计算机之间实现了相互通讯的功能。

Kermit协议采用的是发送等待应答(ARQ)的通讯方式,即发送方发送一个信息包后,等待接收方的回复;接收方可以通过回复ACK应答请求下一个数据包的传输,也可以通过回复NAK应答请求重新发送刚刚的数据包。

接收和发送双方按照ARQ规则进行数据传输,一直到整个文件传送完成为止;然后发送方发送一个特别的文件结束数据包;若还有其它文件数据需要传输,则会接着传输下一个文件的文件头数据包,当所有的文件都传输完成之后,发送方就会发送一个传输结束的数据包表示本次的传输结束。

Kermit协议中的数据包规定由6个字段组成,分别如下表所示:
MARK
LEN
SEQ
TYPE
DATA
CHECK
对于数据字段的长度没有固定,数据字段的内容随着数据包类型不同而变化;只有在DATA数据包中的数据字段,才包含被传输文件的数据内容。所有的数据包内容都是由ASCII码[0, 127]字符组成的,当然也存在一些特殊使用情况,后面会提到;但是都遵循一个原则,就是在数据包中除MARK字段外,其它所有的字段内容都只能由可见(可打印)的ASCII码[0x20, 0x7E]字符组成。


Kermit数据包中的字段定义
MARK:数据包开始标志,一般为CTRT-A(SOH,即0x01)
LEN:数据包长度,指示该字段之后的字节数,上限值为96
SEQ:数据包序号,以64为模循环使用,用来检测丢失或重复的数据包
TYPE:数据包类型,用单个可打印的ASCII字符来表示:
D:DATA数据
Y:ACK应答
N:NAK应答
S:开始传输/初始化传输
B:中断传输/传输结束(EOT)
F:文件头
Z:文件结束(EOF)
E:错误
T:保留
X:在屏幕上显示文本
A:文件属性
DATA:需要发送的数据内容
CHECK:数据包校验值,计算不包括MARK字段。默认的校验值是一个单字节的算术校验和,但它也可以选择两字节算术校验和、或者是三字节16位的CRC校验。如果X是数据包的校验和,那么则有CHECK = char((X + ((X AND 0xC0) / 0x40)) AND 0x3F)。这里所谓的文件数据包算术检验和,是对数据字段的内容,以及LEN字段和SEQ字段累加计算后对256取余数得到的数值。


控制字段中的控制字符
当一个字符的取值在[0x00, 0x20]之间或为0x7F时,便会认为这是一个控制字符。在传送之前需要用char(X) = X + 0x20这种方式将对于控制字符转换成可打印的字符;再等到字符接收到之后,再通过unchar(X) = X - 0x20这种方式把控制字符转换回来即可。需要使用到这种编解码处理方式的字段有LEN、SEQ和CHECK这3个字段。我们可以看出,如果把char函数的形参X赋值一个比0x5F大的数值,就会得到一个比0x7F大的数值,而大于0x7F数值的ASCII码字符是非可见字符,这不符合Kermit协议要求的可见ASCII码字符这个要求;而0x5F在char运算之后变成了0x7F,0x7F本身代表的就是DEL这个控制字符;所以X的实际上限值就被限定到0x5E,所以得到了传输数据字段的长度上限就是94个字节。


数据字段中的控制字符
Kermit协议对在数据字段中的控制字符采用的是所谓的前缀编码,就是在控制字符前面加上一个可打印的字符#,再将控制字符同0x40进行异或运算。比如对13的编码就是#53。


在Kermit数据中数据字节的最高位编码
许多系统上,串行通讯的数据格式在本系统内是固定不变的。在这种情况下,程序常常没有办法来控制数据格式。如果碰巧是一个7位带奇偶校验位的系统,那么要传送8位二进制文件显然必须作某种形式的编码。这里采用了类似于上述前缀编码的方法:如果一个字符的最高位为1,就在它的前面插入一个可打印字符&,并且把这个字节同0x7F相与,使它变成一个可打印的字符。


启动传输
启动传输的方法是当发送方收到接收方的NAK应答后,开始发送第一个数据包(S类型数据);在发送方发送出第一个数据包之前,接收方会间隔固定时间不断的发送NAK数据包。第一个数据包就是下面提到的起始数据包,它包含着发送方自身对某些重要传输参数的设定。接收方收到起始数据包之后会把自己的设定方案再包含在ACK数据包中作为对起始数据包的应答传输给发送方。


S类型数据包
MAXL
TIME
NPAD
PADC
EOL
QCTL
QBIN
CHKT
REPT
CAPAS
MAXL:接收数据包的最大长度,最大值为94
TIME:等待超时时间,单位为秒
NPAD:填充字符
PADC:填充字符<NULL>或<DEL>
EOL:数据包结束字符<CR>
QCTL:控制前缀字符#
QBIN:非ASCII前缀字符,传送二进制文件时使用
CHKT:校验和类型,单、双字符校验和、三字符的CRC校验分别用123来表示,默认值为1
REPT:重复前缀字符,通常为~
CAPAS:位模,表示Kermit的功能
接收方的Kermit用ACK数据包应答发送方的S类型数据包,以告诉对方确定了哪些初始化参数值,至此通信双方进行文件传输时的功能就确定下来了。需要注意的一点:当然如果接收方回复发送方的起始数据包的ACK中,DATA字段为空(就是不带有确认参数),则表示接收方要求发送方以默认值配置进行数据传输


Kermit协议传输流程图


Kermit接收数据代码
uint8_t Kermit_RxSubHandler(uint8_t Data)
{
    static uint8_t  Kermit_RxState = 0;
    static uint32_t Kermit_RxCheck = 0;

    uint8_t Kermit_Result = 0;

    switch(Kermit_RxState)
    {
        case 0x00:  /* MARK */
            if(Data == 0x01)
            {
                Kermit_RxState      = 0x01;
                Kermit_RxCheck      = 0x00;
                KermitRxPacket.MARK = Data;

                printf("\r\nMARK  : 0x%02x", Data);
            }
            break;

        case 0x01:  /* LEN */
            Kermit_RxState     = 0x02;
            Kermit_RxCheck    += Data;
            KermitRxPacket.LEN = Data;

            printf("\r\nLEN   : %d", KERMIT_UNCHAR(Data));
            break;

        case 0x02:  /* SEQ */
            Kermit_RxState     = 0x03;
            Kermit_RxCheck    += Data;
            KermitRxPacket.SEQ = Data;

            printf("\r\nSEQ   : %d", KERMIT_UNCHAR(Data));
            break;

        case 0x03:  /* TYPE */
            Kermit_RxState       = 0x04;
            Kermit_RxCheck      += Data;
            KermitRxPacket.TYPE  = Data;
            KermitRxPacket.Index = 0x00;

            printf("\r\nTYPE  : %c\r\nDATA  : ", Data);
            break;

        case 0x04:  /* DATA & CHECK */
            if((KermitRxPacket.Index + 3) == KERMIT_UNCHAR(KermitRxPacket.LEN))
            {
                Kermit_RxState       = 0x05;
                KermitRxPacket.CHECK = Data;

                printf("\r\nCHECK : [%c]", Data);
            }
            else
            {
                Kermit_RxCheck += Data;
                KermitRxPacket.DATA[KermitRxPacket.Index++] = Data;

                printf("%c", Data);
            }
            break;

        case 0x05:  /* EOL */
            if(Data == 0x0D)
            {
                Kermit_RxCheck %= 256;

                printf("\r\nCALC  : [%c]", KERMIT_TOCHAR((Kermit_RxCheck + ((Kermit_RxCheck & 0xC0) / 0x40)) & 0x3F));

                if(KermitRxPacket.CHECK == KERMIT_TOCHAR((Kermit_RxCheck + ((Kermit_RxCheck & 0xC0) / 0x40)) & 0x3F))
                {
                    Kermit_Result = 0x01;

                    printf("\tSuccess!");
                }
                else
                {
                    Kermit_Result = 0x02;

                    printf("\tError!!!");
                }

                Kermit_RxState     = 0x00;
                KermitRxPacket.EOL = Data;

                printf("\r\nEOL   : 0x%02x\r\n", Data);
            }
            else
            {
                printf("\r\n%c", Data);
            }
            break;

        default:
            Kermit_RxState = 0x00;
            break;
    }

    return Kermit_Result;
}

void Kermit_RxHandler(void)
{
    printf("\r\n%s\r\n", __FUNCTION__);

    QUEUE_INIT(QUEUE_RS232_RX_IDX);

    while(1)
    {
        if(QUEUE_EMPTY(QUEUE_RS232_RX_IDX) == 0)
        {
            uint8_t Result = Kermit_RxSubHandler(QUEUE_READ(QUEUE_RS232_RX_IDX));

            if(Result != 0)
            {
                if(KermitRxPacket.TYPE == 'S')
                {
                    printf("\r\nMAXL   : %d",        KERMIT_UNCHAR(KermitRxPacket.DATA[0]));
                    printf("\r\nTIME   : %d",        KERMIT_UNCHAR(KermitRxPacket.DATA[1]));
                    printf("\r\nNPAD   : %d",        KERMIT_UNCHAR(KermitRxPacket.DATA[2]));
                    printf("\r\nPADC   : 0x%02x",    KERMIT_UNCHAR(KermitRxPacket.DATA[3]));
                    printf("\r\nEOL    : 0x%02x",    KERMIT_UNCHAR(KermitRxPacket.DATA[4]));
                    printf("\r\nQCTL   : %c",        (KermitRxPacket.DATA[5]));
                    printf("\r\nQBIN   : %c",        (KermitRxPacket.DATA[6]));
                    printf("\r\nCHKT   : %c",        (KermitRxPacket.DATA[7]));
                    printf("\r\nREPT   : %c",        (KermitRxPacket.DATA[8]));
                    printf("\r\nCAPAS  : 0x%02x",    KERMIT_UNCHAR(KermitRxPacket.DATA[9]));
                    printf("\r\nWIND0  : %d",        KERMIT_UNCHAR(KermitRxPacket.DATA[10]));
                    printf("\r\nMAXLX1 : %d",        KERMIT_UNCHAR(KermitRxPacket.DATA[11]));
                    printf("\r\nMAXLX2 : %d",        KERMIT_UNCHAR(KermitRxPacket.DATA[12]));
                    printf("\r\n");
                }

                if((KermitRxPacket.TYPE == 'S') || (KermitRxPacket.TYPE == 'F') ||
                   (KermitRxPacket.TYPE == 'D') || (KermitRxPacket.TYPE == 'Z') ||
                   (KermitRxPacket.TYPE == 'B') || (KermitRxPacket.TYPE == 'E'))
                {
                    uint32_t CheckSum = 0;

                    RS232_SendData(KermitRxPacket.MARK);
                    RS232_SendData(KERMIT_TOCHAR(0x03));  CheckSum += KERMIT_TOCHAR(0x03);
                    RS232_SendData(KermitRxPacket.SEQ );  CheckSum += KermitRxPacket.SEQ;

                    if(Result == 1)
                    {
                        RS232_SendData('Y');              CheckSum += 'Y';
                    }
                    else
                    {
                        RS232_SendData('N');              CheckSum += 'N';
                    }

                    CheckSum %= 256;

                    RS232_SendData(KERMIT_TOCHAR((CheckSum + ((CheckSum & 0xC0) / 0x40)) & 0x3F));

                    printf("\r\n0x%02x %d %d %c %c", KermitRxPacket.MARK,  0x03,  KERMIT_UNCHAR(KermitRxPacket.SEQ),
                                                'Y', KERMIT_TOCHAR((CheckSum + ((CheckSum & 0xC0) / 0x40)) & 0x3F));

                    printf("\r\n");
                    printf("\r\n");
                }

                if(KermitRxPacket.TYPE == 'B')
                {
                    printf("\r\nKermitRxFinish"); return;
                }

                if(KermitRxPacket.TYPE == 'E')
                {
                    printf("\r\nKermitRxCancle"); return;
                }
            }
        }
    }
}


Kermit接收数据测试

接收单个文件数据

接收多个文件数据


Kermit发送数据代码
uint8_t Kermit_WaitReponse(uint8_t Data)
{
    uint8_t Result = 0;

    if(Kermit_RxSubHandler(Data) != 0)
    {
        switch(KermitRxPacket.TYPE)
        {
            case 'Y': Result = 1; break;
            case 'N': Result = 2; break;
            case 'E': Result = 3; break;
            default : break;
        }
    }

    return Result;
}

void Kermit_TxSubHandler(uint8_t State, uint8_t TxSEQ)
{
    static uint8_t Kermit_FileName = 0;
    static uint8_t Kermit_FileSize = 0;

    switch(State)
    {
        case 0x01:  /* S */
        {
            printf("\r\nSend S\r\n");

            uint32_t CheckSum = 0;

            uint8_t StartPacket[13] =
            {
                'p',    /* MAXL   */
                '*',    /* TIME   */
                ' ',    /* NPAD   */
                '@',    /* PADC   */
                '-',    /* EOL    */
                '#',    /* QCTL   */
                'Y',    /* QBIN   */
                '1',    /* CHKT   */
                '~',    /* REPT   */
                '*',    /* CAPAS  */
                '!',    /* WIND0  */
                'K',    /* MAXLX1 */
                '*',    /* MAXLX2 */
            };

            RS232_SendData(0x01);
            RS232_SendData(KERMIT_TOCHAR(0x03+0x0D));   CheckSum += KERMIT_TOCHAR(0x03+0x0D);
            RS232_SendData(KERMIT_TOCHAR(TxSEQ));       CheckSum += KERMIT_TOCHAR(TxSEQ);
            RS232_SendData('S');                        CheckSum += 'S';

            for(uint8_t i = 0; i < sizeof(StartPacket); i++)
            {
                RS232_SendData(StartPacket[i]);         CheckSum += StartPacket[i];
            }

            CheckSum %= 256;

            RS232_SendData(KERMIT_TOCHAR((CheckSum + ((CheckSum & 0xC0) / 0x40)) & 0x3F));

            RS232_SendData(0x0D);
        }
        break;

        case 0x02:  /* F */
        {
            printf("\r\nSend F\r\n");

            uint32_t CheckSum = 0;

            char FileName[20];
            memset(FileName, 0, sizeof(FileName));

            sprintf(FileName, "%d.TXT", Kermit_FileName);

            Kermit_FileSize = (Kermit_FileName + 1) * 20;

            RS232_SendData(0x01);
            RS232_SendData(KERMIT_TOCHAR(0x03+strlen(FileName))); CheckSum += KERMIT_TOCHAR(0x03+strlen(FileName));
            RS232_SendData(KERMIT_TOCHAR(TxSEQ));                 CheckSum += KERMIT_TOCHAR(TxSEQ);
            RS232_SendData('F');                                  CheckSum += 'F';

            for(uint8_t i = 0; i < strlen(FileName); i++)
            {
                RS232_SendData(FileName[i]);                      CheckSum += FileName[i];
            }

            CheckSum %= 256;

            RS232_SendData(KERMIT_TOCHAR((CheckSum + ((CheckSum & 0xC0) / 0x40)) & 0x3F));

            RS232_SendData(0x0D);
        }
        break;

        case 0x03:  /* D */
        {
            printf("\r\nSend D\r\n");

            uint32_t CheckSum = 0;

            RS232_SendData(0x01);
            RS232_SendData(KERMIT_TOCHAR(0x03+Kermit_FileSize));  CheckSum += KERMIT_TOCHAR(0x03+Kermit_FileSize);
            RS232_SendData(KERMIT_TOCHAR(TxSEQ));                 CheckSum += KERMIT_TOCHAR(TxSEQ);
            RS232_SendData('D');                                  CheckSum += 'D';

            for(uint8_t i = 0; i < Kermit_FileSize; i++)
            {
                RS232_SendData(0x20 + i);                         CheckSum += (0x20 + i);
            }

            CheckSum %= 256;

            RS232_SendData(KERMIT_TOCHAR((CheckSum + ((CheckSum & 0xC0) / 0x40)) & 0x3F));

            RS232_SendData(0x0D);
        }
        break;

        case 0x04:  /* Z */
        {
            printf("\r\nSend Z\r\n");

            uint32_t CheckSum = 0;

            RS232_SendData(0x01);
            RS232_SendData(KERMIT_TOCHAR(0x03));    CheckSum += KERMIT_TOCHAR(0x03);
            RS232_SendData(KERMIT_TOCHAR(TxSEQ));   CheckSum += KERMIT_TOCHAR(TxSEQ);
            RS232_SendData('Z');                    CheckSum += 'Z';

            CheckSum %= 256;

            RS232_SendData(KERMIT_TOCHAR((CheckSum + ((CheckSum & 0xC0) / 0x40)) & 0x3F));

            RS232_SendData(0x0D);

            Kermit_FileName = (Kermit_FileName + 1) % 4;
        }
        break;

        case 0x05:  /* B */
        {
            printf("\r\nSend B\r\n");

            uint32_t CheckSum = 0;

            RS232_SendData(0x01);
            RS232_SendData(KERMIT_TOCHAR(0x03));    CheckSum += KERMIT_TOCHAR(0x03);
            RS232_SendData(KERMIT_TOCHAR(TxSEQ));   CheckSum += KERMIT_TOCHAR(TxSEQ);
            RS232_SendData('B');                    CheckSum += 'B';

            CheckSum %= 256;

            RS232_SendData(KERMIT_TOCHAR((CheckSum + ((CheckSum & 0xC0) / 0x40)) & 0x3F));

            RS232_SendData(0x0D);
        }
        break;

        default:
            break;
    }
}

void Kermit_TxHandler(void)
{
    uint8_t  Kermit_TxState  = 0;
    uint8_t  Kermit_TxSEQ    = 0;
    uint8_t  Kermit_TxFinish = 0;

    uint8_t  Kermit_FileNumber = 4;
    uint32_t Kermit_WaitTime   = 0;

    printf("\r\n%s\r\n", __FUNCTION__);

    QUEUE_INIT(QUEUE_RS232_RX_IDX);

    while(1)
    {
        Kermit_TxSubHandler(Kermit_TxState, Kermit_TxSEQ);

        Kermit_WaitTime = 0;

        do
        {
            if(QUEUE_EMPTY(QUEUE_RS232_RX_IDX) == 0)
            {
                uint8_t Result = Kermit_WaitReponse(QUEUE_READ(QUEUE_RS232_RX_IDX));

                switch(Result)
                {
                    case 0x01:  /* ACK */
                        switch(Kermit_TxState)
                        {
                            case 0x01: Kermit_TxState  = 0x02; break;   /* S -> F */
                            case 0x02: Kermit_TxState  = 0x03; break;   /* F -> D */
                            case 0x03: Kermit_TxState  = 0x04; break;   /* D -> Z */

                            case 0x04:
                                Kermit_FileNumber--;

                                if(Kermit_FileNumber == 0)
                                {
                                    Kermit_TxState  = 0x05;             /* Z -> B */
                                }
                                else
                                {
                                    Kermit_TxState  = 0x02;             /* Z -> F */
                                }
                                break;

                            case 0x05: Kermit_TxFinish = 0x01; break;   /* B -> Finish */
                            default:
                                break;
                        }

                        Kermit_TxSEQ = (Kermit_TxSEQ + 0x01) % 0x40;
                        break;

                    case 0x02:  /* NAK */
                        Kermit_TxState = 0x01;
                        break;

                    case 0x03:  /* CANCLE */
                        Kermit_TxFinish = 0x02;
                        break;

                    default:
                        break;
                }

                if(Kermit_TxFinish == 0x01)
                {
                    printf("\r\nKermitTxFinish"); return;
                }

                if(Kermit_TxFinish == 0x02)
                {
                    printf("\r\nKermitTxCancle"); return;
                }

                if(Result != 0) Kermit_WaitTime = 100001;
            }
            else
            {
                SysTick_DelayMS(1);
            }

        }while(Kermit_WaitTime++ < 10000);
    }
}


Kermit发送数据测试

发送单个文件数据

发送多个文件数据


附件
软件工程源代码: Kermit.zip (2.75 MB)
Kermit协议: KermitProtocolManual.pdf (320.11 KB)
Kermit传输流程图: Kermit流程图.pdf (253.18 KB)
Kermit收发数据包: RX_DATA.zip (898 Bytes) TX_DATA.zip (1.1 KB)
Kermit参考资料: KERMIT的文件传输功能_符华儿.pdf (555.33 KB) KERMIT通信协议的一种改进方案_田峰.pdf (291.29 KB) Kermit协议及其在Windows环境下的研究与应用_田峰.pdf (230.73 KB) Windows环境下Kermit文件传输协议的研究与应用_贾宇波.pdf (268.44 KB) 具有高级功能的KERMIT文件传输协议_王华.pdf (565.21 KB) 微机教学多机通信系统中KERMIT文件协议实现_马建军.pdf (324.94 KB)

本文是基于SecureCRT软件进行测试Kermit协议进行收发数据的。Kermit应用很广泛,经常使用Linux系统的小伙伴很有体会哦

使用特权

评论回复

打赏榜单

21小跑堂 打赏了 100.00 元 2022-05-11
理由:恭喜通过原创文章审核!请多多加油哦!

沙发
www5911839| | 2022-5-5 13:06 | 只看该作者
【Kermit协议传输流程图】中的流程图片太模糊了,但是附件 【Kermit流程图.pdf】是非常高清的。 推荐用下 PDF24 软件(https://tools.pdf24.org/zh/),在阅读器单击鼠标右键, 可以直接将 PDF 的页面复制为图片。

pdf24.png (164.99 KB )

pdf24.png

使用特权

评论回复
板凳
xld0932|  楼主 | 2022-5-5 13:36 | 只看该作者
www5911839 发表于 2022-5-5 13:06
【Kermit协议传输流程图】中的流程图片太模糊了,但是附件 【Kermit流程图.pdf】是非常高清的。 推 ...

是原图片太大了,发布帖子的时候,系统可能自动做了缩放;原图肯定是清晰的;所以在附件中提供了PDF版本的

使用特权

评论回复
地板
xld0932|  楼主 | 2022-5-5 13:37 | 只看该作者
Kermit协议应用很广泛,尤其在Linux系统中用来进行文件传输;当前找到资料最多的就是教如何在Linux下的安装和使用,但描述在MCU上如何使用的分享却很少;本帖主要分享了基于MM32F3270芯片,使用SecureCRT软件通过Kermit协议进行文件数据传输的实现和测试过程,对基本通讯概念和注意事项做了描述,并绘制了传输流程图。

使用特权

评论回复
5
yklstudent| | 2022-5-5 21:05 | 只看该作者
kermit协议跟XMODEM、YMODEM和ZMODEM协议,有什么区别。。。

使用特权

评论回复
6
xld0932|  楼主 | 2022-5-5 21:30 | 只看该作者
yklstudent 发表于 2022-5-5 21:05
kermit协议跟XMODEM、YMODEM和ZMODEM协议,有什么区别。。。

对于我的理解就是Xmodem仅支持单个文件的收发、Ymodem支持多个文件的收发、Zmodem支持断点续传、而Kermit传输的都是可见字符,有些需要对数据进行处理后再传输。每个人对不同点的关注度不一样,你可以先尝试去了解每一个协议后,再去做详细的比对

使用特权

评论回复
7
weifeng90| | 2022-5-6 08:16 | 只看该作者
学习了,谢谢分享。

使用特权

评论回复
8
xld0932|  楼主 | 2022-5-6 08:29 | 只看该作者
weifeng90 发表于 2022-5-6 08:16
学习了,谢谢分享。

使用特权

评论回复
9
gouguoccc| | 2022-5-7 08:20 | 只看该作者
这与XMODEM和YMODEM有什么区别

使用特权

评论回复
10
xld0932|  楼主 | 2022-5-7 08:28 | 只看该作者
gouguoccc 发表于 2022-5-7 08:20
这与XMODEM和YMODEM有什么区别

6楼解释了

使用特权

评论回复
11
chenjun89| | 2022-5-8 17:07 | 只看该作者
那看来没有X、Y、ZModem实用。

使用特权

评论回复
12
xld0932|  楼主 | 2022-5-8 22:17 | 只看该作者
本帖最后由 xld0932 于 2022-5-9 18:59 编辑
chenjun89 发表于 2022-5-8 17:07
那看来没有X、Y、ZModem实用。

Uboot众所周知了,可以了解一下,里面有用到Kermit

使用特权

评论回复
13
liu96jp| | 2022-5-20 16:47 | 只看该作者
这种协议是不是就是标准呢?

使用特权

评论回复
14
t1ngus4| | 2022-5-20 17:02 | 只看该作者
我觉得协议这种可以自己规约,不过有现成的那是极好的,哈哈

使用特权

评论回复
15
ex7s4| | 2022-5-20 17:35 | 只看该作者
话说,kermit这个协议用的人多么?一般都用在哪儿啊?

使用特权

评论回复
16
q1ngt12| | 2022-5-20 18:23 | 只看该作者
232的话,自己设定个程序协议也行的,也比较好用

使用特权

评论回复
17
su1yirg| | 2022-5-20 18:57 | 只看该作者
其实数据包用你这种协议挺好,自己不用定制协议了

使用特权

评论回复
18
xld0932|  楼主 | 2022-5-20 19:56 | 只看该作者
su1yirg 发表于 2022-5-20 18:57
其实数据包用你这种协议挺好,自己不用定制协议了

嗯,这些都是通用的串行文件传输协议,有配套的上位机软件

使用特权

评论回复
19
tax2r6c| | 2022-5-22 08:16 | 只看该作者
这种协议是有数据大小限制的么?

使用特权

评论回复
20
lamanius| | 2022-5-22 08:45 | 只看该作者
听起来还不错,等以后有时间,研究研究这个协议

使用特权

评论回复
发新帖 本帖赏金 100.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:上海灵动微电子股份有限公司资深现场应用工程师
简介:诚信·承诺·创新·合作

70

主题

3001

帖子

31

粉丝