北京高端网站设计,网站开发项目经验,江西网页制作,楚雄建网站#虚拟串口模拟CH340#
代码gitee地址#xff1a;STM32F103_CH340: 用STM32模拟ch340USB串口的功能
一、思路
1. 确定通信接口#xff1a;CH340是一款USB转串口芯片#xff0c;因此您需要选择STM32上的某个USB接口来实现USB通信。通常情况下#xff0c;STM32系列芯片都有内…#虚拟串口模拟CH340#
代码gitee地址STM32F103_CH340: 用STM32模拟ch340USB串口的功能
一、思路
1. 确定通信接口CH340是一款USB转串口芯片因此您需要选择STM32上的某个USB接口来实现USB通信。通常情况下STM32系列芯片都有内置的USB接口您可以根据您的具体型号选择合适的接口。 2. 实现USB功能在STM32上启用USB功能您需要在代码中初始化USB接口并配置相关的参数例如USB模式、中断等。您可以参考STM32官方提供的库函数和示例代码来实现USB功能。 3. 实现串口功能虚拟串口的核心功能是数据的收发您需要实现串口的初始化、配置和中断处理等。在STM32上UART或USART模块通常用于串口通信。您可以根据需求选择合适的串口模块并在代码中进行相应的配置。 4. 实现CH340协议CH340芯片有自己的通信协议您需要在STM32上实现类似的协议。根据CH340的功能您需要处理一些特定命令和数据格式例如设置波特率、读写寄存器等。您可以在代码中定义相应的结构体和函数来处理CH340协议。 5. 编写数据收发逻辑虚拟串口的关键是数据的收发您需要编写代码来处理上位机发送的数据和发送数据给上位机。在接收数据时您需要处理数据的帧格式和校验等确保数据的完整性和正确性。在发送数据时您需要按照CH340协议的要求组织数据并发送给上位机。 6. 测试与调试完成代码编写后您需要进行测试与调试确保虚拟串口功能正常工作。您可以使用串口调试助手等工具来与虚拟串口进行通信并进行功能验证。
二、关键代码
1.CH340设备信息代码 /********************************************************************************* file usb_desc.c* brief Descriptors for Virtual Com Port Demo******************************************************************************* attention** h2centercopy; COPYRIGHT 2013 STMicroelectronics/center/h2** Licensed under MCD-ST Liberty SW License Agreement V2, (the License);* You may not use this file except in compliance with the License.* You may obtain a copy of the License at:** http://www.st.com/software_license_agreement_liberty_v2** Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.********************************************************************************//* 包含文件 ------------------------------------------------------------------*/
#include usb_lib.h
#include usb_desc.h/* USB 标准设备描述符 */
const uint8_t Virtual_Com_Port_DeviceDescriptor[]
{0x12, /* bLength */USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */0x10,0x01, /* bcdUSB 1.10 */0xff, /* bDeviceClass: CDC */0x00, /* bDeviceSubClass */0x00, /* bDeviceProtocol */0x40, /* bMaxPacketSize0 */0x86,0x1a, /* idVendor 0x1A86 */0x23,0x75, /* idProduct 0x7523 */0x64,0x02, /* bcdDevice 2.00 */1, /* 制造商描述符的索引 */2, /* 产品描述符的索引 */3, /* 设备序列号的描述符的索引 */0x01 /* 配置描述符的数量 */
};const uint8_t Virtual_Com_Port_ConfigDescriptor[]
{/* 配置描述符 */0x09, /* bLength: 配置描述符的长度 */USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */VIRTUAL_COM_PORT_SIZ_CONFIG_DESC, /* wTotalLength: 所有返回的字节数 */0x00,0x01, /* bNumInterfaces: 接口的数量 */0x01, /* bConfigurationValue: 配置值 */0x00, /* iConfiguration: 描述该配置的字符串描述符的索引 */0x80, /* bmAttributes: 自供电 */0x30, /* MaxPower: 0 mA *//* 接口描述符 */0x09, /* bLength: 接口描述符的长度 */USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface *//* 接口描述符类型 */0x00, /* bInterfaceNumber: 接口的编号 */0x00, /* bAlternateSetting: 替代设置 */0x03, /* bNumEndpoints: 使用的端点数 */0xff, /* bInterfaceClass: 通信接口类 */0x01, /* bInterfaceSubClass: 抽象控制模型 */0x02, /* bInterfaceProtocol: 通用 AT 命令 */0x00, /* iInterface: 描述该接口的字符串描述符的索引 *//* 端点2输入描述符 */0x07, /* bLength: 端点描述符的长度 */USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */0x82, /* bEndpointAddress: (IN2) */0x02, /* bmAttributes: 传输类型为批量传输 */0x20, /* wMaxPacketSize: 最大数据包大小 */0x00,0x00, /* bInterval: 传输间隔 *//* 端点2输出描述符 */0x07, /* bLength: 端点描述符的长度 */USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */0x02, /* bEndpointAddress: (OUT2) */0x02, /* bmAttributes: 传输类型为批量传输 */0x20, /* wMaxPacketSize: 最大数据包大小 */0x00,0x00, /* bInterval: 传输间隔 *//* 端点1输入描述符 */0x07, /* bLength: 端点描述符的长度 */USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */0x81, /* bEndpointAddress: (IN1) */0x03, /* bmAttributes: 传输类型为中断传输 */0x08, /* wMaxPacketSize: 最大数据包大小 */0x00,0x01 /* bInterval: 传输间隔 */
};/* USB 字符串描述符 */
const uint8_t Virtual_Com_Port_StringLangID[VIRTUAL_COM_PORT_SIZ_STRING_LANGID]
{VIRTUAL_COM_PORT_SIZ_STRING_LANGID,USB_STRING_DESCRIPTOR_TYPE,0x09,0x04 /* LangID 0x0409: U.S. English */
};const uint8_t Virtual_Com_Port_StringVendor[VIRTUAL_COM_PORT_SIZ_STRING_VENDOR]
{VIRTUAL_COM_PORT_SIZ_STRING_VENDOR, /* 制造商字符串的大小 */USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType*//* 制造商名称: wch.cn */w, 0, c, 0, h, 0, ., 0, c, 0, n, 0
};const uint8_t Virtual_Com_Port_StringProduct[VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT]
{VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT, /* bLength */USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType *//* 产品名称: USB 串口 */U, 0, S, 0, B, 0, , 0, S, 0, e, 0, r, 0, i, 0, a, 0, l, 0
};uint8_t Virtual_Com_Port_StringSerial[VIRTUAL_COM_PORT_SIZ_STRING_SERIAL]
{VIRTUAL_COM_PORT_SIZ_STRING_SERIAL, /* bLength */USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType *//* 设备序列号: 0123456789 */0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0 , 6, 0, 7, 0, 8, 0, 9, 0
};/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
2.添加CH340特有初始化代码 - Virtual_Com_Port_Init函数初始化虚拟串口设备包括获取设备的唯一序列号、设置设备的配置和连接状态等。 - Virtual_Com_Port_Reset函数重置虚拟串口设备包括设置设备的初始状态和清零设备配置和接口信息。 - Virtual_Com_Port_SetConfiguration函数根据设备的配置信息更新设备状态。 - Virtual_Com_Port_SetDeviceAddress函数设置设备的地址。 - Virtual_Com_Port_Status_In和Virtual_Com_Port_Status_Out函数处理设备的状态 IN 和 OUT 请求。 - Virtual_Com_Port_Data_Setup函数处理数据类特定的请求如获取和设置线编码等。 - Virtual_Com_Port_NoData_Setup函数处理非数据类特定的请求如设置串口控制线状态等。 - Virtual_Com_Port_GetDeviceDescriptor、Virtual_Com_Port_GetConfigDescriptor和Virtual_Com_Port_GetStringDescriptor函数获取设备描述符、配置描述符和字符串描述符。 /******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name : usb_prop.c
* Author : MCD Application Team
* Version : V2.2.0
* Date : 06/13/2008
* Description : All processing related to Virtual Com Port Demo
********************************************************************************
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************//* Includes ------------------------------------------------------------------*/
#include usb_lib.h
#include usb_conf.h
#include usb_prop.h
#include usb_desc.h
#include usb_pwr.h
#include hw_config.h
u32 ch341_state0xeeff;
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
u8 Request 0;
void USART_Config_Default(void)
{}LINE_CODING linecoding {115200, /* baud rate*/0x00, /* stop bits-1*/0x00, /* parity - none*/0x08 /* no. of bits 8*/};/* -------------------------------------------------------------------------- */
/* Structures initializations */
/* -------------------------------------------------------------------------- */DEVICE Device_Table {EP_NUM,1};DEVICE_PROP Device_Property {Virtual_Com_Port_init,Virtual_Com_Port_Reset,Virtual_Com_Port_Status_In,Virtual_Com_Port_Status_Out,Virtual_Com_Port_Data_Setup,Virtual_Com_Port_NoData_Setup,Virtual_Com_Port_Get_Interface_Setting,Virtual_Com_Port_GetDeviceDescriptor,Virtual_Com_Port_GetConfigDescriptor,Virtual_Com_Port_GetStringDescriptor,0,0x40 /*MAX PACKET SIZE*/};USER_STANDARD_REQUESTS User_Standard_Requests {Virtual_Com_Port_GetConfiguration,Virtual_Com_Port_SetConfiguration,Virtual_Com_Port_GetInterface,Virtual_Com_Port_SetInterface,Virtual_Com_Port_GetStatus,Virtual_Com_Port_ClearFeature,Virtual_Com_Port_SetEndPointFeature,Virtual_Com_Port_SetDeviceFeature,Virtual_Com_Port_SetDeviceAddress};ONE_DESCRIPTOR Device_Descriptor {(u8*)Virtual_Com_Port_DeviceDescriptor,VIRTUAL_COM_PORT_SIZ_DEVICE_DESC};ONE_DESCRIPTOR Config_Descriptor {(u8*)Virtual_Com_Port_ConfigDescriptor,VIRTUAL_COM_PORT_SIZ_CONFIG_DESC};ONE_DESCRIPTOR String_Descriptor[4] {{(u8*)Virtual_Com_Port_StringLangID, VIRTUAL_COM_PORT_SIZ_STRING_LANGID},{(u8*)Virtual_Com_Port_StringVendor, VIRTUAL_COM_PORT_SIZ_STRING_VENDOR},{(u8*)Virtual_Com_Port_StringProduct, VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT},{(u8*)Virtual_Com_Port_StringSerial, VIRTUAL_COM_PORT_SIZ_STRING_SERIAL}};/* Extern variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Extern function prototypes ------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name : Virtual_Com_Port_init.
* Description : Virtual COM Port Mouse init routine.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void Virtual_Com_Port_init(void)
{/* Update the serial number string descriptor with the data from the uniqueID*/Get_SerialNum();pInformation-Current_Configuration 0;/* Connect the device */PowerOn();/* USB interrupts initialization *//* clear pending interrupts */_SetISTR(0);wInterrupt_Mask IMR_MSK;/* set interrupts mask */_SetCNTR(wInterrupt_Mask);/* configure the USART 1 to the default settings */USART_Config_Default();bDeviceState UNCONNECTED;
}/*******************************************************************************
* Function Name : Virtual_Com_Port_Reset
* Description : Virtual_Com_Port Mouse reset routine
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void Virtual_Com_Port_Reset(void)
{/* Set Virtual_Com_Port DEVICE as not configured */pInformation-Current_Configuration 0;/* Current Feature initialization */pInformation-Current_Feature Virtual_Com_Port_ConfigDescriptor[7];/* Set Virtual_Com_Port DEVICE with the default Interface*/pInformation-Current_Interface 0;SetBTABLE(BTABLE_ADDRESS);/* Initialize Endpoint 0 */SetEPType(ENDP0, EP_CONTROL);SetEPTxStatus(ENDP0, EP_TX_STALL);SetEPRxAddr(ENDP0, ENDP0_RXADDR);SetEPTxAddr(ENDP0, ENDP0_TXADDR);Clear_Status_Out(ENDP0);SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);SetEPRxValid(ENDP0);/* Initialize Endpoint 1 */SetEPType(ENDP1, EP_INTERRUPT);SetEPTxAddr(ENDP1, ENDP1_TXADDR);SetEPTxStatus(ENDP1, EP_TX_NAK);SetEPRxStatus(ENDP1, EP_RX_DIS);// SetEPRxValid(ENDP1);/* Initialize Endpoint 2 */SetEPType(ENDP2, EP_BULK);SetEPTxAddr(ENDP2, ENDP2_TXADDR);SetEPTxStatus(ENDP2, EP_TX_NAK);SetEPRxStatus(ENDP2, EP_RX_VALID);// SetEPRxValid(ENDP2);/* Initialize Endpoint 2 */SetEPType(ENDP2, EP_BULK);SetEPRxAddr(ENDP2, ENDP2_RXADDR);SetEPRxCount(ENDP2, VIRTUAL_COM_PORT_DATA_SIZE);/* Set this device to response on default address */SetDeviceAddress(DADDR_EF|0);// SetDeviceAddress(0);bDeviceState ATTACHED;
}/*******************************************************************************
* Function Name : Virtual_Com_Port_SetConfiguration.
* Description : Udpade the device state to configured.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void Virtual_Com_Port_SetConfiguration(void)
{DEVICE_INFO *pInfo Device_Info;if (pInfo-Current_Configuration ! 0){/* Device configured */bDeviceState CONFIGURED;}
}/*******************************************************************************
* Function Name : Virtual_Com_Port_SetConfiguration.
* Description : Udpade the device state to addressed.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void Virtual_Com_Port_SetDeviceAddress (void)
{bDeviceState ADDRESSED;
}/*******************************************************************************
* Function Name : Virtual_Com_Port_Status_In.
* Description : Virtual COM Port Status In Routine.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void Virtual_Com_Port_Status_In(void)
{if (Request SET_LINE_CODING){USART_Config();Request 0;}
}/*******************************************************************************
* Function Name : Virtual_Com_Port_Status_Out
* Description : Virtual COM Port Status OUT Routine.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void Virtual_Com_Port_Status_Out(void)
{}/*******************************************************************************
* Function Name : Virtual_Com_Port_Data_Setup
* Description : handle the data class specific requests
* Input : Request Nb.
* Output : None.
* Return : USB_UNSUPPORT or USB_SUCCESS.
*******************************************************************************/
static u8 vender_request;u8 *Vender_Handle_CH341(u16 Length)
{u16 wValue pInformation-USBwValues.w;u16 wIndex pInformation-USBwIndexs.w;static u8 buf1[2]{0x30,0};static u8 buf2[2]{0xc3,0};change_byte(wValue);change_byte(wIndex);if (Length 0 (vender_request0x5f||vender_request0x95)){pInformation-Ctrl_Info.Usb_wLength2;return 0;}switch(vender_request){case 0x5f:return buf1;case 0x95:if (wValue0x2518){return buf2;} else if(wValue0x0706){return (u8 *)ch341_state; } }return 0;
}
RESULT Virtual_Com_Port_Data_Setup(u8 RequestNo)
{u8 *(*CopyRoutine)(u16);CopyRoutine NULL;if (RequestNo GET_LINE_CODING){if (Type_Recipient (CLASS_REQUEST | INTERFACE_RECIPIENT)){CopyRoutine Virtual_Com_Port_GetLineCoding;}}else if (RequestNo SET_LINE_CODING){if (Type_Recipient (CLASS_REQUEST | INTERFACE_RECIPIENT)){CopyRoutine Virtual_Com_Port_SetLineCoding;}Request SET_LINE_CODING;}else{vender_requestRequestNo;CopyRoutine Vender_Handle_CH341; }if (CopyRoutine NULL){return USB_UNSUPPORT;}pInformation-Ctrl_Info.CopyData CopyRoutine;pInformation-Ctrl_Info.Usb_wOffset 0;(*CopyRoutine)(0);return USB_SUCCESS;
}/*******************************************************************************
* Function Name : Virtual_Com_Port_NoData_Setup.
* Description : handle the no data class specific requests.
* Input : Request Nb.
* Output : None.
* Return : USB_UNSUPPORT or USB_SUCCESS.
*******************************************************************************/#define CH341_BAUDBASE_FACTOR 1532620800L
RESULT Virtual_Com_Port_NoData_Setup(u8 RequestNo)
{if (Type_Recipient (CLASS_REQUEST | INTERFACE_RECIPIENT)){if (RequestNo SET_COMM_FEATURE){return USB_SUCCESS;}else if (RequestNo SET_CONTROL_LINE_STATE){return USB_SUCCESS;}}else//CH341 specific{u16 wValue pInformation-USBwValues.w;u16 wIndex pInformation-USBwIndexs.w;static u32 baud_factor;static u8 divisor;change_byte(wValue);change_byte(wIndex);switch(RequestNo){case 0XA1:break;case CH341_REQ_WRITE_REG:switch(wValue){case 0x1312:baud_factor0x00ff;baud_factor|(wIndex0xff00);divisorwIndex0x03;break; case 0x0f2c:baud_factor0xff00;baud_factor|wIndex; break;} break; case 0xA4: ch341_state0xee9f;break;}return USB_SUCCESS; }return USB_UNSUPPORT;
}/*******************************************************************************
* Function Name : Virtual_Com_Port_GetDeviceDescriptor.
* Description : Gets the device descriptor.
* Input : Length.
* Output : None.
* Return : The address of the device descriptor.
*******************************************************************************/
u8 *Virtual_Com_Port_GetDeviceDescriptor(u16 Length)
{return Standard_GetDescriptorData(Length, Device_Descriptor);
}/*******************************************************************************
* Function Name : Virtual_Com_Port_GetConfigDescriptor.
* Description : get the configuration descriptor.
* Input : Length.
* Output : None.
* Return : The address of the configuration descriptor.
*******************************************************************************/
u8 *Virtual_Com_Port_GetConfigDescriptor(u16 Length)
{return Standard_GetDescriptorData(Length, Config_Descriptor);
}/*******************************************************************************
* Function Name : Virtual_Com_Port_GetStringDescriptor
* Description : Gets the string descriptors according to the needed index
* Input : Length.
* Output : None.
* Return : The address of the string descriptors.
*******************************************************************************/
u8 *Virtual_Com_Port_GetStringDescriptor(u16 Length)
{u8 wValue0 pInformation-USBwValue0;if (wValue0 4){return NULL;}else{return Standard_GetDescriptorData(Length, String_Descriptor[wValue0]);}
}/*******************************************************************************
* Function Name : Virtual_Com_Port_Get_Interface_Setting.
* Description : test the interface and the alternate setting according to the
* supported one.
* Input1 : u8: Interface : interface number.
* Input2 : u8: AlternateSetting : Alternate Setting number.
* Output : None.
* Return : The address of the string descriptors.
*******************************************************************************/
RESULT Virtual_Com_Port_Get_Interface_Setting(u8 Interface, u8 AlternateSetting)
{if (AlternateSetting 0){return USB_UNSUPPORT;}else if (Interface 1){return USB_UNSUPPORT;}return USB_SUCCESS;
}/*******************************************************************************
* Function Name : Virtual_Com_Port_GetLineCoding.
* Description : send the linecoding structure to the PC host.
* Input : Length.
* Output : None.
* Return : Inecoding structure base address.
*******************************************************************************/
u8 *Virtual_Com_Port_GetLineCoding(u16 Length)
{if (Length 0){pInformation-Ctrl_Info.Usb_wLength sizeof(linecoding);return NULL;}return(u8 *)linecoding;
}/*******************************************************************************
* Function Name : Virtual_Com_Port_SetLineCoding.
* Description : Set the linecoding structure fields.
* Input : Length.
* Output : None.
* Return : Linecoding structure base address.
*******************************************************************************/
u8 *Virtual_Com_Port_SetLineCoding(u16 Length)
{if (Length 0){pInformation-Ctrl_Info.Usb_wLength sizeof(linecoding);return NULL;}return(u8 *)linecoding;
}三、测试 1.下载程序后USB连接 2.用串口自发自收测试