TI中文支持网
TI专业的中文技术问题搜集分享网站

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() failedwhile (1);}UserUART_config[0].fxnTablePtr->controlFxn(Uarthandle, UARTCC26XX_CMD_RETURN_PARTIAL_ENABLE, NULL);wantedRxBytes = 100;UserUART_config[0].fxnTablePtr->readFxn(Uarthandle, UserrxBuf, wantedRxBytes);
}

Galaxy Yue:

您好,

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

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

,

MarPing:

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

,

Galaxy Yue:

默认情况下是200ms

,

MarPing:

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

,

Galaxy Yue:

您好,

子程序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);
}

,

MarPing:

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

,

Galaxy Yue:

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

,

MarPing:

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() failedwhile (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;

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

,

Galaxy Yue:

MarPing 说:Uartparams.readTimeout   = 10000/ClockP_tickPeriod;

/Clock /ClockP  试试去掉P 

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

,

MarPing:

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

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

,

Galaxy Yue:

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

,

MarPing:

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

,

Galaxy Yue:

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

,

Galaxy Yue:

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

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

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

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

,

MarPing:

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

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

,

Galaxy Yue:

明确您的需求,

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

Galaxy Yue 说:

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

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

,

MarPing:

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

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

,

Galaxy Yue:

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

,

Galaxy Yue:

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

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

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

,

MarPing:

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

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

,

Galaxy Yue:

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

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

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

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

,

Galaxy Yue:

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1320327/cc2640r2l-serial-port-partial-return-function-question-about-return-method

这个是链接,您可以自行查看进度

,

MarPing:

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

而不是你所认为的问题

,

Galaxy Yue:

 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上去的一部分

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

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

我会继续重述

MarPing 说:我的问题应该是部分返回功能如何配置可以实现<10ms的数据不被分包,我希望通过调整部分返回这个功能来实现我的功能,因为我有必须使用回调模式和部分返回的理由,

,

MarPing:

我已经找到了关于”部分返回超时机制“的描述,如下(请注意注释部分):

/*!* @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_ENABLEUART_CMD_RESERVED + 0

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

谢谢

,

Galaxy Yue:

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

,

Galaxy Yue:

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

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

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

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

赞(0)
未经允许不得转载:TI中文支持网 » CC2640R2L: 串口“部分返回”功能,返回方式疑问
分享到: 更多 (0)