语音模块学习——LSYT201B模组(实际操作篇)

目录

一、定制词条

二、直接用串口通信

三、使用单片机通信


理论篇在这,依旧是深圳雷龙发展的语音模块。

http://t.csdnimg.cn/2SzJL

一、定制词条

因为我想后面加到我的毕设上加个语音模块,所以定制的词条都是和芯测相关的。

动作词条播报串口输出(9600)
开机播报
10S自动退出唤醒有需要再叫我
唤醒词你好小龙我在FE 04 00 00 02 FD
命令词录制音频开始录制FE 04 00 01 03 FD
播放音频开始播放FE 04 00 02 04 FD
显示红色显示红色FE 04 00 03 05 FD
显示多色显示多色FE 04 00 04 06 FD
调节背光调节背光FE 04 00 05 07 FD
时钟测试开始测试FE 04 00 06 08 FD
四八五测试开始测试FE 04 00 07 09 FD
看测试开始测试FE 04 00 08 0A FD
按键测试开始测试FE 04 00 09 0B FD
查看温度查看温度FE 04 00 0A 0C FD
开始网络通信开始网络通信FE 04 00 0B 0D FD
关闭网络通信关闭网络通信FE 04 00 0C 0E FD
关闭显示器关闭显示器FE 04 00 0D 0F FD
打开显示器打开显示器FE 04 00 0E 10 FD
查看环境温度查看环境温度FE 04 00 0F 11 FD
查看环境湿度查看环境湿度FE 04 00 10 12 FD
查看当前位置查看单签位置FE 04 00 11 13 FD
前进前进FE 04 00 12 14 FD
后退后退FE 04 00 13 15 FD
停止停止FE 04 00 14 16 FD

二、直接用串口通信

 

起始码长度方向动作IDSUM结束码
0xFE0x040x000xXX0xXX0xFD

和技术人员沟通电源最好用5V的供电,我直接接串口用PC做了下测试

        因为这个接线柱是2.0的所以不能直接用杜邦线,杜邦线是2.54的。所欲我就扒了个皮给他焊上了,防止不同接线柱之间连电,这里需要保留一部分塑料。

        

        随便测了几个指令这里拾音度是真的高很灵敏。比我之前做的那个灵敏。但是还是那个缺点,不能自己改语音指令有点难受。

        为了低功耗,所以这类语音模块都是那种唤醒词形式的。像咱们的手机小爱同学,hi,Siri等等这种,我的这个叫你好小龙。

        总体来说可定制化很高比那种自己可以拿SDK烧写的要高很多,缺点是没SDK。

        音量的调节也比较麻烦需要修改电阻的大小。具体怎么修改到时候可以问技术人员

大概就是修改这两个电阻。 

三、使用单片机通信

        重点来咯,怎么用单片机实现,之前想着用I.MAX6ULL来着,但是我现在没时间,就用经典c8t6来做个demo吧。很好一年没写32的程序了已经忘的差不多了哈哈。

        先说说思路,初始化串口1和串口2.串口2接我们的模块,接收到指令后分析一下转化成对应语句打印到串口1很简单的程序,为什么不真的来控制一下呢,还是那句话,没时间。c8t6最小系统没有板载传感器,连灯泡也就一个。难受的很我要自己焊接,属实麻烦嘿嘿。各位读者朋友见谅哈。作者要做毕设,时间紧任务重呀,用韦东山老师的板子本来以为有移植好的鸿蒙和驱动,我只做服务器客户端还有通信就可用呢。但是被骗了,裸机写的驱动程序,和鸿蒙没有一毛钱关系。我要开发14个驱动程序还要学习鸿蒙应用层开发,以及最难的。把鸿蒙移植到I.MAX6ULL上。所以木有办法咯,抱歉抱歉后面有机会再来好好写写怎么用语音模块。

 下面是串口2的驱动程序,基于标准库的,为什么叫ESP8266因为我懒所以拿那个代码改的哈哈。

/* 函数体 --------------------------------------------------------------------*/
/**
  * 函数功能: 初始化ESP8266用到的GPIO引脚
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
static void ESP8266_GPIO_Config ( void )
{
	/*定义一个GPIO_InitTypeDef类型的结构体*/
	GPIO_InitTypeDef GPIO_InitStructure;

	/* 配置 CH_PD 引脚*/
	RCC_APB2PeriphClockCmd( ESP8266_RST_CLK, ENABLE ); 	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	
	/* 配置 RST 引脚*/									   
	GPIO_InitStructure.GPIO_Pin = ESP8266_RST_PIN;
	GPIO_Init ( ESP8266_RST_PORT, & GPIO_InitStructure );		
  
  /* 拉高WiFi模块的复位重启引脚	*/
  GPIO_ResetBits( ESP8266_RST_PORT, ESP8266_RST_PIN );
  
}

/**
  * 函数功能: 配置 ESP8266 USART 的 NVIC 中断优先级
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
static void ESP8266_USART_NVIC_Configuration ( void )
{
	NVIC_InitTypeDef NVIC_InitStructure; 	
	
	/* Configure the NVIC Preemption Priority Bits */  
	NVIC_PriorityGroupConfig ( NVIC_PriorityGroup_2 );

	/* Enable the USART2 Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = ESP8266_USART_IRQ;	 
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

}

/**
  * 函数功能: 初始化ESP8266用到的 USART
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
static void ESP8266_USART_Config ( void )
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;	
	
	/* config USART clock */
	ESP8266_USART_APBxClock_FUN ( ESP8266_USART_CLK, ENABLE );
	ESP8266_USART_GPIO_APBxClock_FUN ( ESP8266_USART_GPIO_CLK | RCC_APB2Periph_AFIO, ENABLE );
	
	/* USART GPIO config */
	/* Configure USART Tx as alternate function push-pull */
	GPIO_InitStructure.GPIO_Pin =  ESP8266_USART_TX_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(ESP8266_USART_TX_PORT, &GPIO_InitStructure);  
  
	/* Configure USART Rx as input floating */
	GPIO_InitStructure.GPIO_Pin = ESP8266_USART_RX_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(ESP8266_USART_RX_PORT, &GPIO_InitStructure);
	
	/* USART1 mode config */
	USART_InitStructure.USART_BaudRate = ESP8266_USART_BAUD_RATE;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(ESP8266_USARTx, &USART_InitStructure);
	
	/* 中断配置 */
	USART_ITConfig ( ESP8266_USARTx, USART_IT_RXNE, ENABLE ); //使能串口接收中断 
	USART_ITConfig ( ESP8266_USARTx, USART_IT_IDLE, ENABLE ); //使能串口总线空闲中断 	

	ESP8266_USART_NVIC_Configuration();	
	
	USART_Cmd(ESP8266_USARTx, ENABLE);	
  
  /* 清除发送完成标志 */
	USART_ClearFlag(ESP8266_USARTx, USART_FLAG_TC|USART_FLAG_TXE|USART_FLAG_RXNE);
}

/**
  * 函数功能: 格式化输出,类似于C库中的printf,但这里没有用到C库
  * 输入参数: USARTx 串口通道,这里只用到了串口2,即USART2
  *		        Data   要发送到串口的内容的指针
  *			      ...    其他参数
  * 返 回 值: 无
  * 说    明:典型应用 USART2_printf( USART2, "\r\n this is a demo \r\n" );
  *            		     USART2_printf( USART2, "\r\n %d \r\n", i );
  *            		     USART2_printf( USART2, "\r\n %s \r\n", j );
  */
void USART_printf(USART_TypeDef * USARTx, char * Data, ... )
{
	const char *s;
	int d;   
	char buf[16];
	
	va_list ap;
	va_start(ap, Data);
	while ( * Data != 0 )     // 判断是否到达字符串结束符
	{				                          
		if ( * Data == 0x5c )  //'\'
		{									  
			switch ( *++Data )
			{
				case 'r':							          //回车符
					USART_SendData(USARTx, 0x0d);
					Data ++;
				break;
				case 'n':							          //换行符
					USART_SendData(USARTx, 0x0a);	
					Data ++;
				break;
				default:
					Data ++;
				break;
			}			 
		}
		else if ( * Data == '%')
		{									  //
			switch ( *++Data )
			{				
				case 's':										  //字符串
					s = va_arg(ap, const char *);
					for ( ; *s; s++) 
					{
						USART_SendData(USARTx,*s);
						while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
					}				
					Data++;				
				break;
				case 'd':			
					//十进制
					d = va_arg(ap, int);					
					itoa(d, buf, 10);					
					for (s = buf; *s; s++) 
					{
						USART_SendData(USARTx,*s);
						while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
					}					
					Data++;				
				break;				
				default:
					Data++;				
				break;				
			}		 
		}		
		else USART_SendData(USARTx, *Data++);
		while ( USART_GetFlagStatus ( USARTx, USART_FLAG_TXE ) == RESET );
	}
}

/**
  * 函数功能: 将整形数据转换成字符串
  * 输入参数: radix =10 表示10进制,其他结果为0
  *           value 要转换的整形数
  *           buf 转换后的字符串
  *           radix = 10
  * 返 回 值: 无
  * 说    明:被USART_printf()调用
  */
static char * itoa( int value, char *string, int radix )
{
	int     i, d;
	int     flag = 0;
	char    *ptr = string;
	/* This implementation only works for decimal numbers. */
	if (radix != 10)
	{
		*ptr = 0;
		return string;
	}
	if (!value)
	{
		*ptr++ = 0x30;
		*ptr = 0;
		return string;
	}
	/* if this is a negative value insert the minus sign. */
	if (value < 0)
	{
		*ptr++ = '-';
		/* Make the value positive. */
		value *= -1;
	}
	for (i = 10000; i > 0; i /= 10)
	{
		d = value / i;
		if (d || flag)
		{
			*ptr++ = (char)(d + 0x30);
			value -= (d * i);
			flag = 1;
		}
	}
	/* Null terminate the string. */
	*ptr = 0;
	return string;
} /* NCL_Itoa */

/**
  * 函数功能: ESP8266初始化函数
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
void ESP8266_Init ( void )
{
	ESP8266_GPIO_Config ();	
	ESP8266_USART_Config ();	
}

       下面是串口1的初始化和输入输出重定向

void DEBUG_USART_Init(void)
{
  /* 定义IO硬件初始化结构体变量 */
  GPIO_InitTypeDef GPIO_InitStructure;
  /* 定义USART初始化结构体变量 */
	USART_InitTypeDef USART_InitStructure;
  /* 使能USART时钟 */
  DEBUG_USARTx_ClockCmd(DEBUG_USARTx_CLK,ENABLE);
  /* 使能USART功能GPIO时钟 */
  DEBUG_USARTx_GPIO_ClockCmd(DEBUG_USARTx_TX_CLK | DEBUG_USARTx_RX_CLK | RCC_APB2Periph_AFIO,ENABLE);
  
	/* 调试USART功能GPIO初始化 */
	/* 设定USART发送对应IO编号 */
	GPIO_InitStructure.GPIO_Pin =  DEBUG_USARTx_TX_PIN;
  /* 设定USART发送对应IO模式:复用推挽输出 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  /* 设定USART发送对应IO最大操作速度 :GPIO_Speed_50MHz */
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  /* 初始化USART发送对应IO */
	GPIO_Init(DEBUG_USARTx_TX_PORT, &GPIO_InitStructure);    
  
	/* 设定USART接收对应IO编号 */
	GPIO_InitStructure.GPIO_Pin = DEBUG_USARTx_RX_PIN;
  /* 设定USART发送对应IO模式:浮空输入 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  /* 其他没有重新赋值的成员使用与串口发送相同配置 */
  /* 初始化USART接收对应IO */
	GPIO_Init(DEBUG_USARTx_RX_PORT, &GPIO_InitStructure);	
			
	/* USART工作环境配置 */
  /* USART波特率:115200 */
	USART_InitStructure.USART_BaudRate = DEBUG_USARTx_BAUDRATE;
  /* USART字长(有效位):8位 */
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  /* USART停止位:1位 */
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
  /* USART校验位:无 */
	USART_InitStructure.USART_Parity = USART_Parity_No ;
  /* USART硬件数据流控制(硬件信号控制传输停止):无 */
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	/* USART工作模式使能:允许接收和发送 */
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  /* 初始化USART */
	USART_Init(DEBUG_USARTx, &USART_InitStructure);
	
  /* 使能USART */
	USART_Cmd(DEBUG_USARTx, ENABLE);
	
}

/**
  * 函数功能: 重定向c库函数printf到USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fputc(int ch, FILE *f)
{
  /* 发送一个字节数据到调试串口 */
  USART_SendData(DEBUG_USARTx, (uint8_t) ch);

  /* 等待串口数据发送完毕 */
  while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);		

  return (ch);
}

/**
  * 函数功能: 重定向c库函数getchar,scanf到USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fgetc(FILE *f)
{
  /* 等待串口输入数据 */
  while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);

  return (int)USART_ReceiveData(DEBUG_USARTx);
}

        主要是中断处理,在中断接收数据并存入缓冲区然后主函数中对缓冲区内容与ID进行比对,最后打印到串口助手。

void ESP8266_USART_INT_FUN(void)
{
	uint8_t ucCh;
	count++;
	if ( USART_GetITStatus (ESP8266_USARTx, USART_IT_RXNE ) != RESET )
	{
//		ucCh  = USART_ReceiveData(ESP8266_USARTx );
//		ucaRxBuf[count] = ucCh;
		if ( strEsp8266_Fram_Record .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) )                       //预留1个字节写结束符
			strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ++ ]  = ucCh;

	}
	 	 
	if ( USART_GetITStatus(ESP8266_USARTx, USART_IT_IDLE ) == SET )                                         //数据帧接收完毕
	{
		if(strEsp8266_Fram_Record .InfBit .FramLength >= 6)
		{	
		    ucTcpClosedFlag = 1;
			strEsp8266_Fram_Record .InfBit .FramFinishFlag = 1;
			strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength++ ] = '\0';
		}

		ucCh = USART_ReceiveData(ESP8266_USARTx );
		//ucTcpClosedFlag = strstr(strEsp8266_Fram_Record .Data_RX_BUF, "CLOSED\r\n" ) ? 1 : 0;
		
    }
	else
	{
		strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;
		//ucTcpClosedFlag = 0;
	}
}

        稍微修改了一下。

        主函数的逻辑大家按照自己的需要去做就行,接收到什么ID对应去操作什么器件。我这里就直接解析并且打印了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/443052.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2.4_2 死锁的处理策略——预防死锁

2.4_2 死锁的处理策略——预防死锁 &#xff08;一&#xff09;破坏互斥条件 互斥条件&#xff1a;只有对必须互斥使用的资源的争抢才会导致死锁。 如果把只能互斥使用的资源改造为允许共享使用&#xff0c;则系统不会进入死锁状态。比如&#xff1a;SPOOLing技术。操作系统可以…

惬意上手MySQL

大家好&#xff0c;我又来写博客了&#xff0c;今天给大家介绍一下MySQL,如果你只想让MySQL作为自己的辅助开发工具&#xff0c;那这一篇文章就够了&#xff0c;如果想作为一门语言来学习&#xff0c;那你可以看此文章了解一些基础。 MySQL介绍 数据库可分为关系型数据库和非关…

Elasticsearch 通过索引阻塞实现数据保护深入解析

Elasticsearch 是一种强大的搜索和分析引擎&#xff0c;被广泛用于各种应用中&#xff0c;以其强大的全文搜索能力而著称。 不过&#xff0c;在日常管理 Elasticsearch 时&#xff0c;我们经常需要对索引进行保护&#xff0c;以防止数据被意外修改或删除&#xff0c;特别是在进…

java IO 02 IO接口,字节流和字符流,节点流和处理流

01.定义 02.IO中的输入和输出的划分 03.流的分类 IO流的所有类中&#xff0c;最先分野的是字节流和字符流。 字节流包括&#xff1a;输入流和输出流 InputStream public abstract class InputStream implements Closeable { }OutputStream public abstract class OutputSt…

专业140+总分430+西南交通大学924信号与系统考研经验电子信息与通信工程,真题,大纲,参考书

今年报考西南交通大学&#xff0c;考研分数专业课924信号与系统140&#xff0c;总分430&#xff0c;各门分数都还是比较均衡&#xff0c;经过一年的复习&#xff0c;有得有失&#xff0c;总结一下自己的复习经历&#xff0c;希望给大家有点帮助&#xff0c;在复习中做的更好&am…

初始安装RabbitMQ

文章目录 1. RabbitMQ 概念2. RabbitMQ 四大核心概念3. RabbitMQ 核心部分4. RabbitMQ 名词解释5. RabbitMQ 安装 1. RabbitMQ 概念 RabbitMQ 是一个消息中间件&#xff1a;它接受并转发消息。 可以把它当做一个快递站点&#xff0c;当你要发送一个包裹时&#xff0c;你把你的…

IntelliJ IDEA自定义关闭当前文件的快捷方式

前言 idea中关闭当前标签页的默认快捷键是CtrlF4,这个组合键在键盘上操作起来很是不方便&#xff0c;我们可以在设置中自定义自己习惯的快捷方式。 自定义步骤 要在 IntelliJ IDEA 中将关闭当前文件的快捷方式设置为 Alt Q&#xff0c;请按照以下步骤操作&#xff1a;打开 …

计算机软件文档编制规范GB_T 8567-2006

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 计算机软件文档编制规范概述 计算机软件文档编制规范&#xff08;Specification for computer software documentation&#xff09; 由TC28&#xff08;全国信息技术标准化技…

【Node.js从基础到高级运用】二、搭建开发环境

Node.js入门&#xff1a;搭建开发环境 在上一篇文章中&#xff0c;我们介绍了Node.js的基础概念。现在&#xff0c;我们将进入一个更实际的阶段——搭建Node.js的开发环境。这是每个Node.js开发者旅程中的第一步。接下来&#xff0c;我们将详细讨论如何安装Node.js和npm&#…

ChatGPT Plus 支付出现「您的银行卡被拒绝/your card has been declined」怎么办?

ChatGPT Plus 支付出现「您的银行卡被拒绝/your card has been declined」怎么办&#xff1f; 在订阅 ChatGPT Plus 或者 OpenAI API 时&#xff0c;有时候会出现已下报错 &#xff1a; Your card has been declined. 您的银行卡被拒绝 出现这种错误&#xff0c;有以下几个解…

蓝桥杯练习系统(算法训练)ALGO-982 最小距离

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 最小距离 问题描述 数轴上有n个数字&#xff0c;求最近的两个数&#xff0c;即min(abs(x-y)) 输入格式 第一行包含一个整数n。   …

Mysql:如何自定义导出表结构

为了方便将mysql表结构信息快速录入到word或Excel表格中&#xff0c;最终实现如下效果&#xff1a; 对于word,则可将Excel表格复制粘贴即可。 废话不多少&#xff0c;开干。 准备准建&#xff1a;navicat 或sqlyog 第一步&#xff1a;编辑sql&#xff0c;如&#xff1a; SE…

rabbitmq 基本总结

rabbitmq 的基本概念 vhost、broker、producer、 consumer、 exchange、 queue、 routing key rabbitmq 常用的队列类型&#xff0c;工作队列&#xff08;简单队列&#xff09;,pub/sub, routing key&#xff0c; topic 模式 <dependency><groupId>com.rabbitmq&l…

Excel 快速填充/输入内容

目录 一. Ctrl D/R 向下/右填充二. 批量输入内容 一. Ctrl D/R 向下/右填充 ⏹如下图所示&#xff0c;通过快捷键向下和向右填充数据 &#x1f914;当选中第一个单元格之后&#xff0c;可以按住Shift后&#xff0c;再选中最后一个单元格&#xff0c;可以选中第一个单元格和最…

云计算项目九:K8S安装

K8S安装 Kube-master安装 按照如下配置准备云主机 防火墙相关配置&#xff1a;禁用selinux&#xff0c;禁用swap&#xff0c;且在firewalld-*。上传kubernetes.zip 到跳板机 配置yum仓库&#xff08;跳板机&#xff09; 跳板机主机配置k8s软件源服务端 [rootjs ~]# yum -y…

uniapp踩坑之项目:uni.previewImage简易版预览单图片

主要使用uni.previewImage //html <view class"box-card" v-for"(item,index) in DataList" :key"index"><view>图片&#xff1a;</view><image :src"item.Path" tap.stop"clickImg(item.Path)">&l…

JavaScript数组方法常用方法大全

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1. push()2. pop()3. unshift()4. shift()5. isArray()6. map()7. filter()8. every()9. some()10. splice()11. slice()12. indexOf()13. includes()14. concat()1…

Python和Google Colab进行卫星图像二维小波变化和机器学习

2D 小波分解是图像处理中的一种流行技术,使用不同的滤波器将图像分解为不同的频率分量(“近似”和“细节”系数)。该技术对于各种图像处理任务特别有用,例如压缩、去噪、特征提取和边缘检测。 在本文中,我们将演示如何在 Google Colab 中使用 Python 下载高分辨率样本卫星…

弄清Resource、ResourceLoader、容器之间的微妙关系

Resource&#xff1a; 在Java中&#xff0c;资源会被抽象成url&#xff0c;通过url前面的协议&#xff08;如file&#xff1a;&#xff0c;classpath&#xff1a;&#xff09;来处理不同的操作逻辑&#xff0c;resource是一个接口 Resource家族 具体的资源访问由其实现类完成&a…

Python学习日记之学习turtle库(下 篇)

前言&#xff1a; 书接上篇&#xff0c;我们继续来了解Python内置库 turtle功能库。在前面的文章中&#xff0c;我们初步的了解了一下 turtle库&#xff0c;画布和画笔相关的函数&#xff0c;那么我们继续来深入了解一下吧。 详情见&#xff1a; Python学习日记之学习turtle库…