#循循渐进学51单片机#UART串口通信#not.10

news2024/11/17 19:45:10

1、能够理解UART串口通信的基本原理和通信过程。

1)串行通信的初步认识

并行通信:通信时数据的各个位同时传送,可以实现字节为单位通信,但是通信线占用资源太多,成本高。

串行通信:一次只能发送一位,要发送8次才能发送一个字节。


2、通过IO口模拟UART串口通信把通信的底层操作原理弄明白。

首先是对通信的波特率的设定,在这里我们配置的波特率是9600,那么串口调试助手也得是9600。配置波特率的时候,我们用的是定时器T0的模式2。模式2中,不再是TH0代表高8位,TL0代表低8位了,而只有TL0在进行计数,当TL0溢出后,不仅仅会让TF0变1,而且还会将TH0中的内容重新自动装到TL0中。这样有一个好处,就是我们可以把想要的定时器初值提前存在TH0中,当TL0溢出后,TH0自动把初值就重新送入TL0了,全自动的,不需要程序中再给TL0重新赋值了,配置方式很简单,大家可以自己看下程序并且计算一下初值。

      波特率设置好以后,打开中断,然后等待接收串口调试助手下发的数据。接收数据的时候,首先要进行低电平检测while (PIN_RXD),若没有低电平则说明没有数据,一旦检测到低电平,就进入启动接收函数StartRXD()。接收函数最开始启动半个波特率周期,初学可能这里不是很明白。大家回头看一下,如果在数据位电平变化的时候去读取,因为时序上的误差以及信号稳定性的问题很容易读错数据,所以我们希望在信号最稳定的时候去读数据。除了信号变化的那个沿的位置外,其它位置都很稳定,那么我们现在就约定在信号中间位置去读取电平状态,这样能够保证我们读的一定是正确的。

      一旦读到了起始信号,我们就把当前状态设定成接收状态,并且打开定时器中断,第一次是半个周期进入中断后,对起始位进行二次判断一下,确认一下起始位是低电平,而不是一个干扰信号。以后每经过1/9600秒进入一次中断,并且把这个引脚的状态读到RxdBuf里边。等待接收完毕之后,我们再把这个RxdBuf加1,再通过TXD引脚发送出去,同样需要先发一位起始位,然后发8个数据位,再发结束位,发送完毕后,程序运行到while (PIN_RXD),等待第二轮信号接收的开始。

#include <reg52.h>

sbit PIN_RXD = P3^0;  //½ÓÊÕÒý½Å¶¨Òå
sbit PIN_TXD = P3^1;  //·¢ËÍÒý½Å¶¨Òå

bit RxdOrTxd = 0;  //ָʾµ±Ç°×´Ì¬Îª½ÓÊÕ»¹ÊÇ·¢ËÍ
bit RxdEnd = 0;    //½ÓÊÕ½áÊø±êÖ¾
bit TxdEnd = 0;    //·¢ËͽáÊø±êÖ¾
unsigned char RxdBuf = 0;  //½ÓÊÕ»º³åÆ÷
unsigned char TxdBuf = 0;  //·¢ËÍ»º³åÆ÷

void ConfigUART(unsigned int baud);
void StartTXD(unsigned char dat);
void StartRXD();

void main()
{
    EA = 1;   //¿ª×ÜÖжÏ
    ConfigUART(9600);  //ÅäÖò¨ÌØÂÊΪ9600
    
    while (1)
    {
        while (PIN_RXD);    //µÈ´ý½ÓÊÕÒý½Å³öÏֵ͵çƽ£¬¼´Æðʼλ
        StartRXD();         //Æô¶¯½ÓÊÕ
        while (!RxdEnd);    //µÈ´ý½ÓÊÕÍê³É
        StartTXD(RxdBuf+1); //½ÓÊÕµ½µÄÊý¾Ý+1ºó£¬·¢ËÍ»ØÈ¥
        while (!TxdEnd);    //µÈ´ý·¢ËÍÍê³É
    }
}
void ConfigUART(unsigned int baud)
{
	TMOD &= 0XF0;
	TMOD |= 0X02;
	TH0 = 256 -(11059200/12)/baud;
}
void   StartRXD()
{
	TL0 = 256 - ((256-TH0)>>1);
	ET0 = 1;
	TR0 = 1;
	RxdEnd = 0;
	RxdOrTxd = 0;
}
void StartTXD(unsigned char dat)
{
	RxdBuf = dat;
	TL0 = TH0;
	ET0 = 1;
	TR0 = 1;
	PIN_RXD = 0;
	TxdEnd = 0;
	RxdOrTxd = 1;
}
void InterruptTimer0() interrupt 1
{
	static unsigned char cnt = 0;
  if(RxdOrTxd)
	{
	 cnt++;
		if(cnt <= 8)
		{
		PIN_TXD = TxdBuf & 0x01;
		TxdBuf >>= 1;
		}
		else if(cnt ==9)
		{
		PIN_TXD = 1;
		}
		else
		{
		cnt = 0;
		TR0 = 1;
		TxdEnd = 1;			
		}
	}
	else
 {
 if(cnt == 0)
 {
     if(!PIN_RXD)
		 {
		 RxdEnd = 0;
			 cnt++;
		 }
		 else
			{
		  TR0 = 0;
		  }
 }
 else if(cnt <= 8)
 {
  RxdBuf >>= 1;
	 if(PIN_RXD)
	 {
       RxdBuf |= 0x80;
	 }
	 cnt++;
 }
 else
 {
            cnt = 0;
            TR0 = 0;       
            if (PIN_RXD)    
            {
                RxdEnd = 1; 
            }
 }
 }
}

3、学会通过配置寄存器,实现串口通信的基本操作过程。

UART模块介绍

      IO口模拟串口通信,让大家了解了串口通信的本质,但是我们的单片机程序却需要不停的检测扫描单片机IO口收到的数据,大量占用了单片机的运行时间。这时候就会有聪明人想了,其实我们并不是很关心通信的过程,我们只需要一个通信的结果,最终得到接收到的数据就行了。这样我们可以在单片机内部做一个硬件模块,让它自动接收数据,接收完了,通知我们一下就可以了,我们的51单片机内部就存在这样一个UART模块,要正确使用它,当然还得先把对应的特殊功能寄存器配置好。

      51单片机的UART串口的结构由串行口控制寄存器SCON、发送和接收电路三部分构成,先来了解一下串口控制寄存器SCON。如表11-1表11-2所示。

                                      SCON——串行控制寄存器的位分配(地址0x98、可位寻址)

7

6

5

4

3

2

1

0

符号

SM0

SM1

SM2

REN

TB8

RB8

TI

RI

复位值

0

0

0

0

0

0

0

0

    

                                                   SCON——串行控制寄存器的位描述

符号

描述

7

SM0

这两位共同决定了串口通信的模式0~模式3共4种模式。我们最常用的就是模式1,也就是SM0=0,SM1=1,下边我们重点就讲模式1,其它模式从略。

6

SM1

5

SM2

多机通信控制位(极少用),模式1直接清零。

4

REN

使能串行接收。由软件置位使能接收,软件清零则禁止接收。

3

TB8

模式2和3中要发送的第9位数据(很少用)。

2

RB8

模式2和3中接收到的第9位数据(很少用),模式1用来接收停止位。

1

TI

发送中断标志位,当发送电路发送到停止位的中间位置时,TI由硬件置1,必须通过软件清零。

0

RI

接收中断标志位,当接收电路接收到停止位的中间位置时,RI由硬件置1,必须通过软件清零。

  

      前边学了那么多寄存器的配置,相信SCON这个地方,对于大多数同学来说已经不是难点了,应该能看懂并且可以自己配置了。对于串口的四种模式,模式1是最常用的,就是我们前边提到的1位起始位,8位数据位和1位停止位。下面我们就详细介绍模式1的工作细节和使用方法,至于其它3种模式与此也是大同小异,真正遇到需要使用的时候大家再去查阅相关资料就行了。

      在我们使用IO口模拟串口通信的时候,串口的波特率是使用定时器T0的中断体现出来的。在硬件串口模块中,有一个专门的波特率发生器用来控制发送和接收数据的速度。对于STC89C52单片机来讲,这个波特率发生器只能由定时器T1或定时器T2产生,而不能由定时器T0产生,这和我们模拟的通信是完全不同的概念。

      如果用定时器2,需要配置额外的寄存器,默认是使用定时器1的,我们本章内容主要就使用定时器T1作为波特率发生器来讲解,方式1下的波特率发生器必须使用定时器T1的模式2,也就是自动重装载模式,定时器的重载值计算公式为:

      TH1 = TL1 = 256 - 晶振值/12 /2/16 /波特率 

     和波特率有关的还有一个寄存器,是一个电源管理寄存器PCON,他的最高位可以把波特率提高一倍,也就是如果写PCON |= 0x80以后,计算公式就成了:

    TH1 = TL1 = 256 - 晶振值/12 /16 /波特率

      公式中数字的含义这里解释一下,256是8位定时器的溢出值,也就是TL1的溢出值,晶振值在我们的开发板上就是11059200,12是说1个机器周期等于12个时钟周期,值得关注的是这个16,我们来重点说明。在IO口模拟串口通信接收数据的时候,采集的是这一位数据的中间位置,而实际上串口模块比我们模拟的要复杂和精确一些。他采取的方式是把一位信号采集16次,其中第7、8、9次取出来,这三次中其中两次如果是高电平,那么就认定这一位数据是1,如果两次是低电平,那么就认定这一位是0,这样一旦受到意外干扰读错一次数据,也依然可以保证最终数据的正确性。

      了解了串口采集模式,在这里要给大家留一个思考题。“晶振值/12/2/16/波特率”这个地方计算的时候,出现不能除尽,或者出现小数怎么办,允许出现多大的偏差?把这部分理解了,也就理解了我们的晶振为何使用11.0592M了。

      串口通信的发送和接收电路在物理上有2个名字相同的SBUF寄存器,它们的地址也都是0x99,但是一个用来做发送缓冲,一个用来做接收缓冲。意思就是说,有2个房间,两个房间的门牌号是一样的,其中一个只出人不进人,另外一个只进人不出人,这样的话,我们就可以实现UART的全双工通信,相互之间不会产生干扰。但是在逻辑上呢,我们每次只操作SBUF,单片机会自动根据对它执行的是“读”还是“写”操作来选择是接收SBUF还是发送SBUF,后边通过程序,我们就会彻底了解这个问题。

#include <REGX52.H>
void ConfigUART(unsigned int baud);
void main()
{
		EA =1;
ConfigUART(9600);
	while(1);
	
}
void ConfigUART(unsigned int baud)
{
   SCON  = 0x50;
	TMOD &= 0x0F;
	TMOD |= 0x02;
	TH1 = 256 - (11059200/12/32)/baud;
	TH1 =TL0;
	ET1 = 0;
	TR1 = 1;
}
void InterruptUART() interrupt 4
{
   if(RI)
	{
	RI = 0;
		SBUF++;
	}
	if(TI)
	{
	TI = 0;
	}
}

4、了解字符和数据之间的转换依据和方法。

  我们用字符格式发送一个小写的a,返回一个十六进制的0x61,数码管上显示的也是61,ASCII码表里字符a对应十进制是97,等于十六进制的0x61;我们再用字符格式发送一个数字1,返回一个十六进制的0x31,数码管上显示的也是31,ASCII表里字符1对应的十进制是49,等于十六进制的0x31。这下大家就该清楚了:所谓的十六进制发送和十六进制接收,都是按字节数据的真实值进行的;而字符格式发送和字符格式接收,是按ASCII码表中字符形式进行的,但它实际上最终传输的还是一个字节数据。这个表格,当然不需要大家去记住,理解它,用的时候过来查就行了。

5、完成通过串口控制流水灯流动和停止的程序。

#include <reg52.h>

sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

unsigned char code LedChar[] = { 
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
unsigned char LedBuff[7] = {  
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
unsigned char T0RH = 0;  
unsigned char T0RL = 0; 
unsigned char RxdByte = 0;  
unsigned char flag200ms = 0; 
unsigned char flagLight = 1;

void ConfigTimer0(unsigned int ms);
void ConfigUART(unsigned int baud);
void FlowingLight();

void main()
{
	EA = 1;
	ADDR3 = 1;
	ENLED = 0;
  ConfigTimer0(1);
	ConfigUART(9600);
	while(1)
	{
	if(flagLight == 0)
	{
		LedBuff[6]= 0XFF;
	}
	else
	{
	if (flag200ms != 0)  
            {
                flag200ms = 0;
                FlowingLight();
            }
	}
	      LedBuff[0] = LedChar[RxdByte & 0x0F];
        LedBuff[1] = LedChar[RxdByte >> 4];
	}
	
}
void FlowingLight()
{
 static unsigned char dir = 0;
 static unsigned char shift = 0x01; 
	
	LedBuff[6] = ~shift;
	if(dir == 0)
	{
	  shift = shift << 1; 
		if(shift == 0x80)
		{
		dir = 1;
		}
	}
	else
	{
	 shift = shift >> 1;
		if(shift == 0x01)
		{
		dir = 0;
		}
	}
}
void ConfigTimer0(unsigned int ms)
{
    unsigned long tmp;  
    
    tmp = 11059200 / 12;     
    tmp = (tmp * ms) / 1000;  
    tmp = 65536 - tmp;        
    tmp = tmp + 13;       
    T0RH = (unsigned char)(tmp>>8);  
    T0RL = (unsigned char)tmp;
    TMOD &= 0xF0;   
    TMOD |= 0x01;  
    TH0 = T0RH;    
    TL0 = T0RL;
    ET0 = 1;        
    TR0 = 1;        
}
void ConfigUART(unsigned int baud)
{
	SCON = 0X50;
	TMOD &=  0X0F;
	TMOD |= 0X02;
	TH1 = (11059200/12/32)/baud;
	TL1 = TH1;
	ET1 = 0;
	ES = 1;
	TR1 = 1;
}
void LedScan()
{
    static unsigned char i = 0; 
    
    P0 = 0xFF;            
    P1 = (P1 & 0xF8) | i;  
    P0 = LedBuff[i];       
    if (i < 6)            
        i++;
    else
        i = 0;
}
void InterruptTimer0() interrupt 1
{
	static unsigned char tmr200ms = 0;

		TH0 = T0RH;
	  TL0 = T0RL;
	  LedScan();
	tmr200ms++;
	if(tmr200ms >= 200)
	{
	tmr200ms = 0;
  flag200ms = 1;
	}
}
void InterruptUART() interrupt 4
{
   if(RI)
	 {
	 RxdByte = SBUF;
	 SBUF = RxdByte;
		 RI = 0;
	
	flagLight = !flagLight;	 
	 }
	 if(TI)
	 {
	 TI = 0;
	 }
}


6、完成通过串口实现蜂鸣器鸣叫的程序。

#include <reg52.h>

sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit BUZZ  = P1^6;

unsigned char code LedChar[] = { 
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
unsigned char LedBuff[7] = {  
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
unsigned char T0RH = 0;  
unsigned char T0RL = 0; 
unsigned char RxdByte = 0;  
unsigned char flagBuzz = 0;

void ConfigTimer0(unsigned int ms);
void ConfigUART(unsigned int baud);

void main()
{
	EA = 1;
	ADDR3 = 1;
	ENLED = 0;
  ConfigTimer0(1);
	ConfigUART(9600);
	while(1)
	{
	      LedBuff[0] = LedChar[RxdByte & 0x0F];
        LedBuff[1] = LedChar[RxdByte >> 4];
	}
	
}

void ConfigTimer0(unsigned int ms)
{
    unsigned long tmp;  
    
    tmp = 11059200 / 12;     
    tmp = (tmp * ms) / 1000;  
    tmp = 65536 - tmp;        
    tmp = tmp + 13;       
    T0RH = (unsigned char)(tmp>>8);  
    T0RL = (unsigned char)tmp;
    TMOD &= 0xF0;   
    TMOD |= 0x01;  
    TH0 = T0RH;    
    TL0 = T0RL;
    ET0 = 1;        
    TR0 = 1;        
}
void ConfigUART(unsigned int baud)
{
	SCON = 0X50;
	TMOD &=  0X0F;
	TMOD |= 0X20;
	TH1 = (11059200/12/32)/baud;
	TL1 = TH1;
	ET1 = 0;
	ES = 1;
	TR1 = 1;
}
void LedScan()
{
    static unsigned char i = 0; 
    
    P0 = 0xFF;            
    P1 = (P1 & 0xF8) | i;  
    P0 = LedBuff[i];       
    if (i < 6)            
        i++;
    else
        i = 0;
}
void InterruptTimer0() interrupt 1
{
		TH0 = T0RH;
	  TL0 = T0RL;
	  LedScan();
	if(flagBuzz == 0)
	    BUZZ = 1;    
	else
			BUZZ = ~BUZZ;    
}
void InterruptUART() interrupt 4
{
   if(RI)
	 {
	 RxdByte = SBUF;
	 SBUF = RxdByte;
		 RI = 0;
	if(RxdByte == 'B')
	{
	 flagBuzz = !flagBuzz;
	}
	 }
	 if(TI)
	 {
	 TI = 0;
	 }
}

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

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

相关文章

debian终端快捷键设置

为了方便使用图形化debian&#xff0c;快捷调出shell终端是提升工作学习效率的最重要的一步。 1.首先点击右上角&#xff0c;选择设置 2.点击键盘&#xff0c;选择快捷键&#xff0c;并创建自定义快捷键 3.点击添加快捷键 4.根据图中提示创建快捷键 Name: Terminal Command…

软考网络工程师华为配置考点总结

华为交换机配置基础 1.vlan的配置 华为设备中划分VLAN的方式有&#xff1a; 静态的划分&#xff1a;基于接口动态划分&#xff1a;基于MAC地址、基于IP子网、基于协议、基于策略&#xff08;MAC地址、Ip地址&#xff09;。 其中基于接口划分VLAN&#xff0c;是最简单&#x…

Arduino程序设计(十一)8×8 共阳极LED点阵显示(74HC595)

88 共阳极LED点阵显示 前言一、74HC595点阵模块1、74HC595介绍2、74HC595工作原理3、1088BS介绍4、74HC595点阵模块 二、点阵显示实验1、点阵显示初探2、点阵显示进阶3、点阵显示高阶3.1 点阵显示汉字&#xff08;方法1&#xff09;3.2 点阵显示汉字&#xff08;方法2&#xff…

不用addEventListener(‘resize‘, this.resize),用新的Web API ResizeObserver监听DIV元素尺寸的变化

响应式设计指的是根据屏幕视口尺寸的不同&#xff0c;对 Web 页面的布局、外观进行调整&#xff0c;以便更加有效地进行信息的展示。我们日常生活中接触的很多应用都遵循响应式的设计。 响应式设计如今也成为 web 应用的基本需求&#xff0c;而现在很多 web 应用都已经组件化&a…

华为云云耀云服务器L实例评测 |云服务器选购

华为云耀云服务器 L 实例是一款轻量级云服务器&#xff0c;开通选择实例即可立刻使用&#xff0c;不需要用户再对服务器进行基础配置。新用户还有专享优惠&#xff0c;2 核心 2G 内存 3M 带宽的服务器只要 89 元/年&#xff0c;可以点击华为云云耀云服务器 L 实例购买地址去购买…

如何在新浪、搜狐、腾讯、网易、人民网等知名媒体网站上投稿

网络通稿成本低、投入小&#xff0c;软文宣传成为了众多企业的宣传选择&#xff0c;一篇优质的稿件更是能带来惊人的效果。越知名的网站传播效果越好&#xff0c;像新浪、搜狐、腾讯、网易、人民网等&#xff0c;那么如果找到这些网站投稿呢&#xff0c;本期盒子分享&#xff0…

[Go疑难杂症]为什么nil不等于nil

现象 在日常开发中&#xff0c;可能一不小心就会掉进 Go 语言的某些陷阱里&#xff0c;而本文要介绍的 nil ≠ nil 问题&#xff0c;便是其中一个&#xff0c;初看起来会让人觉得很诡异&#xff0c;摸不着头脑。 先来看个例子&#xff1a; type CustomizedError struct {Err…

MySQL的进阶篇1-MySQL的存储引擎简介

存储引擎 MySQL的体系结构 0、客户端连机器【java、Python、JDBC等】 1、【MySQL服务器-连接层】认证&#xff0c;授权&#xff0c;连接池 2、【MySQL服务器-服务层】 {SQL接口&#xff08;DML、DDL、存储过程、触发器&#xff09;、解析器、查询优化器、缓存} 3、【MySQL…

C8051F020 SMBus一直处于busy状态解决办法

当SMBus总线处于busy状态切且无法自动释放时&#xff0c;SMB0CN寄存器的第7位一直为 1&#xff0c;总线没有释放。 SMBus总线释放超时的一个纠错机制&#xff0c;它允许SMBus状态机在 SDA 和 SCL 信号线同为高电平超过 10个SMBus时钟源周期后判断总线为释放状态。 如果总线释放…

Linux下gdb常规调试

Linux系统&#xff1a;ubuntu-20.04 gdb简介 gdb 全称“GNU symbolic debugger”&#xff0c;从名称上不难看出&#xff0c;它诞生于 GNU 计划&#xff08;同时诞生的还有 GCC、Emacs 等&#xff09;&#xff0c;是 Linux 下常用的程序调试器。发展至今&#xff0c;GDB 已经迭…

代码随想录算法训练营day59|503.下一个更大元素II |42.接雨水

503.下一个更大元素II 力扣题目链接 给定一个循环数组&#xff08;最后一个元素的下一个元素是数组的第一个元素&#xff09;&#xff0c;输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序&#xff0c;这个数字之后的第一个比它更大的数&#xff0c…

【面试必刷TOP101】 删除有序链表中重复的元素-I 删除有序链表中重复的元素-II

目录 题目&#xff1a;删除有序链表中重复的元素-I_牛客题霸_牛客网 (nowcoder.com) 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 题目&#xff1a;删除有序链表中重复的元素-II_牛客题霸_牛客网 (nowcoder…

CTF--攻防世界杂项--第二课

下载题目根据文件类型可知&#xff0c;这是一个流量包 那么接下来就是利用分析流量包常用的工具wireshark来分析 利用关键词进行搜索 http contains shell 在最后一条数据中看到了flag。 以上就结束&#xff0c;非常简单的一道题。

nginx相关漏洞处理:CVE-2016-2183、CVE-2022-41741、CVE-2022-41742

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、漏洞内容二、现状三、centos7安装openssl11四、升级nginx到1.24.01. 下载nginx2. 编译安装nginx3. 配置nginx.service4. 重启nginx 总结 前言 漏扫发现机器…

[maven] 使用 Nexus 管理 repository

[maven] 使用 Nexus 管理 repository 大概是说还有一篇笔记&#xff0c;两篇内容&#xff0c;maven 的内容就差不多过完了。这一篇笔记主要记一下 maven 的 central 管理部分&#xff0c;之前提到过我们公司用的就是 nexux 做了一个镜像&#xff0c;这里也会用 docker 去创建一…

力扣刷题-数组-滑动窗口法相关题目总结

209. 长度最小的子数组&#xff08;最小滑窗&#xff09; 给定一个含有 n 个正整数的数组和一个正整数 s &#xff0c;找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组&#xff0c;并返回其长度。如果不存在符合条件的子数组&#xff0c;返回 0。 示例&#xff1a; 输入&…

uniapp确认提示框;uniapp判断输入框值是否符合正常手机号,身份证号

确认提示框 UniApp 中&#xff0c;你可以使用 uni.showModal 方法来创建确认提示框。以下是一个示例&#xff1a; <template><view class"container"><button click"showAuthModal">显示确认提示框</button></view> </…

react实现动态递增展示数字特效

在可视化展示界面时有一种场景&#xff0c;就是页面在初始化的时候&#xff0c;有些数字展示想要从某个值开始动态递增到实际值&#xff0c;形成一种动画效果。例如&#xff1a; 写一个数字递增的组件&#xff0c;代码如下&#xff1a; import {useEffect, useRef, useState} f…

软考网络工程师IPSEC VPN配置考点总结

IPSEC VPN&#xff08;华为&#xff09;工作流程 配置安全ACL&#xff1a;配置哪些流量需要被保护配置安全提议&#xff1a;配置IPsec的参数配置IKE&#xff1a;预共享密钥&#xff0c;配置身份验证方法、加密算法等安全参数配置安全策略&#xff1a;1和2做关联在接口应用安全…

文件系统之程序是怎么打开文件进行操作的

本篇文章自顶向下&#xff0c;从文件系统的上层出发讲到磁盘&#xff0c;帮助理解程序是如何打开文件并进行后序的读写操作的&#xff0c;读到后面&#xff0c;前面的一些疑惑就得到解决 介绍相关概念 注意&#xff0c;目录也是文件 文件描述符 每个进程都有一个指针*files…