STM32F103C8 虚拟串口移植实验(1)_#include "usb_lib.h-程序员宅基地

技术标签: stm32  usb  虚拟串口  STM32学习笔记  

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]);
	}
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u012292754/article/details/102620987

智能推荐

tc275单片机的内核_英飞凌TC275_bootloader源码 TC275单片机基于autosar的bootloader工程代码(Bootloader engineering code of tc...-程序员宅基地

文章浏览阅读1.4k次。压缩包 : f9a27655e546fd0d4bf5ed97eda6479f.zip 列表英飞凌TC275_bootloader源码/英飞凌TC275_bootloader源码/.cproject英飞凌TC275_bootloader源码/.htcproject英飞凌TC275_bootloader源码/.project英飞凌TC275_bootloader源码/.settings/英飞凌TC27..._英飞凌tc275芯片bootloader开发

SimpleFOC(三)—— AS5600角度读取_as5600磁编码器中文手册-程序员宅基地

文章浏览阅读3.2w次,点赞25次,收藏137次。目录一、硬件介绍1、磁编码器说明:2、硬件连接二、程序演示1、模拟电压获取角度2、I2C通信获取角度三、程序拓展一、硬件介绍1、磁编码器说明:  ◆AS5600与两极磁铁配对,可以输出12位分辨率的磁性旋转位置,支持IIC通信,还可以输出模拟电压和PWM信号。官方例程中主要演示了模拟电压和IIC通信两种角度获取方式。  ◆模拟电压模式,Aout引脚输出0—5V对应0°—360°,  ◆I2C模式,读取0x0C/0x0D两个寄存器,获取12bits的角度值,0—4096对应0°—360°,2_as5600磁编码器中文手册

Windows恢复Grub引导,用grub安装ubuntu-程序员宅基地

文章浏览阅读86次。http://www.linuxidc.com/wap.aspx?nid=18027&p=&cp=&cid=http://m.blog.chinaunix.net/uid-22197900-id-359250.htmlhttp://zhidao.baidu.com/question/147900468.html?fr=ala&word=Grub%20%E5%AE..._在windowa 修复grub 引导

lua游戏代码_在游戏中如何使用LUA脚本语言_lua如何用一段代码在游戏屏幕上添加一个按钮-程序员宅基地

文章浏览阅读3.6k次。当你希望在你的游戏开始的时候读取一些信息,以配置你的游戏,这些信息通常都是放到一个文本文件中,在你的游戏启动的时候,你需要打开这个文件,然后解析字符串,找到所需要的信息。或许你认为这样就足够了,为什么还要使用Lua呢?应用于“配置”这个目的,Lua提供给你更为强大,也更为灵活的表达方式,在上一种方式中,你无法根据某些条件来配置你的游戏,Lua提供给你灵活的表达方式,你可以类似于这样来配置你的游戏:ifplayer:is_dead()then_lua如何用一段代码在游戏屏幕上添加一个按钮

LINUX下MATLAB MEX编译的问题_matlab mex编译linux-程序员宅基地

文章浏览阅读3.8k次。最近跑一个程序,是matlab和c混合编程的,而且调用了一些Linux下特有的库文件,所以只能在linux下运行。但是ubuntu里安装的Matlab r2013a 出现了gcc版本问题。matlab r2013a只支持gcc4.4, 而ubuntu的gcc已经更新到4.8.2所以为了方便,只好安装4.4版的编译器, 包括gcc, g++, gfortran安装命令_matlab mex编译linux

序列化和反序列化_使用反序列化的 readobject() 方法-程序员宅基地

文章浏览阅读348次。1.概念:序列化: 将数据结构或对象转换成二进制串的过程。反序列化:将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程。只有实现了Serializable或Externalizable接口的类的对象才能被序列化,否则抛出异常2:为什么要序列化和反序列化我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二_使用反序列化的 readobject() 方法

随便推点

51单片机之数码管_0x3f,0x06-程序员宅基地

文章浏览阅读5k次,点赞4次,收藏13次。1.静态数码管原理图LED数码管根据LED的不同接法分为两类:共阴和共阳_0x3f,0x06

计算机组成原理脱机运算器实验数据,实验三:脱机运算器实验报告.pdf-程序员宅基地

文章浏览阅读841次。大连理工大学大连理工大学 本科实验报告本科实验报告 课程名称 计算机组成原理实验 学院 系 软件学院 专 业 软件工程 班 级 0907 英 学 号 200892497 学生姓名 刘云伟 2011 年 3 月 31 日 大连理工大学实验报告大连理工大学实验报告 学院 系 软件学院 专业 软件工程 班级 0907 英 姓 名 刘云伟 学号 200892497 实验台 21 实验时间 2011 3 3..._脱机运算器实验结果表格

自适应大邻域算法(ALNS)求解TSP问题,golang实现_alns tsp-程序员宅基地

文章浏览阅读489次,点赞12次,收藏6次。自适应大邻域搜索算法(Adaptive Large Neighborhood Search , ALNS)_alns tsp

form做表单验证时,填写了正确的数值但是依旧一直提示为空。_form.validate( 输入的值会被设置为空-程序员宅基地

文章浏览阅读2.6k次。定义验证规则时,rule和model绑定的属性值必须是一样的_form.validate( 输入的值会被设置为空

2022-2028年中国甘油磷脂酰胆碱(GPC)行业市场发展模式及投资规划分析报告-程序员宅基地

文章浏览阅读170次。报告类型:产业研究报告格式:电子版、纸介版、电子+纸介出品单位:智研咨询-产业信息网智研咨询发布的《2022-2028年中国甘油磷脂酰胆碱(GPC)行业市场发展模式及投资规划分析报告》共十五章。首先介绍了甘油磷脂酰胆碱(GPC)行业市场发展环境、甘油磷脂酰胆碱(GPC)整体运行态势等,接着分析了甘油磷脂酰胆碱(GPC)行业市场运行的现状,然后介绍了甘油磷脂酰胆碱(GPC)市场竞争格局。随后,报告对甘油磷脂酰胆碱(GPC)做了重点企业经营状况分析,最后分析了甘油磷脂酰胆碱(GPC)行业发展趋...

组蛋白修饰化合物库 | 药物筛选 | MCE-程序员宅基地

文章浏览阅读275次,点赞3次,收藏10次。MCE提供人内源性代谢物库,包括971个生物活性化合物,用于研究代谢组学和代谢相关药物开发。产品以溶液或粉末包装提供,具有多种浓度选择。化合物经临床前和临床试验验证,具有药用活性和细胞渗透性,是研究组蛋白修饰调控及相应疾病的有用工具。