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做虚拟串口的回调功能

功能演示

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

cat_milk

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

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

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

打赏作者

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

抵扣说明:

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

余额充值