首页 > 其他分享 >STM32单片机芯片与内部75 USB虚拟串口 标准库 HAL库 配置实现

STM32单片机芯片与内部75 USB虚拟串口 标准库 HAL库 配置实现

时间:2025-01-14 10:57:24浏览次数:3  
标签:NVIC HAL USB USART void STM32 USBD 串口 GPIO

目录

一、标准库工程

1、USB初始化

2、USB中断配置

3、中断服务函数与回调接收

4、USB连接

5、时钟配置

6、数据发送

二、HAL库工程

1、USB初始化

2、中断服务函数与回调接收

4、USB连接

5、时钟配置

6、数据发送


一、标准库工程

1、USB初始化

        由官方进行适配。

void USB_Init(void)
{
  pInformation = &Device_Info;
  pInformation->ControlState = 2;
  pProperty = &Device_Property;
  pUser_Standard_Requests = &User_Standard_Requests;
  /* Initialize devices one by one */
  pProperty->Init();
}

2、USB中断配置

        配置了USB外部18中断,使能USB RX和WakeUp中断。

	NVIC_InitTypeDef NVIC_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;

 
	/* Configure the EXTI line 18 connected internally to the USB IP */
	EXTI_ClearITPendingBit(EXTI_Line18);
											  //  开启线18上的中断
	EXTI_InitStructure.EXTI_Line = EXTI_Line18; // USB resume from suspend mode
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;	//line 18上事件上升降沿触发
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure); 	 

	/* Enable the 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 the USB Wake-up interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = USBWakeUp_IRQn;   //组2,优先级最高	
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_Init(&NVIC_InitStructure);   

3、中断服务函数与回调接收

        以收到\r\n作为结束。

void EP3_OUT_Callback(void)
{
	u16 USB_Rx_Cnt; 
	USB_Rx_Cnt = USB_SIL_Read(EP3_OUT, USB_Rx_Buffer);	//得到USB接收到的数据及其长度  
	USB_To_USART_Send_Data(USB_Rx_Buffer, USB_Rx_Cnt);	//处理数据(其实就是保存数据) 
	SetEPRxValid(ENDP3);								//时能端点3的数据接收
}
void USB_To_USART_Send_Data(u8* data_buffer, u8 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;
				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;//接收数据错误,重新开始接收	
				}					
			}
		}   
	}  
} 

4、USB连接

        先将enable置位0,延时一段时间后再置位1。

void USB_Port_Set(u8 enable)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);    //使能PORTA时钟		 
	if(enable)_SetCNTR(_GetCNTR()&(~(1<<1)));//退出断电模式
	else
	{	  
		_SetCNTR(_GetCNTR()|(1<<1));  // 断电模式
		GPIOA->CRH&=0XFFF00FFF;
		GPIOA->CRH|=0X00033000;
		PAout(12)=0;	    		  
	}
}

5、时钟配置

void Set_USBClock(void)
{
	RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);//USBclk=PLLclk/1.5=48Mhz	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);	 //USB时钟使能		 
} 

6、数据发送

        可以看到,通过配置buffer即可实现自动发送,同时循环执行即可实现发送长串字符。

//发送一个字节数据到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)//超过buf大小了,归零.
	{
		uu_txfifo.writeptr=0;
	} 
}
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]); 
	}
} 

二、HAL库工程

1、USB初始化

        由官方进行适配。

void MX_USB_DEVICE_Init(void)
{
	/* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */

	/* USER CODE END USB_DEVICE_Init_PreTreatment */

	/* Init Device Library, add supported class and start the library. */
	//1.初始化USBD,初始化设备栈和加载类驱动
	if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
	{
		Error_Handler();
	}
	//2.注册USB 类
	if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK)
	{
		Error_Handler();
	}
	//3.注册CDC接口
	if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK)
	{
		Error_Handler();
	}
	//4.启动USBD
	if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
	{
		Error_Handler();
	}

	/* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */

	/* USER CODE END USB_DEVICE_Init_PostTreatment */
}

2、中断服务函数与回调接收

        以收到\r\n作为结束。

int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
	/* USER CODE BEGIN 6 */
	//CDC_Transmit_FS(Buf,*Len);//串口回环
	USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
	USBD_CDC_ReceivePacket(&hUsbDeviceFS);
	USB_To_USART_Send_Data(Buf, *Len);
	return (USBD_OK);
	/* USER CODE END 6 */
}
void USB_To_USART_Send_Data(u8* data_buffer, u32 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;
				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;//接收数据错误,重新开始接收	
				}				
			}
		}   
	}  
}

4、USB连接

void USB_Reset()
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
 
    /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOA_CLK_ENABLE();
 
    /*Configure GPIO pin Output Level */
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11 | GPIO_PIN_12, GPIO_PIN_RESET);

    GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLDOWN;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	delay_us(700);//delay 10 ms
}

5、时钟配置

void Set_USBClock(void)
{
	RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);//USBclk=PLLclk/1.5=48Mhz	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);	 //USB时钟使能		 
} 

6、数据发送

        可以看到,通过配置buffer即可实现自动发送,同时循环执行即可实现发送长串字符。

void USB_To_USART_Send_Data(u8* data_buffer, u32 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;
				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;//接收数据错误,重新开始接收	
				}				
			}
		}   
	}  
} 

//发送一个字节数据到USB虚拟串口
void USB_USART_SendData(u8 *data)
{
	//等待数据发送完毕再发送下一个字节
	while((CDC_Transmit_FS(data,sizeof(*data)))==USBD_BUSY);
}
//usb虚拟串口的printf函数p
//确保一次发送数据不超USB_USART_REC_LEN字节
void USB_Printf(char* fmt,...)  
{  
	u16 i,len;
	va_list ap;
	va_start(ap,fmt);
	vsprintf((char*)USART_PRINTF_Buffer,fmt,ap);
	va_end(ap);
	len=strlen((const char*)USART_PRINTF_Buffer);//此次发送数据的长度
	for(i=0;i<len;i++)
	{
		USB_USART_SendData(&USART_PRINTF_Buffer[i]);
	}
	//CDC_Transmit_FS(USART_PRINTF_Buffer,len);
}

标签:NVIC,HAL,USB,USART,void,STM32,USBD,串口,GPIO
From: https://blog.csdn.net/qq_39376872/article/details/144498215

相关文章

  • STM32单片机芯片与内部74 USB 简介 控制器 通用寄存器 端点寄存器 缓冲区描述表
    目录一、USB简介二、STM32USB控制器三、通用寄存器1、USB控制寄存器(USB_CNTR)2、USB中断状态寄存器(USB_ISTR)3、USB帧编号寄存器(USB_FNR)5、USB设备地址寄存器(USB_DADDR)6、USB分组缓冲区描述表地址寄存器(USB_BTABLE)四、端点寄存器1、USB端点n寄存器(USB_EP......
  • 【江协STM32】11-2/3 W25Q64简介、软件SPI读写W25Q64
    1.W25Q64简介W25Qxx系列是一种低成本、小型化、使用简单的非易失性存储器,常应用于数据存储、字库存储、固件程序存储等场景存储介质:NorFlash(闪存)时钟频率:80MHz/160MHz(DualSPI)/320MHz(QuadSPI)存储容量(24位地址):   W25Q40:    4Mbit/512KByte   W2......
  • 基于STM32C6T6的智能小车设计:自动寻迹、避障与无线控制全解析(含有源码资料)
    一、设计要求:1.1功能要求:设计并制作一个基于STM32C6T6核心板的智能小车,具备自动寻迹、避障和无线控制功能。小车应能够沿着不规则的黑色轨迹行驶,遇到障碍物时能够自动绕行,并可通过蓝牙模块进行无线控制。自动寻迹:小车应能够沿着不规则的黑色轨迹行驶,根据五路灰度循迹模块的......
  • 《STM32开发:深入解析 TIM2->CCR2 与 TIM2.CCR2 的区别与应用》
    前言在最初学习STM32的过程中,由于知识不进脑子,经常边学边忘,并且C语言学习的也比较浅,涉及到指针地址等方面的知识,内心就有点排斥。第一次遇到->和.这两种操作符时,我只是知道按照示例“照着用”,但并不清楚它们之间的具体区别,也没有深入理解它们的内在逻辑。这样的学习方......
  • STM32之LWIP网络通讯设计-下(十五)
    STM32F407系列文章-ETH-LWIP(十五)目录前言一、软件设计二、CubeMX实现1.配置前准备2.CubeMX配置1.ETH模块配置2.时钟模块配置3.中断模块配置4.RCC及SYS配置5.LWIP模块配置3.生成代码1.main文件2.用户层源文件3.用户层头文件4.效果演示三、移植实现总结......
  • 基于STM32F103标准库实现FFT,并实现音乐频谱绘制
    整个工程文件是在江科大的OLED显示屏OLED-V2.0版本IIC四针脚接口UTF-8的工程上编写的,在屏幕显示过程中,只用到了OLED显示屏的绘制直线和绘制像素点两个函数(注意,显示屏的绘制函数坐标可以任意指定,而不是按页写入。任一屏幕只要有上述两个函数均可使用。工程接线:STM32F103C8T6......
  • 【江协STM32】11-1 SPI通信协议
    SPI(SerialPeripheralInterface)是由Motorola公司开发的一种通用数据总线四根通信线:SCK(SerialClock)、MOSI(MasterOutputSlaveInput)、MISO(MasterInputSlaveOutput)、SS(SlaveSelect)同步,全双工支持总线挂载多设备(一主多从)         1. 硬件电路所有SPI设......
  • STM32 HAL库函数入门指南:从原理到实践
    1STM32HAL库概述STM32HAL(HardwareAbstractionLayer)库是ST公司专门为STM32系列微控制器开发的一套硬件抽象层函数库。它的核心设计理念是在应用层与硬件层之间建立一个抽象层,这个抽象层屏蔽了底层硬件的具体实现细节,为开发者提供了一套统一的、标准化的应用程序接口(API)......
  • half hour
    Theytakeahalfhourtocallindetectives.他们花了半个小时叫侦探。tookalmostahalfhour.花了差不多半个小时。I'mgettingcallsfromNewYorkeveryhalfhour.我每半小时就会接到纽约的电话。 Westillhavetwoandhalfhoursleftuntilourdate.离约会还......
  • STM32中的内存映射
     STM32中的内存映射在STM32中,内存映射通常如下:Flash:存储.text段(代码)、.rodata段(只读数据)和.data段的初始值。RAM:存储.data段(运行时)、.bss段、栈和堆。4. 程序启动过程在STM32中,程序启动时会发生以下操作:从Flash中加载.data段的初始值到RAM。将.bss......