当前位置: 首页 > news >正文

USBX移植(X是eXtended的意思)

1. 添加Class layer, 添加含有“ ux_device_class_cdc_acm_"前缀的C文件,其中,cdc是Communication Device Class 的缩写,acm是Abstract Control Model的缩写。

2. 添加stack layer,添加含有ux_device_stack_, ux_utility_, ux_system_前缀的C文件。

3. 添加Controller layer, 添加含有ux_dcd_stm32_前缀的C文件。其中dcd是Device Controller Driver的缩写。

4.添加app文件夹下的ux_device_cdc_acm.c, ux_device_descriptors.c, app_usbx_device.c

修改usb.c, 添加如下代码:

MX_USBX_Device_Init(); 
//使能usb控制器的电源
/*
HAL_PWREx_EnableVddUSB()是给USB模块本身供电,有些STM32的USB模块有独立的电源域,需要特别开启。HAL_PWREx_EnableUSBVoltageDetector()则是启用电压检测器,确保USB工作在稳定的电压下,这对可靠性至关重要。
*/
HAL_PWREx_EnableVddUSB();
HAL_PWREx_EnableUSBVoltageDetector();

HAL_PCDEx_PMAConfig(&hpcd_USB_DRD_FS, 0x00, PCD_SNG_BUF, 0x14);
HAL_PCDEx_PMAConfig(&hpcd_USB_DRD_FS, 0x80, PCD_SNG_BUF, 0x54);
HAL_PCDEx_PMAConfig(&hpcd_USB_DRD_FS, USBD_CDCACM_EPINCMD_ADDR, PCD_SNG_BUF, 0x94);
HAL_PCDEx_PMAConfig(&hpcd_USB_DRD_FS, USBD_CDCACM_EPOUT_ADDR, PCD_SNG_BUF, 0xD4);
HAL_PCDEx_PMAConfig(&hpcd_USB_DRD_FS, USBD_CDCACM_EPIN_ADDR, PCD_SNG_BUF, 0x114);
/*将初始化好的STM32 HAL库的USB设备句柄 (hpcd_USB_DRD_FS) 传递给USBX设备栈的STM32设备控制器驱动层(DCD),完成两层软件之间的对接。*/
ux_dcd_stm32_initialize((ULONG)USB_DRD_FS, (ULONG)&hpcd_USB_DRD_FS);//启动USB控制器
HAL_PCD_Start(&hpcd_USB_DRD_FS);/****************************
PCD: Peripheral Controller Driver
DRD: Dual Role Device
FS: Full Speed****************************/

在默认任务里调用如下函数:

ux_system_tasks_run();

app_freertos.c 

ux_device_cdc_acm_send((uint8_t *)buf, strlen(buf), 1000); 
当 USB 串口收到数据后,ux_device_class_cdc_acm_read_callback 函数被调用。

4.8 源码分析与改造

ux_device_cdc_acm_send会调用

/* 启动发送 */
UINT ux_device_class_cdc_acm_write_with_callback(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR 
*buffer, ULONG requested_length);
/* 发送完毕的回调函数 */
static UINT ux_device_class_cdc_acm_write_callback(struct UX_SLAVE_CLASS_CDC_ACM_STRUCT 
*cdc_acm, UINT status, ULONG length);

发送函数改造:

static SemaphoreHandle_t g_xUSBUARTSend;......VOID USBD_CDC_ACM_Activate(VOID *cdc_acm_instance)函数中创建信号量:{        ......if(!g_xUSBUARTSend){g_xUSBUARTSend = xSemaphoreCreateBinary(void);g_xUSBUART_RX_Queue = xQueueCreate(200,1);}......
}int ux_device_cdc_acm_send(uint8_t *datas, uint32_t len, uint32_t timeout)
{if (cdc_acm){//启动发送if (UX_SUCCESS == ux_device_class_cdc_acm_write_with_callback(cdc_acm, datas, len)){/* 等待发送完成*/if(pdTRUE == xSemaphoreTake(g_xUSBUARTSend, timeout)){return 0;}else{return -1;    //timeout}}else{return -1;}}else{return -1;}return 0;
}//发送完成的回调函数
static UINT ux_device_class_cdc_acm_write_callback(struct UX_SLAVE_CLASS_CDC_ACM_STRUCT *cdc_acm, UINT status, ULONG length)
{xSemaphoreGive(g_xUSBUARTSend);return 0;
}

接收函数改造:

static QueueHandle_t g_USBUART_RX_Queue;static UINT ux_device_class_cdc_acm_read_callback(struct UX_SLAVE_CLASS_CDC_ACM_STRUCT *cdc_acm, UINT status, UCHAR *data_pointer, ULONG length)
{for(int i=0; i<length; ++i){xQueueSendFromISR(g_USBUART_RX_Queue, (const void*)&data_pointer[i], 0);}return 0;
}
int ux_device_cdc_acm_getchar(uint8_t* pData, uint32_t timeout){if(g_xUSBUART_RX_Queue){if(pdPASS == xQueueReceive(g_xUSBUART_RX_Queue, pData, timeout))return 0;elsereturn -1;}else{return -1;}
}在CH2_UART4_RxTaskFunction(void* pvParameter)中调用该函数,验证接收的数据并打印出来

同UART,发送时使用信号量,接收数据时使用队列

http://www.dtcms.com/a/360253.html

相关文章:

  • 基于i.MX6ULL的RAM Disk驱动开发
  • Linux目录和命令介绍
  • 如何建立奢侈品牌的数字资产安全管控体系?
  • leetcode 371 两个整数之和
  • 智能数据建设与治理 Dataphin-数仓分层
  • 基于AI的大模型在S2B2C商城小程序中的应用与定价策略自我评估
  • “机器人管家“离我们还有多远?
  • 7.3 el-menu
  • 【C2000】C2000的硬件设计指导与几点意见
  • 官方 API 与网络爬虫的技术特性对比及选型分析
  • shell编程基础入门-2
  • Overleaf中文显示
  • 把 `QVector<QPointF>` 写入文件:三种风格、三段独立可编译的完整代码
  • APB协议​​ 构建一个完整的 ​​UVM验证VIP Agent介绍类的要素
  • 《隐性质量:决定软件生命周期的看不见的竞争力》
  • 【Linux】创建线程
  • flutter工程
  • 包的相对导入
  • Android开发简介
  • Redis常见数据类型及应用场景
  • Pytest 插件介绍和开发
  • 极客时间AI 全栈开发实战营毕业总结(2025年8月31日)
  • NCCL-TEST ib集群测试UCX代替方案
  • mit6.031软件构造 笔记 Testing
  • ROI、 binning、下采样功能区别
  • windows编译minicap.so文件
  • 由题构造 嵌入汇编(汇编)
  • NAS Docker 安装N8N
  • 计算机视觉与深度学习 | 双目立体特征提取与匹配算法综述——理论基础、OpenCV实践与MATLAB实现指南
  • 猛犸Lark max 无线麦克风录音爆音问题的解决