This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2640R2L: 串口“部分返回”功能,返回方式疑问

Part Number: CC2640R2L

在使用2640串口时,配置为回调方式并开启部分返回功能接收不定长字符串,正常情况下2640串口收到一个字符串,可以一包收到,但是当发送方发送的字符之间延时稍大,2640的接收就会分包,这个应该是部分返回功能导致的,我想知道部分返回功能是什么原理,是超过一定时间没有接收到下一个字节就会返回吗?还是有其他判断方式进行部分返回?

代码如下:

// Callback function
static void UartreadCallback(UART_Handle handle, void *rxBuf, size_t size)
{

    //UserUART_config[0].fxnTablePtr->writeFxn(Uarthandle,rxBuf,size);
    UartReceiveDataProcess(rxBuf,size);
    UserUART_config[0].fxnTablePtr->readFxn(Uarthandle,UserrxBuf,wantedRxBytes);

}


void UserUartInit(void)
{
    // Initialize the UART driver.
    UART_init();

    // Create a UART with data processing off.
    UART_Params_init(&Uartparams);                                //初始化是赋予一个默认值
    Uartparams.baudRate      = 9600;
    Uartparams.writeDataMode = UART_DATA_BINARY;                  //可以选择二进制格式还是10进制格式
    Uartparams.readMode      = UART_MODE_CALLBACK;
    Uartparams.readDataMode  = UART_DATA_BINARY;
    Uartparams.readCallback  = UartreadCallback;

    Uarthandle = UART_open(Board_UART0, &Uartparams);
    if (Uarthandle == NULL)
    {
        // UART_open() failed
        while (1)
            ;
    }
    UserUART_config[0].fxnTablePtr->controlFxn(Uarthandle, UARTCC26XX_CMD_RETURN_PARTIAL_ENABLE, NULL);

    wantedRxBytes = 100;
    UserUART_config[0].fxnTablePtr->readFxn(Uarthandle, UserrxBuf, wantedRxBytes);
}

  • 您好,

    部分返回功能是指当串口接收到一个字节时,如果在超过一定时间(由硬件决定)内没有接收到下一个字节,就会触发回调函数。

    在收到一个完整的字符串时,串口会停止触发回调函数并返回整个字符串。但如果发送方发送的字符之间延时稍大,串口就会分包接收。在分包接收时,串口会先触发回调函数,返回已经接收到的部分字符串,然后继续等待下一个字节的到来。这样就实现了部分返回功能。

  • 您好,我所使用的器件是CC2640R2L,请问你所提到的一定时间具体指多久?

  • 默认情况下是200ms

  • 目前我观察到的是两个字节间隔4ms不会分包,但是两个字节间隔5ms,就会部分返回变成一个一个的字节,默认是200ms应该不会出现这种情况吧,这个是可以进行配置的吗?请问该如何配置,我没有查找到相关资料,手册和协议栈中也没有看到相关内容,感谢

  • 您好,

    子程序UART_Params_init(),9600您可以更改成115200进行观察一下

    先调用这个子程序,对所有参数进行赋予默认值。
    接下来,您可以对一些至关重要的参数进行自定义赋值,比如波特率,进制格式,接收是选择回调还是等待,接收数据是什么格式,如果是回调模式,就要设置回调程序的指针,等等,设置好了以后,进行初始化,就是这个openFxn子程序,与要进行设置的参数,进行分配,然后返回一个已经配置好了的handle,handle实际就是个首地址,你配置的个个参数存放的首地址。

    void UserUartInit(void)
    {
          UART_Params_init(&Uartparams);                                //初始化是赋予一个默认值
          Uartparams.baudRate      = 115200;
          Uartparams.writeDataMode = UART_DATA_BINARY;                  //可以选择二进制格式还是10进制格式
          Uartparams.readMode      = UART_MODE_CALLBACK;
          Uartparams.readDataMode  = UART_DATA_BINARY;
          Uartparams.readCallback  = UartreadCallback;
          Uarthandle = UserUART_config[0].fxnTablePtr->openFxn((UART_Handle)&UserUART_config[0],&Uartparams);
    //      UARTCC26XX_read(UART_Handle handle, void *buffer, size_t size)
          wantedRxBytes = 20;
          UserUART_config[0].fxnTablePtr->readFxn(Uarthandle,UserrxBuf,wantedRxBytes);
          UserUART_config[0].fxnTablePtr->controlFxn(Uarthandle, UARTCC26XX_CMD_RETURN_PARTIAL_ENABLE,NULL);
    }
    

  • 我是指串口在回调模式下,启用了部分返回功能后,这个部分返回的超时时间,你之前提到默认是200ms,既然有默认,那么说明这个部分返回的时间可以配置,部分返回的时长如何配置?

  • UART_Params的结构体中对参数 readTimeout 进行设置

  • readTimeout这个参数的注释说明这个参数在blocking模式下有效,我现在使用的是回调模式,能够正常生效吗?我尝试将串口这样初始化:

    void UserUartInit(void)
    {
        // Initialize the UART driver.
        UART_init();
    
        // Create a UART with data processing off.
        UART_Params_init(&Uartparams);                                //初始化是赋予一个默认值
        Uartparams.baudRate      = 9600;
        Uartparams.writeDataMode = UART_DATA_BINARY;                  //可以选择二进制格式还是10进制格式
        Uartparams.readMode      = UART_MODE_CALLBACK;
        Uartparams.readDataMode  = UART_DATA_BINARY;
        Uartparams.readCallback  = UartreadCallback;
        Uartparams.readTimeout   = 10000/ClockP_tickPeriod;
    
        Uarthandle = UART_open(Board_UART0, &Uartparams);
        if (Uarthandle == NULL)
        {
            // UART_open() failed
            while (1)
                ;
        }
    //    Uarthandle = UserUART_config[0].fxnTablePtr->openFxn((UART_Handle) &UserUART_config[0], &Uartparams);
    //    UARTCC26XX_read(UART_Handle handle, void *buffer, size_t size)
    
        UserUART_config[0].fxnTablePtr->controlFxn(Uarthandle, UARTCC26XX_CMD_RETURN_PARTIAL_ENABLE, NULL);
    
        wantedRxBytes = 100;
        UserUART_config[0].fxnTablePtr->readFxn(Uarthandle, UserrxBuf, wantedRxBytes);
    }

    Uartparams.readTimeout   = 10000/ClockP_tickPeriod;

    我添加了这行代码用于设置超时,实际上它好像并没有起作用

  • Uartparams.readTimeout   = 10000/ClockP_tickPeriod;

    /Clock /ClockP  试试去掉P 

    如果该参数传递无效就是只能在blocking模式下,并且回调模式下,timeout由系统和驱动库自动管理

  • Clock_tickPeriod没有这个定义,直接使用数值也没用

    如果是系统和驱动自动管理,有没有什么办法调整呢,由哪个驱动文件管理的?

  • 超时机制:只有在Block模式下才有read和write的超时机制,超时发生时将会返回已经接收到的data,而RX在超时后仍然是enable的。而在Callback模式下,没有超时机制,只有显式调用UART_readCancel()或UART_writeCancel()才能取消操作。重新开始一次read或write都会将UART_Object.status的值重置为UART_OK;

  • 2640串口在callback模式下,开启了部分返回机制后,你之前说的是超时产生的部分返回,是这个的时间,你这会又说没有超时机制,麻烦你看看标题和之前的回复好吗,回答一直翻过来翻过去说不到问题上

  • 为更加有效地解决您的问题,我需要询问更了解这款芯片的TI资深工程师,再为您解答,一旦得到回复会立即回复给您。

  • 以下来自英文论坛工程师的回复:

     如果您需要测量程序的延迟,您可以使用 GPIO 引脚(高/低)和逻辑分析仪来根据需要读取程序中特定点的高点和低点。

    - 您是否使用 UART 从 PuTTY 等设备接收字符数据?

    - 您使用的 SDK 版本和基准示例是什么?

  • 不是要测量程序延迟,是要知道回调模式下串口“部分返回”的原理和详细信息,包括在什么条件下可以会触发部分返回,如果是超过一定时间没有数据会触发部分返回,那么这个时间如何配置?

    我现在遇到的问题是:配置串口为回调模式,开启部分返回功能,当收到的字节间隔<4ms,这些字节会被认为是一包数据通过回调返回,当收到的字节间隔>5ms,这些字节每一个都会触发独立的回调,变成一个一个单独的字节,我不希望出现这样的现象,我希望当每个字节间隔<10ms时,都能被认为一包返回,我该如何实现?

  • 明确您的需求,

    请就以下问题也做出回答,SDK版本会有部分影响

    - 您是否使用 UART 从 PuTTY 等设备接收字符数据?

    - 您使用的 SDK 版本和基准示例是什么?

  • 使用的是另一块mcu通过定时器定时发送数据

    SDK版本是simplelink_cc2640r2_sdk_1_40_00_45,基准示例是simple_peripheral

  • 信息会同步更新到英文论坛,有消息会通知您

  • 感谢您详细解释您的问题。 我认为有几种方法可以实现解决方案,首先是使用某些 UART 参数,例如 ReturnMode 字段,可以将其配置为在缓冲区已满或收到换行符时执行回调。 这样程序可以等到缓冲区完成或输入换行符。


    如果您确实使用 ReturnMode,则还需要更改 DataMode,如下面的注释中所述。

    您也许可以使用信号量和延迟来允许缓冲区接收更多数据。

  • 我觉得我的问题已经描述的足够清楚,我需要使用callback模式,并且由于是不定长数据,我无法使用RETURN_FULL,并且我的数据是流式数据,不是文本,我也不能使用NEW_Line,我希望您专注于我的问题:“有关串口部分返回功能的解释,关于部分返回的条件,部分返回时长的调整”,而不是转移问题,我认为我咨询的是一个相当详尽和明确的问题,如果您热衷于重构我的功能,我可以提交我的代码,您来帮我通过其他方式实现

    所以请关注问题本身,而不是通过其他方式转移问题,谢谢

  • 我现在遇到的问题是:配置串口为回调模式,开启部分返回功能,当收到的字节间隔<4ms,这些字节会被认为是一包数据通过回调返回,当收到的字节间隔>5ms,这些字节每一个都会触发独立的回调,变成一个一个单独的字节,我不希望出现这样的现象,我希望当每个字节间隔<10ms时,都能被认为一包返回,我该如何实现?

    已经将您的问题如实描述给英文论坛

    以上是来自英文团队工程师的回复

    会再次将您的问题重述给英文论坛

  • 你引用的是我描述目前部分返回功能产生的现象,结合上下文我的问题应该是部分返回功能如何配置可以实现<10ms的数据不被分包,我希望通过调整部分返回这个功能来实现我的功能,因为我有必须使用回调模式和部分返回的理由,所以请关注问题本身:

    而不是你所认为的问题

  •  I hope that when the interval between each byte is <10ms, it can be considered as a packet and returned. , how can I achieve?

    这个是之前根据你的描述在英文post上去的一部分

    下面这段就是来自英文论坛的回应

    我认为有几种方法可以实现解决方案,首先是使用某些 UART 参数,例如 ReturnMode 字段,

    我会继续重述

    我的问题应该是部分返回功能如何配置可以实现<10ms的数据不被分包,我希望通过调整部分返回这个功能来实现我的功能,因为我有必须使用回调模式和部分返回的理由,
  • 我已经找到了关于”部分返回超时机制“的描述,如下(请注意注释部分):

    /*!
     * @brief Command used by UART_control to enable partial return
     *
     * Enabling this command allows UART_read to return partial data if data
     * reception is inactive for a given 32-bit period.  With this command @b arg
     * is @a don't @a care and it returns UART_STATUS_SUCCESS.
     */
    #define UARTCC26XX_CMD_RETURN_PARTIAL_ENABLE    UART_CMD_RESERVED + 0

    也就是说,在9600波特率下,传输一个bit是0.104ms,32个周期即3.32ms,这与我目前的测试是一致的,现在我的问题是,这个32bit可以修改或者配置吗,我希望等待更长的周期

    谢谢

  • 上午已经在英文论坛继续跟进了,请等候回复,谢谢

  • 用户无法修改 32 位非活动周期,因为它是由硬件本身设置的。 

    https://e2e.ti.com/f/1/t/762686/

    您可以配置 readTimeout 和 writeTimeout 以适合您的用例,因为周期字段是可修改的。 (请注意, 使用UART_MODE_CALLBACK模式 时未使用 UART_Params.readTimeout  ,因此您可能必须创建自己的回调/任务来处理数据)。 

    UARTCC26XX.h 文件参考 (ti.com)