【51单片机】串口通信实验(包括波特率如何计算)

目录

  • 串口通信实验
    • 通信的基本概念
      • 串行通信与并行通信
      • 异步通信与同步通信
      • 单工、 半双工与全双工通信
      • 通信速率
    • 51单片机串口介绍
      • 串口介绍
      • 串口通信简介
      • 串口相关寄存器
      • 串口工作方式
        • 方式0
        • 方式1
        • 方式 2 和方式 3
      • 串口的使用方法(计算波特率)
    • 硬件设计
    • 软件设计
      • 1、向单片机发送数据 0x11
      • 2、向单片机发送一个不断加1的数
      • 3、通过电脑端发送一个数据去点亮led灯

****

串口通信实验

本节来学习 51 单片机的串口通信。 开发板上集成了 1 个串口通信电路, 是 USB 转串口模块, 它既可下载程序也可实现串口通信功能。 本节要实现的功能是:51 单片机通过串口(UART) 实现与 PC 机对话,51 单片机的串口收到 PC 机发来的数据后原封不动的返回给 PC 机显示。

通信的基本概念

51 单片机不仅可以实现串口通信, 还可以通过 IO 口模拟实现多种其他通信, 比如 SPI、 IIC 等, 学习这些通信前, 我们很有必要了解下通信的基本概念。 通信的方式可以分为多种, 按照数据传送方式可分为串行通信和并行通信。 按照通信的数据同步方式, 可分为异步通信和同步通信。 按照数据的传输方向又可分为单工、 半双工和全双工通信。 下面我们就来简单介绍这几种通信方式。

串行通信与并行通信

(1)串行通信
串行通信是指使用一条数据线, 将数据一位一位地依次传输, 每一位数据占据一个固定的时间长度。 其只需要少数几条线就可以在系统间交换信息, 特别适用于计算机与计算机、 计算机与外设之间的远距离通信。 如下图所示:
在这里插入图片描述
串行通信的特点: 传输线少, 长距离传送时成本低,且可以利用电话网等现成的设备, 但数据的传送控制比并行通信复杂。

(2)并行通信
并行通信通常是将数据字节的各位用多条数据线同时进行传送, 通常是 8位、16 位、32 位等数据一起传输。 如下图所示:
在这里插入图片描述
并行通信的特点: 控制简单、 传输速度快; 由于传输线较多, 长距离传送时成本高且接收方的各位同时接收存在困难, 抗干扰能力差。

异步通信与同步通信

(1)异步通信
异步通信是指通信的发送与接收设备使用各自的时钟控制数据的发送和接收过程。 为使双方的收发协调, 要求发送和接收设备的时钟尽可能一致。
异步通信是以字符(构成的帧) 为单位进行传输, 字符与字符之间的间隙(时间间隔) 是任意的, 但每个字符中的各位是以固定的时间传送的, 即字符之间不一定有“位间隔” 的整数倍的关系, 但同一字符内的各位之间的距离均为“ 位间隔” 的整数倍。 如下图所示:
在这里插入图片描述
异步通信的特点: 不要求收发双方时钟的严格一致, 实现容易, 设备开销较小, 但每个字符要附加 2~3 位用于起止位, 各帧之间还有间隔, 因此传输效率不高。
(2)同步通信
同步通信时要建立发送方时钟对接收方时钟的直接控制, 使双方达到完全同步。 此时, 传输数据的位之间的距离均为“位间隔” 的整数倍, 同时传送的字符间不留间隙, 即保持位同步关系, 也保持字符同步关系。 发送方对接收方的同步可以通过两种方法实现。 如下图所示:
在这里插入图片描述

单工、 半双工与全双工通信

(1) 单工通信
单工是指数据传输仅能沿一个方向, 不能实现反向传输。 如下图所示:
在这里插入图片描述
(2) 半双工通信
半双工是指数据传输可以沿两个方向, 但需要分时复用一根数据线进行。 如下图所示:
在这里插入图片描述
(3) 全双工通信
全双工是指数据可以同时进行双向传输。 如下图所示:
在这里插入图片描述

通信速率

衡量通信性能的一个非常重要的参数就是通信速率, 通常以比特率(Bitrate)来表示。 比特率是每秒钟传输二进制代码的位数, 单位是: 位/ 秒(bps) 。 如每秒钟传送 240 个字符, 而每个字符格式包含 10 位(1 个起始位、 1 个停止位、8 个数据位), 这时的比特率为:
                                                  10 位× 240 个/秒 = 2400 bps

在后面会遇到一个“波特率” 的概念, 它表示每秒钟传输了多少个码元。 而码元是通信信号调制的概念, 通信中常用时间间隔相同的符号来表示一个二进制数字, 这样的信号称为码元。 如常见的通信传输中, 用 0V 表示数字 0, 5V 表示数字 1, 那么一个码元可以表示两种状态 0 和 1, 所以一个码元等于一个二进制比特位, 此时波特率的大小与比特率一致; 如果在通信传输中, 有 0V、 2V、4V 以及 6V 分别表示二进制数 00、 01、 10、 11, 那么每个码元可以表示四种状态, 即两个二进制比特位, 所以码元数是二进制比特位数的一半, 这个时候的波特率为比特率的一半。 由于很多常见的通信中一个码元都是表示两种状态,所以我们常常直接以波特率来表示比特率。

51单片机串口介绍

串口介绍

串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单可实现两个设备的互相通信。

在这里插入图片描述
在这里插入图片描述
前两种电平的传输距离超过十几米错误率就很高了,而RS485电平传输距离可以达到千米以上。

常见的通信接口比较
在这里插入图片描述

串口通信简介

串口通信(Serial Communication), 是指外设和计算机间通过数据信号线、地线等按位进行传输数据的一种通信方式, 属于串行通信方式。 串口是一种接口标准, 它规定了接口的电气标准, 没有规定接口插件电缆以及使用的协议。
(1)接口标准
串口通信的接口标准有很多, 有 RS-232CRS-232RS-422ARS-485 等。常用的是 RS-232RS-485RS-232 其实是 RS-232C 的改进, 原理是一样的。这里我们就以 RS-232C 接口进行讲解。RS-232C 是 EIA(美国电子工业协会) 1969 年修订 RS-232C 标准。 RS-232C定义了数据终端设备(DTE) 与数据通信设备(DCE) 之间的物理接口标准。RS-232C 接口规定使用 25 针连接器, 简称 DB25, 连接器的尺寸及每个插
针的排列位置都有明确的定义, 如下图所示:
在这里插入图片描述

RS-232C 还有一种 9 针的非标准连接器接口, 简称 DB9。 串口通信使用的大多都是 DB9 接口。 DB25DB9 接头有公头和母头之分, 其中带针状的接头是公头, 而带孔状的接头是母头。 9 针串口线的外观图如下图所示:

在这里插入图片描述

从上图中可以看到公头和母头的管脚定义顺序是不一样, 这一点需要特别注意。 这些管脚都有什么作用呢? 9 针串口和 25 针串口常用管脚的功能说明如下图所示:
在这里插入图片描述

在串口通信中, 通常我们只使用 2、 3、 5 三个管脚, 即 TXD(transmit exchange data)RXDSGND,其他管脚功能大家看不明白也没关系。RS-232C 对逻辑电平也做了规定, 如下:
在 TXD 和 RXD 数据线上:
1.逻辑 1 为-3~-15V 的电压
2.逻辑 0 为 3~15V 的电压

在 RTS、 CTS、 DSR、 DTR 和 DCD 等控制线上:
1.信号有效( ON 状态) 为 3~15V 的电压
2.信号无效( OFF 状态) 为-3~-15V 的电压

由此可见, RS-232C 是用正负电压来表示逻辑状态, 与晶体管-晶体管逻辑集成电路(TTL) 以高低电平表示逻辑状态的规定正好相反。 而我们 51 单片机使用的就是 TTL 电平, 所以要实现 51 单片机与计算机的串口通信, 需要进行 TTLRS-232C 电平转换, 通常使用的电平转换芯片是 MAX232。

在串口通信中通常 PC 机的 DB9 为公头, 单片机上使用的串口 DB9 为母头,通过一根直通串口线进行相连。 在 9 针串口线实物图即为直通型串口线, 串口线(COM) 母头连接计算机 DB9 的公头, 串口线公头连接单片机上使用的 DB9 母头, 这样就是将 2、 3、 5 管脚直接相连。 如果你要实现两台计算机串口通信,那么就需要一根交叉串口线, 将 2 对 3、 3 对 2、 5 对 5 连接, 交叉串口线一般两头都是母头。

串口通信中还需要注意的是, 串口数据收发线要交叉连接, 计算机的 TXD 要对应单片机的 RXD, 计算机的 RXD 要对应单片机的 TXD, 并且共 GND, 如下图:
在这里插入图片描述
有的朋友就会问了, 在计算机与单片机进行串口通信时, 使用的不是直通线吗, 这时候怎么让 TXD 与 RXD 交叉连接? 前面我们说了单片机处理的是 TTL电平, 需要使用 RS232 电平转换芯片, 将 RS232 电平转换芯片串行数据输出管脚交叉连接在 DB9 母头上即可, 本章后面硬件设计部分会介绍。
(2)通信协议
RS232 的通信协议比较简单, 通常遵循 96-N-8-1 格式。“96” 表示的是通信波特率为 9600。 串口通信中通常使用的是异步串口通信, 即没有时钟线, 所以两个设备要通信, 必须要保持一致的波特率, 当然, 波特率常用值还有 4800、 115200 等。

“N” 表示的是无校验位, 由于串口通信相对更容易受到外部干扰导致传输数据出现偏差, 可以在传输过程加上校验位来解决这个问题。 校验方法有奇校验(odd)、 偶校验(even)、 0 校验(space)、 1 校验(mark)以及无校验(noparity)。具体的介绍, 大家可以百度串口通信了解。

8”表示的是数据位数为 8 位, 其数据格式在前面介绍异步通信中已讲过。当然数据位数还可以为 5、 6、 7 位长度。“1” 表示的是 1 位停止位, 串口通讯的一个数据包从起始信号开始, 直到停止信号结束。 数据包的起始信号由一个逻辑 0 的数据位表示, 而数据包的停止信号可由 0.5、 1、 1.5 或 2 个逻辑 1 的数据位表示, 只要双方约定一致即可。

(3) 串口内部结构

在这里插入图片描述

SBUF(serial data bufferr)∶串口数据缓存寄存器,物理上是两个独立的寄存器,但占用相同的地址。写操作时,写入的是发送寄存器,读操作时,读出的是接收寄存器

上图中右边的 TXDRXD 为单片机 IO 口, TXD 对应的是 P3.1 管脚, RXD 对应的是 P3.0 管脚。 其内部工作方式在后面小节会介绍。

串口相关寄存器

在这里插入图片描述
下面介绍部分寄存器

(1) 串口控制寄存器 SCON
在这里插入图片描述
SM0 和 SM1 为工作方式选择位:
在这里插入图片描述

SM2: 多机通信控制位, 主要用于方式 2 和方式 3。 当 SM2=1 时可以利用收到的 RB8 来控制是否激活 RI(RB8=0 时不激活 RI, 收到的信息丢弃; RB8=1 时收到的数据进入 SBUF, 并激活 RI, 进而在中断服务中将数据从 SBUF 读走) 。 当SM2=0 时, 不论收到的 RB8 为 0 和 1, 均可以使收到的数据进入 SBUF, 并激活 RI(即此时 RB8 不具有控制 RI 激活的功能) 。 通过控制 SM2, 可以实现多机通信。

REN: 允许串行接收位。 由软件置 REN=1, 则启动串行口接收数据; 若软件置REN=0, 则禁止接收。

TB8: 在方式 2 或方式 3 中, 是发送数据的第 9 位, 可以用软件规定其作用。可以用作数据的奇偶校验位, 或在多机通信中, 作为地址帧/数据帧的标志位。在方式 0 和方式 1 中, 该位未用到。

RB8: 在方式 2 或方式 3 中, 是接收到数据的第 9 位, 作为奇偶校验位或地址帧/数据帧的标志位。 在方式 1 时, 若 SM2=0, 则 RB8 是接收到的停止位。

TI(transmit interrupt): 发送中断标志位。 在方式 0 时, 当串行发送第 8 位数据结束时, 或在其它方式, 串行发送停止位的开始时, 由内部硬件使 TI 置 1, 向 CPU 发中断申请。在中断服务程序中, 必须用软件将其清 0, 取消此中断申请。

RI(receive interrupt): 接收中断标志位。 在方式 0 时, 当串行接收第 8 位数据结束时, 或在其它方式, 串行接收停止位的同时, 由内部硬件使 RI 置 1, 向 CPU 发中断申请。也必须在中断服务程序中, 用软件将其清 0, 取消此中断申请。

(2) 电源控制寄存器 PCON
在这里插入图片描述
SMOD:波特率倍增位。 在串口方式 1、 方式 2、 方式 3 时, 波特率与 SMOD 有关, 当 SMOD=1 时, 波特率提高一倍。 复位时, SMOD=0。

串口工作方式

前面在介绍寄存器时已经知道了 51 单片机串口的几种工作方式, 下面分别来对它介绍。

方式0

方式 0 时, 串行口为同步移位寄存器的输入输出方式。 主要用于扩展并行输入或输出口。 数据由 RXD(P3.0) 引脚输入或输出, 同步移位脉冲由 TXD(P3.1)引脚输出。 发送和接收均为 8 位数据, 低位在先, 高位在后。 波特率固定为fosc/12(“fosc” 表示系统的振荡频率,“波特率 = fosc/12” 意味着每秒传输的符号数等于振荡频率除以12。例如,如果系统的振荡频率为120,000 Hz(也就是12MHz),那么根据这个公式,波特率将为120,000 Hz / 12 = 10,000 Baud。这意味着在每秒内会传输10,000个符号。)。 对应的输入输出时序图如下所示:

①方式 0 输出
在这里插入图片描述

②方式 0 输入
在这里插入图片描述

方式1

方式 1 是 10 位数据的异步通信口。 TXD 为数据发送引脚, RXD 为数据接收引脚, 传送一帧数据的格式如下所示。 其中 1 位起始位, 8 位数据位, 1 位停止位。
在这里插入图片描述
①方式 1 输出
在这里插入图片描述
②方式 1 输入
在这里插入图片描述
用软件置 REN 为 1 时, 接收器以所选择波特率的 16 倍速率采样 RXD 引脚电平, 检测到 RXD 引脚输入电平发生负跳变时, 则说明起始位有效, 将其移入输入移位寄存器, 并开始接收这一帧信息的其余位。 接收过程中, 数据从输入移位寄存器右边移入, 起始位移至输入移位寄存器最左边时, 控制电路进行最后一次移位。 当 RI=0, 且 SM2=0(或接收到的停止位为 1) 时, 将接收到的 9 位数据的前8 位数据装入接收 SBUF, 第 9 位(停止位) 进入 RB8, 并置 RI=1, 向 CPU 请求中断。

方式 2 和方式 3

方式 2 或方式 3 时为 11 位数据的异步通信口。 TXD 为数据发送引脚, RXD 为数据接收引脚。 其数据格式如下所示:
在这里插入图片描述
对应的输入输出时序图如下所示:
①方式 2、方式 3 输出
在这里插入图片描述
发送开始时, 先把起始位 0 输出到 TXD 引脚, 然后发送移位寄存器的输出位(D0)到 TXD 引脚。每一个移位脉冲都使输出移位寄存器的各位右移一位, 并由TXD 引脚输出。 第一次移位时, 停止位“1” 移入输出移位寄存器的第 9 位上,以后每次移位, 左边都移入 0。 当停止位移至输出位时, 左边其余位全为 0, 检测电路检测到这一条件时, 使控制电路进行最后一次移位, 并置 TI=1, 向 CPU请求中断。

②方式 2、 方式 3 输入
在这里插入图片描述

接收时, 数据从右边移入输入移位寄存器, 在起始位 0 移到最左边时, 控制电路进行最后一次移位。 当 RI=0, 且 SM2=0(或接收到的第 9 位数据为 1) 时,接收到的数据装入接收缓冲器 SBUF 和 RB8(接收数据的第 9 位) , 置 RI=1, 向CPU 请求中断。 如果条件不满足, 则数据丢失, 且不置位 RI, 继续搜索 RXD 引脚的负跳变。

串口的使用方法(计算波特率)

(1)如何计算波特率
在学习 51 单片机串口时, 非常重要的一点是学会如何计算波特率。 以下列出了几种方式下波特率的计算公式:
方式 0 的波特率 = fosc/12
方式 1 的波特率 =(2SMOD/32)×(T1 溢出率)
方式 2 的波特率 =(2SMOD/64)× fosc
方式 3 的波特率 =(2SMOD/32) ×(T1 溢出率)
其中 T1 溢出率 = fosc /{12× [256 -(TH1)]}, 当然还可以使用STC-ISP内附带的小工具自动生成波特率。
在这里插入图片描述

举个例子:
在这里插入图片描述

设TL1=0XF3

假设晶振频率为12MHZ,所以晶振周期为1/12M(单位是s)。定时器时钟为12T,也就是12个时钟周期(晶振周期),机器完成一条指令。
所以机器完成一条指令所需的时间为:1/12M×12=1/1M=1us

F3换算成2进制为243,需要13us才会溢出一次

所以溢出频率就是1/13us=0.07692307692307692307692307692308MHZ

SMOD置为1,则走上面,无需除以2;置于0,则走下面,需要除以2,相当于波特率减倍

最后波特率=0.07692307692307692307692307692308MHZ÷16=0.00480769MHZ=4807.69HZ

为什么最后不是4800hz呢?因为这就是设计不够精细有误差,用STC-ISP中的小工具波特率计算器计算也可知:
在这里插入图片描述
会有0.16%的误差,这多出来的7.69正好就是0.16%的误差
在这里插入图片描述

(2) 串口初始化步骤
如何使用串口, 大家可以按照以下几个步骤配置。
①确定 T1 的工作方式(TMOD 寄存器) ;
②确定串口工作方式(SCON 寄存器) ;
③计算 T1 的初值(设定波特率) , 装载 TH1、 TL1;
④启动 T1(TCON 中的 TR1 位) ;
⑤如果使用中断, 需开启串口中断控制位(IE 寄存器) 。
例如: 设置串口为工作方式 1、 波特率为 9600、 波特率加倍、 使用中断。 其配置程序如下:

/*******************************************************************************
* 函 数 名 : uart_init
* 函数功能 : 串口通信中断配置函数, 通过设置 TH 和 TL 即可确定定时时间
* 输 入 : baud: 波特率对应的 TH、 TL 装载值
* 输 出 : 无
*******************************************************************************/
void uart_init(u8 baud)
{
TMOD|=0X20; //设置计数器工作方式 2
SCON=0X50; //设置为工作方式 1
PCON=0X80; //波特率加倍
TH1=baud; //计数器初始值设置
TL1=baud;
ES=1; //打开接收中断
EA=1; //打开总中断
TR1=1; //打开计数器
}

在主函数中调用该函数并传入 0XFA 值即可, 如下:

uart_init(0XFA);//波特率为 9600

硬件设计

开发板上板载一个 USB 转串口模块。 其硬件电路如下所示:
在这里插入图片描述

软件设计

本节所要实现的功能是:

1、向单片机发送数据 0x11

#include "reg52.h"void UartInit(void)		//4800bps@11.0592MHz
{PCON |= 0x80;		//使能波特率倍速位SMOD,也就是使波特率提高一倍SCON = 0x40;		//8位数据,可变波特率TMOD &= 0x0F;		//清除定时器1模式位,也就是高4位全部置为0TMOD |= 0x20;		//设定定时器1为8位自动重装方式TL1 = 0xF4;		//设定定时初值TH1 = 0xF4;		//设定定时器重装值ET1 = 0;		//禁止定时器1中断TR1 = 1;		//启动定时器1
}void UART_SendByte(unsigned char Byte)
{SBUF=Byte;while(T1==0);T1=0;
}void main()
{UartInit();UART_SendByte(0x11);while(1){}
}

把程序下载进板子,设置好串口号和波特率后(校验位一般设置为无校验,停止位一般设置为1位),点击51单片机开发板上的复位键,上方的白框中就会显示11
在这里插入图片描述

2、向单片机发送一个不断加1的数

#include "reg52.h"typedef unsigned int u16;
unsigned char Sec=0;void delay(u16 i)
{while(i--);
}void UartInit(void)		//4800bps@11.0592MHz
{PCON |= 0x80;		//使能波特率倍速位SMOD,也就是使波特率提高一倍SCON = 0x40;		//8位数据,可变波特率TMOD &= 0x0F;		//清除定时器1模式位,也就是高4位全部置为0TMOD |= 0x20;		//设定定时器1为8位自动重装方式TL1 = 0xF4;		//设定定时初值TH1 = 0xF4;		//设定定时器重装值ET1 = 0;		//禁止定时器1中断TR1 = 1;		//启动定时器1
}void UART_SendByte(unsigned char Byte)
{SBUF=Byte;while(TI==0);TI=0;
}void main()
{UartInit();while(1){		UART_SendByte(Sec);Sec++;delay(1000000);		}
}

在这里插入图片描述

3、通过电脑端发送一个数据去点亮led灯

中断号为4的中断是串口中断,随意向51单片机发送一个数据,即可触发该中断,从而点亮对应的led灯

#include "reg52.h"void UartInit(void)		//4800bps@11.0592MHz
{PCON |= 0x80;		//使能波特率倍速位SMOD,也就是使波特率提高一倍SCON = 0x50;		//8位数据,可变波特率TMOD &= 0x0F;		//清除定时器1模式位,也就是高4位全部置为0TMOD |= 0x20;		//设定定时器1为8位自动重装方式TL1 = 0xF4;		//设定定时初值TH1 = 0xF4;		//设定定时器重装值ET1 = 0;		//禁止定时器1中断TR1 = 1;		//启动定时器1EA=1;ES=1;
}void main()
{UartInit();while(1){			}
}void UART_Routine() interrupt 4
{if(RI==1){P2=SBUF;RI=0;}}

串口在接收到数据之后,硬件会自动将RI=1。
只要RI>=1或者TI>=1就会触发串口中断,也就是发送和接收都会触发中断。前提是程序打开了总中断和串口中断。
为什么要加if(RI==1)判断?因为发送和接收都会触发中断,当接收了时,RI会被自动置为1。
这样根据P2被赋给的值即可点亮相应的led灯

在这里插入图片描述
最右边四个灯会亮起

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Junit常用注解

注解是方法的“标签” 说明每个方法的“职责” Q:总共有那些注解? 参见官方的API文档 0.常用主机及其特点 BeforeClass 只会执行一次必须用static修饰常用来初始化测试需要的变量 Before 会执行多次(只要写一次)在每个Test执行执行之前执行可以和…

VTK 三维场景的基本要素(相机) vtkCamera

观众的眼睛好比三维渲染场景中的相机,在VTK中用vtkCamera类来表示。vtkCamera负责把三维场景投影到二维平面,如屏幕,相机投影示意图如下图所示。 1.与相机投影相关的要素主要有如下几个: 1)相机位置: 相机所处的位置…

文件的操作(上)

上一期代码题中我们补充一下,代码1中我们创建了一个指针变量来接收我们开辟的空间的首地址,出了函数只是变量被销毁,但是我们在堆区申请的空间却不会自己销毁,这样容易造成内存泄漏,只有等整个程序结束,才会…

[2024]常用的pip指令

[2024]常用的pip指令 HI,这里是肆十二,好久不见,大家! 新年好! pip是Python的包管理工具,它可以用来安装、升级、卸载Python包。以下是一些常用的pip指令: 安装包: bash复制代码…

C#,泰波拿契数(Tribonacci Number)的算法与源代码

1 泰波拿契数(Tribonacci Number) 泰波拿契数(Tribonacci Number)是斐波那契的拓展。 泰波拿契数 (Tribonacci Number) 即把费波拿契数 (Fibonacci Number) 的概念推广至三个数。 2 计算结果 3 源程序 using System; namespace…

通过平扫CT实现胰腺癌早筛(平扫CT+AI)

Large-scale pancreatic cancer detection via non-contrast CT and deep learning - PubMed (nih.gov) 实验团队:海军军医大学第一附属医院(上海长海医院),放射诊断科曹凯主治医生为共同第一作者,邵成伟、陆建平等教…

Linux笔记之Docker进行镜像备份与迁移

Linux笔记之Docker进行镜像备份与迁移 ——2024-02-11 code review! 文章目录 Linux笔记之Docker进行镜像备份与迁移1. 导出容器文件系统为 tar 归档文件2. 将 tar 归档文件导入为新的 Docker 镜像3. 运行新的 Docker 镜像并创建容器 1. 导出容器文件系统为 tar 归档文件 要导…

Windows快捷键大全(包含语音输入、剪切板历史快捷键)

最近发现了微软官网上给出的快捷键大全,并且使用了其中几个新的键盘快捷键(语音输入、剪切板历史),确实方便快捷,所以写个博客记录分享一下。 注:windows快捷键大全微软官方已经给出,此处不再赘…

每日一练:LeeCode-654、最大二叉树【二叉树+DFS+分治】

本文是力扣LeeCode-654、最大二叉树【二叉树DFS分治】 学习与理解过程,本文仅做学习之用,对本题感兴趣的小伙伴可以出门左拐LeeCode。 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点,其…

OpenCV-36 多边形逼近与凸包

目录 一、多边形的逼近 二、凸包 一、多边形的逼近 findContours后的轮廓信息countours可能过于复杂不平滑,可以用approxPolyDP函数对该多边形曲线做适当近似,这就是轮廓的多边形逼近。 apporxPolyDP就是以多边形去逼近轮廓,采用的是Doug…

git合入的parents和child

最近在管理代码,有2的权限,看到一些以前1看不到的东西。 有时候会遇到多个人基于同一节点提交代码,那就要选择先合入和后合入,如果这多人修改到同一个文件同一个地方,就可能产生冲突,一般要避免这种情况出…

Kotlin和Java 单例模式

Java 和Kotlin的单例模式其实很像,只是Kotlin一部分单例可以用对象类和委托lazy来实现 Java /*** 懒汉式,线程不安全*/ class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (insta…

Unity学习笔记(零基础到就业)|Chapter04:C#篇补充到Unity篇过渡

Unity学习笔记(零基础到就业)|Chapter02:C#篇补充到Unity篇过渡 前言C#总结补充1.值类型和引用类型有什么区别,他们在值的传递上分别有怎样的特性2.string是引用类型,但是他对外表现出值类型的特性,为什么&…

联想thinkpad-E450双系统升级记

早期笔记本联想thinkpad-E450双系统 大约16年花4000多大洋,买了一台thinkpad-L450屏幕是16寸本,有AMD独立显卡,i5cpu,4G内存。 . 后来加了一个同型号4G内存组成双通道, . 加了一个三星固态500G, . 换了一个…

【leetcode热题100】反转链表 II

给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#xff1a;[1,4,3,2…

Java 基于微信小程序的电子商城购物系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

160基于matlab的负熵和峭度信号的盲分离

基于matlab的负熵和峭度信号的盲分离。基于峭度的FastICA算法的收敛速度要快&#xff0c;迭代次数比基于负熵的FastICA算法少四倍以上。SMSE随信噪比增大两种判据下的FastICA算法都逐渐变小&#xff0c;但是基于峭度的算法的SMSE更小&#xff0c;因此基于峭度的FastICA算法性能…

Vue源码系列讲解——模板编译篇【一】(综述)

目录 1. 前言 2. 什么是模板编译 3. 整体渲染流程 4. 模板编译内部流程 4.1 抽象语法树AST 4.2 具体流程 5. 总结 1. 前言 在前几篇文章中&#xff0c;我们介绍了Vue中的虚拟DOM以及虚拟DOM的patch(DOM-Diff)过程&#xff0c;而虚拟DOM存在的必要条件是得先有VNode&…

c++猜数游戏

一.题目要求 系统随机产生1~100的随机数,进行猜数,如果猜的数过大提示猜数过大,过小提出猜数过小,直到猜出正确的数字 二.代码 三.示例

嵌入式电子产品开发感悟!

​ 2023特别深有感触的有以下几个事件&#xff1a; 1. 早在2月底就提交报告&#xff1a;抓紧开一款便携式的空气波压力按摩仪外壳&#xff0c;包括模具费和100台试产物料费用总计不超过22W&#xff0c;保证最迟在4月中旬全部生产好&#xff0c;以供业务参加5月份开始的大健康展…