虚拟串口接收不定长数据
时间: 2025-01-09 18:40:12 浏览: 1
### 实现虚拟串口接收不定长数据
对于STM32F405/407系列微控制器,在使用USB虚拟串口时,为了能够有效地处理不定长数据的接收,可以采用基于事件驱动的方式。具体来说,当接收到特定字符序列或超时时触发数据读取操作。
#### 使用空闲线检测机制
在提供的代码库中已经实现了六个完全配置的串口,并启用了DMA功能以及空闲中断[^1]。这种设置非常适合用于处理不定长的数据流。每当串口处于空闲状态一段时间后会触发一次中断通知CPU有新消息到达,此时就可以收集缓冲区内的全部字节作为一条完整的命令或者记录下来。
#### USB 虚拟 COM 口回调函数
针对USB虚拟COM端口,则可以通过定义相应的回调函数来捕获来自上位机发送过来的信息包:
```c
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN ReceiveCallback */
// 将接收到的数据存入全局变量或其他合适位置
/* USER CODE END ReceiveCallback */
return (USBD_OK);
}
```
在此基础上还需要考虑如何判断一帧有效载荷结束的位置。一种常见做法是在协议层面规定特殊的终止符;另一种则是依靠定时器设定最大等待时限——如果超过该期限仍未遇到预期结尾标记则强行截断当前批次并提交解析引擎进一步分析其合法性。
#### 完整示例代码片段
下面给出一段简单的C语言程序用来展示上述概念的实际应用情况:
```c
#include "usbd_cdc_if.h"
// 假设我们有一个环形队列用于暂存未完成的消息体部分
#define BUFFER_SIZE 256
uint8_t buffer[BUFFER_SIZE];
volatile size_t head = 0;
volatile size_t tail = 0;
void AddToBuffer(const uint8_t byte){
if ((head + 1) % BUFFER_SIZE != tail){ // 队列未满
buffer[head++] = byte;
head %= BUFFER_SIZE;
}
}
int ProcessReceivedData(){
while(tail != head){
char c = buffer[tail++];
tail %= BUFFER_SIZE;
// 这里可以根据实际需求修改逻辑,
// 比如查找换行符(\n),分号(;)或者其他自定义定界符
if(c == '\n'){
// 找到一行完整的内容,调用其他函数进行后续处理...
// 清除已处理过的数据
tail = head = 0;
}else {
// 继续累加直到发现结束标志为止..
}
}
return 0;
}
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
for(size_t i=0;i<*Len;++i){
AddToBuffer(Buf[i]);
}
HAL_UART_Transmit(&huart1,(uint8_t*)"Echo:", strlen("Echo:"),HAL_MAX_DELAY);
HAL_UART_Transmit(&huart1,Buf,*Len,HAL_MAX_DELAY);
ProcessReceivedData();
return USBD_OK;
}
```
此段代码展示了如何通过USB虚拟串口接收不定长的数据,并将其存储在一个循环缓冲区内逐步累积成有意义的整体再做下一步动作。需要注意的是这里仅提供了一个非常基础的例子,真实场景下可能涉及到更复杂的错误恢复策略、多任务调度等问题。
阅读全文