STM32 USB-CDC实现虚拟串口

STM32Cubemx 配置

1.打开一个usb设备勾选为从设备
在这里插入图片描述
2.在这里选择CDC选项
在这里插入图片描述

代码

  • 添加环形缓冲区

/**  环形缓冲区驱动文件
*  
*
*
*
*
*/

#include "driver_buffer.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

/* 初始化环形缓冲区 */

RingBuffer USERRxDataBuffer1;
RingBuffer USERRxDataBuffer2;
RingBuffer USERRxDataBuffer3;

int Driver_Buffer_Init(ptRingBuffer buffer,uint16_t size)
{
	if(buffer == NULL||size == 0 ) return  -1; /* 判断合法性 */
	if(buffer->fifo == NULL)                   /* 判断是否为内存大小空*/
	{
		buffer->fifo =(uint8_t*)malloc(size);  /* 动态分配内存 */
		if(buffer->fifo == NULL)
		{
		  printf("Malloc %d bytes failed.\r\n", size);
            return -1;
		}
	} 
	buffer->pw = buffer->pr = 0;               
    buffer->buf_size = size;                   
	return 0;
}

/* 环形缓冲区写一个字节 */

int Driver_Buffer_Write(ptRingBuffer buffer,const uint8_t data)
{
	if(buffer == NULL || buffer->fifo == NULL ) return  -1; /* 判断合法性 */
	int i = (buffer->pw + 1)%buffer->buf_size;            
	if(i != buffer->pr)                   /* 判断是否写满 */                           
	{
		buffer->fifo[buffer->pw] = data;       /* */
		buffer->pw = i;                        /* 重置写指针 */   
		return 0;
	}
	
	 return -1;
}

/* 环形缓冲区写多个字节 */
int Driver_Buffer_WriteBytes(ptRingBuffer buffer,const uint8_t *data_stream,uint8_t len)
{
	int i;
	if(buffer == NULL || buffer->fifo == NULL ) return  -1; /* 判断合法性 */
	if(data_stream == NULL||len == 0 ) return -1;
	for(i = 0;i<len ;i++ )
	{
        if(Driver_Buffer_Write(buffer, data_stream[i]) != 0)    break;
    }
	return i;
}


/* 环形缓冲区 读一个字节 */
int Driver_Buffer_Read(ptRingBuffer buffer,uint8_t *data)
{
	if(buffer == NULL || buffer->fifo == NULL ) return  -1; /* 判断合法性 */
	if(data == NULL) return -1;
	if(buffer->pr == buffer->pw ) return -1;                /* 满 */
	
	*data = buffer ->fifo[buffer->pr];
	buffer ->pr =(buffer ->pr+1)%buffer ->buf_size ;    /* 自增 */
	return 0;
	
}

/* 环形缓冲区 读多个字节 */
int Driver_Buffer_ReadBytes(ptRingBuffer buffer,uint8_t *data_stream,uint8_t len)
{
	int i = 0;
	if(buffer == NULL || buffer->fifo == NULL ) return  -1; /* 判断合法性 */
	if(data_stream == NULL || len == 0) return -1;
	for(i = 0; i<len; i++)
    {
        if(Driver_Buffer_Read(buffer, &data_stream[i]) != 0)    break;
    }
	 return i;
}

/*  清空环形缓冲区 */
int Driver_Buffer_Clean(ptRingBuffer buffer)
{
	if(buffer == NULL || buffer->fifo == NULL ) return  -1; /* 判断合法性 */
	memset(buffer->fifo,0,buffer->buf_size);                /* 清空 */
	buffer->pr = buffer->pw = 0;                              /* 归零 */
	return 0;
}

/**
 * @brief 更新数据到数组
 * @param buffer 
 * @param data_stream 
 * @return 返回更新的数据长度
 */
int Driver_Buffer_RefreshData(ptRingBuffer buffer,uint8_t *data_stream)
{
    uint16_t len=0;
    if(buffer->pw == buffer->buf_size)
        buffer->pw = 0;

    while(buffer->pw != buffer->pr)
    {
        data_stream[len++] = buffer ->fifo[buffer->pr];
        buffer ->fifo[buffer->pr] = 0;
        buffer->pr++;
        if(buffer->pr >= buffer->buf_size)
            buffer->pr = 0;
        if(len >= buffer->buf_size)
            break;
    }
    return len;

}

#ifndef __DRIVER_BUFFER_H
#define __DRIVER_BUFFER_H
#include "main.h"
typedef struct{
	uint8_t *fifo;
	uint16_t pw; /*写地址*/
	uint16_t pr;
	uint16_t buf_size;
	
}RingBuffer,*ptRingBuffer;

extern RingBuffer USERRxDataBuffer1;
extern RingBuffer USERRxDataBuffer2;
extern RingBuffer USERRxDataBuffer3;

/* 初始化环形缓冲区 */

int Driver_Buffer_Init(ptRingBuffer buffer,uint16_t size);

/* 环形缓冲区写一个字节 */


int Driver_Buffer_Write(ptRingBuffer buffer,const uint8_t data);

/* 环形缓冲区写多个字节 */
int Driver_Buffer_WriteBytes(ptRingBuffer buffer,const uint8_t *data_stream,uint8_t len);

/* 环形缓冲区 读一个字节 */
int Driver_Buffer_Read(ptRingBuffer buffer,uint8_t *data);

/* 环形h缓冲区 读多个字节 */
int Driver_Buffer_ReadBytes(ptRingBuffer buffer,uint8_t *data_stream,uint8_t len);

/*  清空环形缓冲区 */
int Driver_Buffer_Clean(ptRingBuffer buffer);

int Driver_Buffer_RefreshData(ptRingBuffer buffer,uint8_t *data_stream);





#endif



usbd_cdc_if.c文件中个更新环形缓冲区的写入在这里插入图片描述

在main.c 中初始化环形缓冲区
在这里插入图片描述
然后添加以下的代码

if(USERRxDataBuffer1.pr!=USERRxDataBuffer1.pw)
{
	CDC_Tx_Lenth = abs(USERRxDataBuffer1.pw-USERRxDataBuffer1.pr);
    Driver_Buffer_ReadBytes(&USERRxDataBuffer1,USB_CDC_RxData,CDC_Tx_Lenth);
	
    CDC_Transmit_HS(USB_CDC_RxData,CDC_Tx_Lenth);
	memset(USB_CDC_RxData,0,sizeof(USB_CDC_RxData));
}

则实现了USB做虚拟串口的回调功能

功能演示

在这里插入图片描述

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
是的,STM32F429上的USB OTG接口可以通过使用USB CDC(Communication Device Class)协议来实现虚拟串口功能。 通过将USB OTG接口配置为USB CDC设备,可以在STM32F429上创建一个虚拟串口,使其在计算机上显示为串口设备。这样,你就可以通过USB连接将STM32F429与计算机进行通信,并像使用普通串口一样发送和接收数据。 要在STM32F429上配置USB OTG接口为虚拟串口,请按照以下步骤进行: 1. 打开RT-Thread的配置文件(`rtconfig.h`),确保以下宏定义被启用: ```c #define RT_USING_USB_DEVICE #define RT_USB_DEVICE_CDC ``` 2. 在应用程序的初始化函数中,调用以下函数来创建虚拟串口设备: ```c #include <rtthread.h> #include <usb_device_cdc.h> int app_init(void) { /* 创建虚拟串口设备 */ struct rt_usb_cdc_device *cdc; cdc = rt_usb_cdc_device_create("cdc", RT_NULL); if (cdc == RT_NULL) { rt_kprintf("Failed to create CDC device"); return -RT_ERROR; } return RT_EOK; } ``` 3. 在RT-Thread的配置文件(`rtconfig.h`)中,你可以根据需要对虚拟串口设备进行配置,例如设置波特率、缓冲区大小等。 4. 编译和下载你的应用程序到STM32F429开发板中,并在启动后,虚拟串口设备将被创建并可以使用。 需要注意的是,使用USB OTG作为虚拟串口时,你需要在计算机上安装对应的串口驱动程序,并将其与STM32F429连接起来。此外,还需要根据具体的应用需求配置和使用USB CDC设备。 确保参考RT-Thread和USB设备驱动的文档以获取更详细的指导。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cat_milk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值