STM32F103C8 虚拟串口移植实验(1)

1 虚拟串口移植

  • 项目新建 USB 文件夹,将USB 驱动拷贝过来
    在这里插入图片描述
    在这里插入图片描述

  • 从官方案例的 src,inc拷贝以下文件
    在这里插入图片描述

2 添加分组和头文件

  • 新建分组
    在这里插入图片描述
    在这里插入图片描述

  • 添加头文件目录
    在这里插入图片描述


3 修改 platform_config.h

  • 去掉红色框部分,添加如图的头文件
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 注释掉这里
    在这里插入图片描述

4 修改 hw_config.c

先编译

  • 注释掉 #include "stm32_it.h"
  • 添加如下的头文件
#include "usb_lib.h"
#include "usb_prop.h"
#include "usb_desc.h"
#include "usb_istr.h"
#include "hw_config.h"
#include "usb_pwr.h"
#include "usart.h"
#include "string.h"
#include "stdarg.h"
#include "stdio.h"

  • 去掉
    在这里插入图片描述
  • 添加
_usb_usart_fifo uu_txfifo; // usb串口发送FIFO结构体,在 hw_config.h 定义
u8 USART_PRINTF_Buffer[USB_USART_REC_LEN]; // usb printf 发送缓冲区
u8 USB_USART_RX_BUF[USB_USART_REC_LEN]; // 接收缓冲区

//接收状态
// bit15--接收完成标志
// bit14--接收到 0x0d
// bit13~0--接收到的有效字节的数目
u16 USB_USART_RX_STA = 0;
extern LINE_CODING linecoding; // usb虚拟串口配置信息(波特率、位数等),usb_prop.c 定义

在这里插入图片描述


  • hw_config.h 添加
#define USB_USART_TXFIFO_SIZE	1024 // USB虚拟串口发送FIFO大小
#define USB_USART_REC_LEN			200 // 接收缓冲区的最大字节

//定义一个USB USART FIFO 结构体
typedef struct
{
	u8 buffer[USB_USART_TXFIFO_SIZE];
	vu16 writeptr; // 写指针
	vu16 readptr; // 读指针
}_usb_usart_fifo;

extern _usb_usart_fifo uu_txfifo;

  • 删除 void Set_System(void) 函数
  • 添加函数
void USBWakeUp_IRQHandler(void)
{
	EXTI_ClearITPendingBit(EXTI_Line18); // 清除 USB 唤醒中断挂起位
}

// USB 中断处理
void USB_LP_CAN1_RX0_IRQHandler(void)
{
	USB_Istr();
}

  • 修改 void Set_USBClock(void)
void Set_USBClock(void)
{
  /* Select USBCLK source */
  RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5); // USB-48MHz
  /* Enable the USB clock */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
}


  • 修改 void Enter_LowPowerMode(void) 函数
void Enter_LowPowerMode(void)
{
	printf("usb enter low power mode\r\n");
  /* Set the device state to suspend */
  bDeviceState = SUSPENDED; // bDeciceState 记录 USB 连接状态, usb_pwr.c 定义
}

  • 修改 void Leave_LowPowerMode(void) 函数
void Leave_LowPowerMode(void)
{
  DEVICE_INFO *pInfo = &Device_Info;

	printf("leave low power mode\r\n");
  /* Set the device state to the correct state */
  if (pInfo->Current_Configuration != 0)
  {
    /* Device configured */
    bDeviceState = CONFIGURED;
  }
  else
  {
    bDeviceState = ATTACHED;
  }
  
  /*Enable SystemCoreClock*/
  //SystemInit();
}

  • 修改 void USB_Interrupts_Config(void) 函数
void USB_Interrupts_Config(void)
{
	NVIC_InitTypeDef NVIC_InitStructure; 
	EXTI_InitTypeDef EXTI_InitStructure;
	
	EXTI_ClearITPendingBit(EXTI_Line18);// 开启线 18 中断
	
	EXTI_InitStructure.EXTI_Line = EXTI_Line18;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);
	
	//enable usb interrupt
	NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; //组2,优先级次之
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	// enable usb wake-up interrupt
	NVIC_InitStructure.NVIC_IRQChannel = USBWakeUp_IRQn; // 组2,优先级最高
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_Init(&NVIC_InitStructure);
	
}

  • 修改 void USB_Cable_Config (FunctionalState NewState) 函数
// NewState: DISABLE,不上拉; ENABLE,上拉;
void USB_Cable_Config (FunctionalState NewState)
{
	if(NewState != DISABLE)
		printf("usb pull up enable\r\n");
	else
		printf("usb pull up disable\r\n");
}

  • 删除 void USART_Config_Default(void) 函数
  • 添加 USB_Port_Set(u8 enable) 函数
void USB_Port_Set(u8 enable)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	if(enable)
	{
		_SetCNTR(_GetCNTR() & (~(1<<1))); // 退出断电模式
	}else{
		_SetCNTR(_GetCNTR() | (1<<1)); // 断电模式
		GPIOA -> CRH &= 0xFFF00FFF;
		GPIOA -> CRH |= 0x00033000;
		PAout(12) = 0;
	}
}

  • 修改 bool USART_Config(void) 函数
// USB COM 口的配置信息打印
bool USART_Config(void)
{
	uu_txfifo.readptr = 0; // 清空读指针
	uu_txfifo.writeptr = 0; 
	USB_USART_RX_STA = 0;
	
	printf("linecoding.format: %d\r\n",linecoding.format);
	printf("linecoding.paritytype: %d\r\n",linecoding.paritytype);
	printf("linecoding.datatype: %d\r\n",linecoding.datatype);
	printf("linecoding.bitrate: %d\r\n",linecoding.bitrate);
	
	return (TRUE);
}


  • 修改 void USB_To_USART_Send_Data(uint8_t* data_buffer, uint8_t Nb_bytes) 函数
// 处理从 USB 虚拟串口接收到的数据
void USB_To_USART_Send_Data(uint8_t* data_buffer, uint8_t Nb_bytes)
{
	u8 i; 
	u8 res;
	for(i = 0;i < Nb_bytes; i++)
	{
		res = data_buffer[i];
		if((USB_USART_RX_STA & 0x8000) == 0) // 接收未完成
		{
			if(USB_USART_RX_STA & 0x4000) // 接收到了 0x0d
			{
				if(res != 0x0a) USB_USART_RX_STA = 0; // 错误,重新开始
				else USB_USART_RX_STA |= 0x8000; // 接收完成
			}else{ // 还没收到 0x0d
				if(res == 0x0d) USB_USART_RX_STA |= 0x4000; // 标记接收到了 0x0d
				else{
					USB_USART_RX_BUF[USB_USART_RX_STA & 0x3FFF] = res;
					USB_USART_RX_STA++;
					if(USB_USART_RX_STA > (USB_USART_REC_LEN-1))
						USB_USART_RX_STA = 0;// 错误,重传
				}
			}
		}
	}
}

  • 删除 Handle_USBAsynchXferUSART_To_USB_Send_Data 这两个函数;
  • 新增 USB_USART_SendData 函数,用于虚拟串口发送一个字节数据到 USB(实际上只是写到了发送 FIFO,最终还是由 EP1_IN_Callback 函数实现输出给 USB)
void USB_USART_SendData(u8 data)
{
	uu_txfifo.buffer[uu_txfifo.writeptr] = data;
	uu_txfifo.writeptr++;
	if(uu_txfifo.writeptr == USB_USART_TXFIFO_SIZE)
	{
		uu_txfifo.writeptr = 0;
	}
}

  • 删除 IntToUnicode 函数前面的 static, 在 hw_config.h 中声明这个函数
  • 新增 usb_printf 函数,实现 USB 虚拟串口的 printf
// USB 虚拟串口 printf 函数
// 确保一次发送数据不超过 USB_USART_REC_LEN 字节
void usb_printf(char *fmt,...)
{
	u16 i,j;
	va_list ap;
	va_start(ap,fmt);
	vsprintf((char*) USART_PRINTF_Buffer,fmt,ap);
	va_end(ap);
	i = strlen((const char*) USART_PRINTF_Buffer); // 此次发送数据长度
	for(j=0;j<i;j++)
	{
		USB_USART_SendData(USART_PRINTF_Buffer[j]);
	}
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值