本项目为2025贸泽电子M-Design创意设计竞赛,方向一:边缘智能、智能设备的作品。
虽然现在的PC上难以见到传统的9芯串口,但是串口仍然存在于各种设备上。比如,串口是单片机必不可少的接口。此外,USB串口可以方便的实现PC对外的接口,因此串口编程仍然是一个通用的PC对外通讯接口。
一些时候,我们设计的外部设备使用USB串口通讯,在编写上位机应用程序的时候我们不可避免的需要串口调试,我们需要得知发送的数据是否符合预期。一种方法是直接使用逻辑分析抓取设备端的串口数据,这种方法优点是非常可靠,缺点是比较麻烦,需要连接线路,此外如果调试目标的是USB 串口是通过单片机内部实现的,那么就无法实现抓取;另外一种方法是通过在主机端安装虚拟串口软件,这种方法的优点是灵活,可以配置出来各种组合,缺点是软件按台计费成本较高,同时因为是驱动实现的,在一些特殊情况下比如操作系统升级还会遇到兼容性问题。
这次的作品是通过 Ch32V305实现的虚拟串口设备(我将这种设备称作“PVD”,Physical Virtual Device,物理虚拟设备,更多设备可以在【参考1】中看到)。设计上非常简单,可以看作是一个 Ch32V305的最小系统。设备通过USB 供电,之后通过TLV1117,将5V转化为3.3V,提供给芯片。芯片外围电路非常简单:一个8Mhz晶振提供信号源,配合2个100nF 电容即可工作。
PCB 设计如下:
焊接之后的实物如下:
对于这样的设计来说,代码是重中之重。这次我们使用CherryUSB 框架配合 FreeRTOS实现了设计目标。
设计上,我们使用了4个端点进行收发:
工作流程如下:
具体关键代码如下:
1.代码入口在 main.c 文件中,这里会对设备进行初始化设定
int main(void)
{
SystemCoreClock = 0;
SystemCoreClockUpdate();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n", SystemCoreClock);
printf("This is Audio example\r\n");
Com_Init();
xTaskCreate(Led_task, (const char*)"Led", (uint16_t)32, (void*)NULL, (UBaseType_t)5, NULL);
/* Start the scheduler. */
vTaskStartScheduler();
while(1)
{
}
}
2.作为USB设备描述符是重要的部分,具体描述符在cdc_acm_multi.c 中的cdc_descriptor[]结构体中定义,此外,为了方便配置,还模拟除了一个HID 设备,具体的描述符在hid_custom_report_desc 中定义。
3.借由前面提到的 CherryUSB框架,收到的数据会在Com_Data_Recv() 函数中进行处理,根据设定将收到的数据进行转发
// 处理数据接收的函数,只能在中断调用
void Com_Data_Recv(uint8_t DevIndex, uint8_t* DataPtr, uint32_t DataLen)
{
uint8_t ComCfgData = ComConfig[DevIndex];
Com_Data_Queue stQueue;
BaseType_t xHigherPriorityTaskWoken;
stQueue.DataPtr = DataPtr;
stQueue.DataLen = DataLen;
for (uint8_t i = 0; i < ComDevCnt; ++i)
{
if (ComCfgData & 1 << i)
{
// 数据复制一份
stQueue.DataPtr = pvPortMalloc(DataLen);
if (stQueue.DataPtr)
{
memcpy(stQueue.DataPtr, DataPtr, DataLen);
// 将数据放入队列中
xQueueSendFromISR(ComQueue[i], &stQueue, &xHigherPriorityTaskWoken);
// if (xPortIsInsideInterrupt()) {
// xQueueSendFromISR(ComQueue[i], &stQueue, &xHigherPriorityTaskWoken);
// } else {
// xQueueSend(ComQueue[i], &stQueue, portMAX_DELAY);
// }
}
}
}
}
编译后的代码通过 LinkE烧录到设备中之后插入PC中即可使用。因为每次要求配置组合不同,我们还设计了一个上位机程序。程序执行之后会使用USB HID 和设备通讯,将配置信息发送给设备。
感谢贸泽电子与硬禾科技举办的创意设计竞赛。这是我们第一次在 FreeRTOS 上使用CherryUSB 框架。可以看到,这样的方法使得资源调配变得非常容易,使用者可以对任务目标进行聚焦。团队成员一边学习一边实践,相互配合分工协作,在一个又一个周末不断沟通协调,最终完成了目标。
