串口和 蓝牙模块HC08

串口基本认知

串行接口简称串口,也称 串行通信 接口或 串行通讯接口 (通常指 COM 接口 ),是采用串行通信方
式的 扩展接口 串行 接口Serial Interface )是指数据一位一位地顺序传送。其特点是 通信线路 简 单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢
  • 是设备间接线通信的一种方式
  • 数据一位一位地顺序传送
  • 双向通信,全双工
  • 传送速度相对较慢

 串口关于电器标准和协议

串行接口按电气标准及协议来分包括 RS-232-C RS-422 RS485 等。 RS-232-C RS-422 RS-485 标准只对接口的电气特性做出规定,不涉及接插件、电缆或协议。

RS-232

也称为标准串口,最常用的一种串行通讯接口,比如我们电脑主机的9针串口,最高速率是20kb/s,RS-232是为点对点设计的,最长传输距离为15m,适合本地设备之间的通信。

RS-422

支持点对点的双向通信,最大传输距离为1219米,最大传输速率为10Mb/s。

RS-482

是从RS-422基础上发展而来的,无论四线还是二线连接方式总线上可多接32个设备。

 串口的电平

异步串行是指 UART Universal Asynchronous Receiver/Transmitter ),通用异步接收 / 发送。
UART 包含 TTL 电平的 串口 RS232 电平的串口 所以串口的概念比UART大一点。

怎么理解异步通信?

由于单片机和电脑,不同设备的频率和配置不同,因此CPU运行速度不同,所以各自使用各自的时钟来相互配合。

RS232电平和TTL电平有什么区别?

对于RS232逻辑1是 -3 ~ -15V的电压,逻辑0是 3 ~ 15V 的电压。

TTL电平Transistor-Transistor Logic,即晶体管-晶体管逻辑的简称,TTL电平信号应用广泛,是因为其数据表示采用二进制规定,+5v等价于逻辑1,0v等价于逻辑0。 在数字电路中,由TTL电子元器件组成电路的电平是个电压范围,规定:

输出高电平>=2.4V,输出低电平<=0.4V; 

输入高电平>=2.0V,输入低电平<=0.8V;

 串口通信

  • RXD:数据输入引脚,数据接受;STC89系列对应P3.0
  • TXD:数据发送引脚,数据发送;STC89系列对应P3.1
  • 接线方式

 

笔记本电脑通过TTL电平和单片机通讯:TX发送线(端口);RX接受线(端口),并使用CH340进行USB转TTL。

串口编程要素

串口的结构如下图所示,
通过定时器T1计时,由T1产生溢出率,作为波特率发生器。

  • 两个数据缓冲器,SBUF。分别是发送数据的发送寄存器,读取数据的接收寄存器。
    串口写入时,写入的是发送寄存器,即数据向发送寄存器SBUF写入。
    向串口读时,读出的是接收寄存器,即数据由接收寄存器SBUF读出。

  • 定时器1产生波特率, 串口一般使用定时器1,模式2,八位自动重装模式,来产生溢出率,从而产生波特率。而且在配置定时器相关的寄存器时不用配置定时器中断,只是使用定时器1来产生波特率的功能。

  • 移位寄存器,在接受控制器的控制下,将输入的数据逐位移入接收SBUF。

  • 串行控制寄存器SCON,SCON的功能是控制串行通信口的工作方式以及工作的状态。

输入 / 输出数据缓冲器都叫做 SBUF , 都用 99H 地址码,但是是两个独立的 8 位寄存器

代码体现为:

  • 想要接收数据 char data = SBUF(将缓存器的值读取到data,即单片机读取SBUF的数据存入到data中)
  • 想要发送数据 SBUF = data (将data的值写入缓存器,即单片机发送data到SBUF中

再次回忆UART的概念,”由于单片机和电脑,不同设备的频率和配置不同,因此CPU运行速度不同,所以各自使用各自的时钟来相互配合。”  所以双方需要约定通讯速度,这个速度就叫做波特率,对于电脑来说,别人做好了软件,鼠标点点就能配置好,而单片机的波特率则需要自己写代码。

对于电脑来说,需要点击配置的东西是:

 所以在代码中,我们也需要配置波特率校验位停止位。那在代码中的这些如何进行设置?答案还是,和设置定时器模式一样,要操控寄存器。 而且,也和定时器一样,代码也可以从stc-isp助手里面得到: 注意!这里的波特率设置应该和之前电脑设置的波特率

 串行通信口的控制寄存器

1 串行控制寄存器SCON

SCON寄存器用来控制串行通信的工作方式及反映串行口的工作状态。SCON的地址是98H,可位寻址。如下图所示。

通过配置SCON寄存器来对串行通信的工作模式进行控制。
说说几个常用的位

  • SM0和SM1,组合确定串行口的模式,不同的模式下波特率不同,功能也不同,下面会详细介绍不同模式下的波特率该如何计算
  • REN,允许/禁止串行接收控制位。 由软件置位REN,即REN=1为允许串行接收状态,可启动串行口接收数据。
  • TI,发送中断请求标志位。主机通过串行口发送数据发送完成后,TI会置1,向串口申请中断,如果TI为1 就表示SUBF的数据已经发送完成了,要手动将TI位清零。(即SBUF=Data)
  • RI,接收中断请求标志位。从机接收到主机通过串行口接收到的数据后,RI会置1,即会串口申请中断,如果RI为1 就表示数据已经通过SBUF读取完成了,要手动将RI位清零。(即Data=SBUF)

 2 电源控制寄存器PCON

这里我们只需要知道SMOD是啥就可以了。

  • SMOD位,就是波特率是否加倍,若SMOD=0,波特率不变。SMOD=1,波特率加倍SMOD默认为0。

3 配置寄存器

配置SCON寄存器

 

 上图就是SCON寄存器的位图,下面以串口通信的模式1来举例。
模式1,那么SM0和SM1就要配置成 0 1,注意这里SM0和SM1决定串口通信的模式
REN,可置1,置1就是允许串行通信口接收数据,当不需要接收数据的时候可以置0。
后面的几位直接不看,一般用不到
TI和RI,也默认为0,当接收数据或发送数据的时候,会由硬件置1,继而触发中断,这时要由软件置1。
这样SCON寄存器就配置好了。


这样我的SCON配置如下

SCON=0x40;   //方式1   REN置0 禁止数据接收的控制位  0100 0000
SCON=0x50;   //方式1   REN置1 允许数据接收的控制位  0101 0000
 配置PCON寄存器

我们只需要明确一点,我的波特率是否需要加倍,如果加倍,那么PCON的第一位SMOD就要置
这样我的PCON就配置好了,如加倍(不倍速可以不写)

PCON &= 0x8F;  //波特率加倍

1.代码实现单片机向电脑发送一个字符

#include "reg52.h"
#include "intrins.h" //这个库加了,delay函数里面的nop()才不会报错

sbit led1 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
sbit led2 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口

sfr AUXR = 0x8E;//配置了这句话,才可以在UART的初始化里写AUXR寄存器,原因见STC89系列的手册


void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void UartInit()		//9600bps@11.0592MHz
{
	PCON &= 0x7F;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率   0101 0000
	AUXR &= 0xBF;		//定时器1时钟12T模式
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设置定时器1模式
	TMOD |= 0x20;		//设置定时器1为8位自动重装方式
	TL1 = 0xFD;			//设置定时初始值
	TH1 = 0xFD;			//设置定时重载值
	ET1 = 0;			//禁止定时器1中断
	TR1 = 1;			//启动定时器1
}


void main()
{
	char data_msg = 'a';
	
	//配置C51串口通信发送方式
	UartInit();
	
	while(1){
		Delay1000ms();
		//往发送缓冲器写入数据,就完成数据的发送
		SBUF = data_msg;
	}	
	
}

实现效果1 

2.代码实现单片机向电脑发送字符串

SCON寄存器中,BIT1为TI:即,每发送一个BYTE(一个char变量的大小),TI就会被硬件置1,根据这个,我们可以编写使串口打印字符串:

#include "reg52.h"

sbit led1 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
sbit led2 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口



/*
void UartInit(void)		//9600bps@11.0592MHz
{
	PCON &= 0x7F;		//波特率不倍速 SMOD在PCON里
	SCON = 0x50;		//8位数据,可变波特率
	AUXR &= 0xBF;		//定时器时钟12T模式
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器模式
	TL1 = 0xFD;			//设置定时初始值
	TH1 = 0xFD;			//设置定时重载值
	ET1 = 0;			//禁止定时器中断
	TR1 = 1;			//定时器1开始计时
}
*/

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}




void UartInit()		//9600bps@11.0592MHz
{
	SCON = 0x40;  //配置串口工作方式1,REN不使能接收
	
	//配置定时器1,工作方式为8位自动重载
	TMOD &= 0x0f;//
	TMOD |= 0x20;
	
	TH1 = 0xFD; 
	TL1 = 0xFD; //9600波特率的初值
	
	TR1 = 1;//启动定时器
	
	
}

void Send_byte(char data_msg)
{
	SBUF = data_msg;//往发送缓冲器里写入数据,就完成了数据的发送

	while(!TI);//在请求中断时,TI= 1,既!TI=0,等待数据的发送完成;响应中断结束后TI = 0,既!TI = 1,将TI清零
	TI = 0;

}

void Send_string(char* str)
{
	while(*str != '\0')
	{
		Send_byte(*str);
		str++;
	}
}

void main()
{
	char data_msg = 'a';
	
	//配置C51串口通信发送方式
	UartInit();
	
	while(1){
		Delay1000ms();
		//往发送缓冲器写入数据,就完成数据的发送

		Send_string("wdnmd\t");
	}	
	
}

效果实现

3.代码实现使用串口点亮单片机LED

SCON寄存器中,BIT0为RI:即收到数据后,RI位会由硬件置1

我们需要如何接收数据呢?

设置阻塞检测接收的数据?此方法会影响程序的进程,一般不使用

还是中断?

查询手册可知,使用中断的方式接收指令可以使得响应没有延时

所以,打开UART中断需要打开ES和EA

下方代码块为中断服务子函数模块

// 串口中断函数模板
void Uart_Routine() interrupt 4
{
	if(RI==1)  
	{
		RI=0;
	}
	if(TI==1)
	{
	TI=0;
	}
}

 

#include "reg52.h"

sbit D5 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
sbit led2 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口



/*
void UartInit(void)		//9600bps@11.0592MHz
{
	PCON &= 0x7F;		//波特率不倍速 SMOD在PCON里
	SCON = 0x50;		//8位数据,可变波特率
	AUXR &= 0xBF;		//定时器时钟12T模式
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器模式
	TL1 = 0xFD;			//设置定时初始值
	TH1 = 0xFD;			//设置定时重载值
	ET1 = 0;			//禁止定时器中断
	TR1 = 1;			//定时器1开始计时
}
*/

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}




void UartInit()		//9600bps@11.0592MHz
{
	SCON = 0x50;  //配置串口工作方式1,REN使能接收
	
	//配置定时器1,工作方式为8位自动重载
	TMOD &= 0x0f;//
	TMOD |= 0x20;
	
	TH1 = 0xFD; 
	TL1 = 0xFD; //9600波特率的初值
	
	TR1 = 1;//启动定时器
	
	
}

void Send_byte(char data_msg)
{
	SBUF = data_msg;
	while(!TI);//在请求中断时,TI= 1,既!TI=0,等待数据的发送完成;响应中断结束后TI = 0,既!TI = 1,将TI清零
	TI = 0;

}

void Send_string(char* str)
{
	while(*str != '\0')
	{
		Send_byte(*str);
		str++;
	}
}

void main()
{
	char data_msg = 'a';
	char cmd;
	
	D5 = 1;
	//配置C51串口通信发送方式
	UartInit();
	
	while(1){
		Delay1000ms();
		//往发送缓冲器写入数据,就完成数据的发送

		Send_string("wdnmd\t");
		//怎么知道收到数据,查询RI的值,如果RT是1(收到数据后由硬件置一)
        //非中断触发
		/*if(RI == 1) //RI = 1时数据接收完毕
		{
			RI = 0;//软件复位
			cmd = SBUF; //从SBUF里面读发来的数据
			if(cmd == 'o')
			{
				D5 = 0;//点亮D5
			}
			if(cmd == 'c')
			{
				D5 = 1;//熄灭D5
			}
			
		}*/
	}	
	
}


//中断触发
void Uart_Handler() interrupt 4
{
	if(RI)//中断处理函数中,对于接收中断的响应
	{
		RI = 0;//清除接收中断标志位
		cmd = SBUF;
		if(cmd == '1')
		{
			D5 = 0;//点亮D5
		}
		if(cmd == '0')
		{
			D5 = 1;//熄灭D5
		}
	}
	if(TI)
	{
		
	}
}

这次试验就很好的体现了串口的"全双工“,即可以不断同时的发送和接收数据。

同时注意,在”发送缓冲区”中选择文本模式后要注意,在文本模式下输入的任何东西都会被认为字符,如果输入1,则为字符1,对应ASCII码中是数字49!!!

4.代码实现使用串口点亮单片机LED

以上的代码实现的是接收字符来点亮LED,如果是想要使用字符串来控制点亮LED,需要修改代码:

#include "reg52.h"
#include <string.h>

#define SIZE 12
sbit D5 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
sbit led2 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口

char cmd[12];



/*
void UartInit(void)		//9600bps@11.0592MHz
{
	PCON &= 0x7F;		//波特率不倍速 SMOD在PCON里
	SCON = 0x50;		//8位数据,可变波特率
	AUXR &= 0xBF;		//定时器时钟12T模式
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器模式
	TL1 = 0xFD;			//设置定时初始值
	TH1 = 0xFD;			//设置定时重载值
	ET1 = 0;			//禁止定时器中断
	TR1 = 1;			//定时器1开始计时
}
*/

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}




void UartInit()		//9600bps@11.0592MHz
{
	SCON = 0x50;  //配置串口工作方式1,REN使能接收
	
	//配置定时器1,工作方式为8位自动重载
	TMOD &= 0x0f;//
	TMOD |= 0x20;
	
	TH1 = 0xFD; 
	TL1 = 0xFD; //9600波特率的初值
	
	TR1 = 1;//启动定时器
	ES  = 1;//开启串口中断
	EA  = 1;//开启总中断
	
	
}



//TI 发送请求中断标志位,是指单片机向电脑发送
//RI 接收请求中断标志位,是指单片机接收电脑的消息


void Send_byte(char data_msg)
{
	SBUF = data_msg;
	while(!TI);//在请求中断时,TI= 1,既!TI=0,等待数据的发送完成;响应中断结束后TI = 0,既!TI = 1,将TI清零
	TI = 0;

}

void Send_string(char* str)
{
	while(*str != '\0')
	{
		Send_byte(*str);
		str++;
	}
}

void main()
{
	char data_msg = 'a';

	
	D5 = 1;
	//配置C51串口通信发送方式
	UartInit();
	
	while(1){
		Delay1000ms();
		//往发送缓冲器写入数据,就完成数据的发送

		Send_string("wdnmd\t");
		//怎么知道收到数据,查询RI的值,如果RT是1(收到数据后由硬件置一)
	}	
	
}

void Uart_Handler() interrupt 4
{
	static int i = 0;//静态变量,被初始化一次 避免每次发生中断i都会清0

	if(RI)//中断处理函数中,对于接收中断的响应  //如果是RI引起的中断
	{
		RI = 0;//清除接收中断标志位,软件复位
		cmd[i] = SBUF;
		i++;
		if(i == SIZE)
		{
			i = 0;
		}
		if(strstr(cmd,"open\r\n"))
		{
			D5 = 0;//点亮D5
			i = 0;
			memset(cmd,'\0',SIZE);
		}
		if(strstr(cmd,"close\r\n"))
		{
			D5 = 1;//熄灭D5
			i = 0;
			memset(cmd,'\0',SIZE);
		}
	}
	if(TI)
	{
		
	}
}

如此一来,在串口中输入"open“加上换行键再按下发送数据就可以点灯;同样输入”close"加上换行键再按下发送数据就可以关灯。

使用蓝牙模块HC08进行串口通讯

注意!蓝牙的RXD要和串口的TXD相连,同理,蓝牙的TXD要和串口的RXD相连。使用上左图的蓝牙模块(内置波特率9600,正好可以对应)再使用右图扫码小程序,搜索“HC08"即可连接成功!

注意!在串口中,是检测换行符结束字符串的

'\r’是回车,前者使光标到行首
'\n’是换行,后者使光标下移一格

Unix系统里,每行结尾只有“<换行>”,即“\n”;
Windows系统里面,每行结尾是“<回车><换行>”,即“\r\n”;
Mac系统里,每行结尾是“<回车>”,即“\r


以下来自ChatGPT的解答:

串口通信中,有时需要在发送的数据后面加上\r\n(回车换行符),这主要是为了满足接收端或显示设备的特定要求,确保数据能够被正确解析和显示。

具体来说,\r(回车符)的作用是使光标移动到当前行的最前面,而\n(换行符)的作用则是将光标移动到下一行的当前位置。因此,\r\n组合起来,可以实现光标跳到下一行的开始位置,从而实现数据的换行显示。

在串口通信中,如果接收端或显示设备需要按照特定的格式来解析和显示数据,那么就需要在发送的数据后面加上相应的控制符。例如,在某些情况下,接收端可能期望每接收完一行数据后进行一些处理,或者显示设备可能需要在每行数据的末尾换行以显示新的数据。在这些情况下,就需要在发送的数据后面加上\r\n来实现换行。

需要注意的是,不是所有的串口通信都需要加\r\n。是否添加以及添加的方式(是\r\n、\n还是其他控制符)取决于具体的通信协议和接收端或显示设备的要求。因此,在进行串口通信时,需要根据实际情况来确定是否需要添加\r\n以及其他控制符。

 

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

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

相关文章

vulhub打靶记录——Corrosion2

文章目录 主机发现端口扫描ssh—22search openssh EXP web服务—8080目录扫描登录tomcat后台 提权切换用户查看用户权限寻找SUID命令破解登录密文 总结 主机发现 使用nmap扫描局域网内存活的主机&#xff0c;命令如下&#xff1a; nmap -sP 192.168.151.0/24192.168.151.1&am…

【LeetCode】894. 所有可能的真二叉树

文章目录 [894. 所有可能的真二叉树](https://leetcode.cn/problems/all-possible-full-binary-trees/)思路一&#xff1a;分治代码&#xff1a;思路二&#xff1a;记忆化搜索代码&#xff1a; 894. 所有可能的真二叉树 思路一&#xff1a;分治 1.递归&#xff0c;n1 时&#…

数字图像处理——数字图像基础(持续更新)

视觉感知要素——亮度适应和鉴别&#xff1a; 人眼对不同亮度的适应和鉴别能力&#xff1a;亮 -> 暗 适应&#xff1b;暗 -> 亮 适应 图像取样和量化 1、概念&#xff1a; 数字化坐标值称为取样 数字化幅度值称为量化 2、 坐标的数字化称为采样&#xff0c;…

【强化学习的数学原理-赵世钰】课程笔记(二)贝尔曼公式

【强化学习的数学原理-赵世钰】课程笔记&#xff08;二&#xff09;贝尔曼公式 一. 内容概述 1. 第二章主要有两个内容 &#xff08;1&#xff09;一个核心概念&#xff1a;状态值&#xff08;state value&#xff09;&#xff1a;从一个状态出发&#xff0c;沿着一个策略我…

GIS水文分析填充伪洼地学习

1 基本操作 洼地是指流域内被较高高程所包围的局部区域&#xff1b; 分为自然洼地和伪洼地&#xff1b; 自然洼地是自然界实际存在的洼地&#xff1b; 在 DEM 数据中&#xff0c;由于数据处理的误差和不合适的插值方法所产生的洼地&#xff0c;称为伪洼地&#xff1b; DEM 数据…

【C语言】汉诺塔问题

目录 一、何为汉诺塔问题&#xff1f; 二、汉诺塔计算规律 三、打印汉诺塔的移动路径 总结 一、何为汉诺塔问题&#xff1f; 汉诺塔问题是一个经典的问题。汉诺塔&#xff08;Hanoi Tower&#xff09;&#xff0c;又称河内塔&#xff0c;源于印度一个古老传说。大梵天创造世…

Linux Shell:`cat`命令

Linux Shell&#xff1a;cat命令 Linux 系统中的 cat 命令是一种多用途的工具&#xff0c;主要用于查看、创建、连接和追加文件内容。其名称来源于 concatenate 的缩写&#xff0c;意味着它可以用来连接文件内容到标准输出&#xff08;屏幕&#xff09;。在日常使用中&#xf…

C语言整数和小数的存储

1.整数在内存中的存储 计算机使用二进制进行存储、运算&#xff0c;整数在内存中存储使用的是二进制补码 1.1原码、反码、补码 整数的2进制表⽰⽅法有三种&#xff0c;即 原码、反码和补码 三种表⽰⽅法均有符号位和数值位两部分&#xff0c;符号位都是⽤0表⽰“正”&am…

WHILE循环

oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 WHILE 循环是先判断条件&#xff0c;如果条件成立就执行循环体&#xff0c;如果不成立&#xff0c;就退出循环 while 条件表达式 loop 语句序列 end loop 运行的时候&…

14届蓝桥杯省赛 C/C++ B组 T8 整数删除(双向链表,堆)

瞬间定位一个数的左边或者右边&#xff0c;需要用到双向链表。 在过程中不断维护最小值&#xff0c;需要用到堆。 所以定义一个pair类型优先队列&#xff0c;每次取出堆顶进行删除&#xff0c;并且同时让删除元素的左右元素加上其值。 同时需要注意&#xff0c;在删除元素之后…

5. 4 二重循环将二维数组的某列、某矩形转大写

5. 4 二重循环将二维数组的某列、某矩形转大写 1. 把每一行的b都变成大写 assume cs:codesg,ds:data,ss:stack data segmeNTstr db aaaaabbbbbcccccdb aaaaabbbbbcccccdb aaaaabbbbbcccccdb aaaaabbbbbccccc,$ data endsstack segmentdb 10 dup(0) stack endscodesg SEgments…

船气废弃锅炉三维仿真vr交互展示降低培训门槛

火化炉是殡葬行业的核心设备&#xff0c;其操作技艺对于专业人才的培养至关重要。然而&#xff0c;传统实践教学受限于时间、场地、设备损耗等多重因素&#xff0c;难以给予学生充分的实操机会。面对这一挑战&#xff0c;我们创新推出了火化炉vr三维仿真培训软件&#xff0c;以…

Java私房菜:探索泛型之妙用与深意

“泛型”&#xff08;generics&#xff09;作为Java特性之一&#xff0c;相信大家也耳熟能详了&#xff0c;就算没听说过&#xff0c;也肯定看过或偶然间使用过泛型&#xff0c;在这里&#xff0c;我们一起重新温习一下泛型&#xff0c;通过一些案例引发些新的思考。Java中的泛…

保研复习数据结构-图(10)

一.图的定义和基本术语 1.什么是图&#xff1f; 图(Graph)是由顶点的有穷非空集合V(G)和顶点之间边的集合E(G)组成&#xff0c;通常表示为:G(V,E)&#xff0c;其中&#xff0c;G表示图&#xff0c;V是图G中顶点的集合&#xff0c;E是图G中边的集合。 2.什么是完全图&#xf…

MySQL基础练习题:创建数据库

这部分主要是为了帮助大家回忆回忆MySQL的基本语法&#xff0c;数据库来自于MySQL的官方简化版&#xff0c;题目也是网上非常流行的35题。这些基础习题基本可以涵盖面试中需要现场写SQL的问题。 创建数据库 在开始练习之前&#xff0c;我默认你的电脑上是没有本系列练习题需要…

题目:【序列中删除指定数字】【变种水仙花数】【数组串联】【交换奇偶位】【offsetof宏的实现】

题目一:序列中删除指定数字 #include <stdio.h>int main(){int a0;int arr[50]{0};int c0;scanf("%d",&a);for(int i0;i<a;i){scanf("%d",&arr[i]);//输入a个值}scanf("%d",&c);//输入要删除的数据int i0;int j0;for(i0;i&…

【科东软件】鸿道Intewell-Win_V2.1.1_release版本正式发布

Intewell-Win_V2.1.1_release版本 版本号&#xff1a;V2.1.1 版本发布类型&#xff1a;release正式版本 版本特点 修复此前版本中的问题 运行环境推荐 Intewell developer可以运行在windows7及windows10 64位 支持硬件列表

【40分钟速成智能风控2】互联网金融信用风险

目录 ​编辑 信用风险 白名单准入 贷前识别 贷中管理 贷后催收 信用风险 白名单准入 白名单是信用风险管理的第一道门槛&#xff0c;与整个平台贷款产品的设计和定位有紧密的联系。白名单设立的初衷是圈定目标客户&#xff0c;有了目标客群之后才能更好地进行精准营销&…

非关系型数据库——三万字Redis数据库详解

目录 前言 一、Redis概述 1.主要特点 2.Redis优缺点 3.Redis为什么这么快 4.Redis那么快&#xff0c;为什么不用它做主数据库&#xff0c;只用它做缓存 5.线程模型 5.1单线程架构 5.2多线程IO处理&#xff08;Redis 6及以上&#xff09; 5.3线程模型的优化 6.作用 …

基于SpringBoot+微信小程序的点餐系统

一、项目背景介绍&#xff1a; 小程序外卖扫码点餐为客户提供的是最方便的饮食方式,以快速、便捷的点餐业务送货上门为 -客户服务,这省去了客户很多不必要的时间和麻烦,给商家带来更多利益。同时,小程序外卖扫码点餐可以辅助餐饮企业营销,通过信息管理,可以记录餐饮企业方方面面…