51单片机--AD/DA

AD/DA介绍

AD和DA是模拟信号和数字信号之间的转换过程。
AD,全称为模拟到数字(Analog-to-Digital),指的是将模拟信号转换为数字信号的过程。在AD转换中,模拟信号经过采样、量化和编码等步骤,被转换为离散的数字信号。这样可以更方便地处理和传输信号,在数字系统中进行数字信号的处理和分析。
DA,全称为数字到模拟(Digital-to-Analog),指的是将数字信号转换为模拟信号的过程。在DA转换中,数字信号经过解码和重构处理,被转换为连续的模拟信号。这样可以将数字信号转换为模拟信号,使其能够被模拟系统接收和处理。
AD和DA转换常见于各种电子设备和系统中,例如音频设备、通信系统、传感器等。AD转换可以将实际物理量(如声音、温度、光强)转换为数字形式进行处理,而DA转换则可以将数字信号转换为模拟形式输出到外部设备或环境中
AD和DA转换的准确性和性能对于系统的精度和稳定性至关重要,因此在设计和选择AD和DA转换器时需要考虑多个因素,如分辨率、采样率、信噪比、线性度等。
在这里插入图片描述

硬件电路模型

在这里插入图片描述

AD转换电路

  1. 采样电路:根据采样信号,对要转换的模拟量进行抽样,通常使用开关电容电路或采样保持电路实现。
  2. 模拟信号输入电路:将要转换的模拟信号经过滤波、放大等处理后输入到采样电路。
    该电路通常包括输入缓冲器、低通滤波器和增益放大器等。
  3. A/D转换器(ADC):采样电路输出的模拟信号通过ADC芯片进行转换。ADC芯片可能采用逐次逼近法、积分法或其他转换方法。
  4. 数字信号输出:转换后的数字信号通过总线或其他方式传输给单片机

DA转换电路

  1. 数字信号输入:单片机通过总线或其他方式将要转换的数字信号输入到DA转换电路。
  2. D/A转换器(DAC):数字信号经过DAC芯片进行转换,DAC芯片可能采用R-2R网络、串行接口或其他转换方法。
  3. 模拟信号输出电路:转换后的模拟信号经过滤波、放大等处理后输出到外部设备或环境.

举个例子,麦克风接收声音:通过声音的大小、音调、音色等因素转换为高低不同的电压,转换后的电压值就是数字信号;然后用扩音器放出声音:单片机或者芯片通过总线将存储在寄存器上的数字信号传入到DAC中;DAC将数字信号转换为对应的声音,最后进行输出。

AD原理

在这里插入图片描述

这是单片机上的ADC模块原理图;
与单片机芯片连接的引脚:

DIN:串行数据输入
CS;片选信号;这是一种控制信号,用于选择要与主设备进行通信的从属设备。
DLCK:串行时钟
DOUT:串行数据输出

与外部电阻连接的引脚:

AIN0:连接着分压电阻;
AIN1:连接着热敏电阻;
AIN2:连接着光敏电阻;

在这里插入图片描述

下面是AD转换器的内部结构:逐次逼近型AD转换器
在这里插入图片描述
它使用二分搜索的方法逼近输入的模拟信号,并将其转换为数字输出;
逐次逼近型AD转换器通常由以下几个主要组成部分构成:

  1. 比较器(Comparator):用于比较输入模拟信号和DAC输出的数字量,产生一个比较结果。

  2. 数字-模拟转换器(Digital-to-Analog Converter,DAC):将数字量转换为模拟信号输出。在逐次逼近型AD转换器中,DAC通常是一个逐位逼近型DAC,可以根据比较结果生成合适的模拟电压输出。

  3. 控制逻辑(Control Logic):用于控制转换过程,包括初始化、逐位逼近、对比和停止等步骤。控制逻辑会根据比较结果调整DAC的输出,直到得到一个与输入模拟信号尽可能接近的数字输出。

  4. 计数器(Counter):用于计数和记录逼近过程中的比特位。逐次逼近型AD转换器从高位(MSB)开始逼近,通过逐步调整DAC输出的比特位。计数器会在每一次逼近过程中更新。

DA原理

在这里插入图片描述
与单片机相连的引脚:P21;通过放大器将数字信号转换为模拟信号到DA1(LED灯上);

T型电阻网络DA转换器
在这里插入图片描述
T型电阻网络DAC通常由一个或多个可变电阻和固定比例的电阻组成。其中,可变电阻用于控制输出模拟信号的大小,而固定比例的电阻则用于分割参考电压以确定输出模拟信号的范围。
在T型电阻网络DAC中,输入的数字信号首先被编码为N位二进制数。每个二进制位对应一个电阻。根据输入二进制数中1的个数,相应的开关会连接或断开对应的电阻通过这样的连接和断开过程,可变电阻的总阻值可以被调整,从而实现不同模拟输出电压的生成。当电阻网络的总阻值变化时,输出模拟电压也会相应地变化。
需要注意的是,T型电阻网络DAC的精度受限于电阻的精度和线性度。此外,由于电阻切换过程中可能引入的开关跳变,可能产生瞬态误差(glitch),导致输出信号的非理想性。
在这里插入图片描述

PWM型DA转换器
在这里插入图片描述
PWM型DA转换器(Pulse Width Modulation)是一种常见的数字模拟转换器,通过调节脉冲的宽度来实现模拟输出信号的调节
PWM型DA转换器基于脉冲信号,其输出信号的模拟值由脉冲的占空比决定。PWM型DA转换器通常包含一个计数器和一个比较器。计数器用于生成一个周期性的计数序列,比较器用于将计数值与给定的参考值进行比较产生脉冲信号。
工作原理如下:通过改变计数器的计数范围,以及在每个计数值处进行比较的阈值,可以控制脉冲信号的占空比。占空比表示脉冲高电平的时间与周期的比例,反映了输出模拟信号的幅度
在PWM型DA转换器中,**输入的数字信号首先被编码为N位二进制数。这个二进制数通常对应了脉冲信号的占空比调节值。**因此,输入数字信号越大,对应的脉冲信号的高电平时间也越长,从而模拟输出信号的幅度也会相应增加。
在这里插入图片描述

运算放大器

运算放大器(Operational Amplifier,简称运放或OP-AMP)是一种具有很高放大倍数的电路单元。它常用于模拟电路中,可以将输入信号进行放大、加、减、微分、积分等数学运算,并输出相应的结果。
运放通常由集成电路或分立元件组成,在现代电子行业广泛应用。它的工作原理是利用多级放大电路实现非常高的增益,同时通过外部反馈网络来控制其响应和特性。运放具有差分输入和单端输出的特点,其中两个输入端分别为非反相输入端和反相输入端,输出端则与输入端之间存在一个差分增益。
在这里插入图片描述

运放电路

在这里插入图片描述

1.运算放大器的正相输入端和反向输入端分别连接到待比较的两个电压源。
2.运算放大器的输出端与反馈电阻组成反馈网络,将输出信号通过反馈电阻返回到运放的正相输入端。
3.参考电压源为基准,通常连接到运放的正相输入端。
当运放的非反相输入端(+)所对应的电压高于反相输入端(-)时,运算放大器的输出会趋向于最大正饱和电压。相反地,当非反相输入端(+)的电压低于反相输入端(-)时,输出会趋向于最大负饱和电压。

在这里插入图片描述

反向放大器的原理如下:

  1. 输入信号通过输入电阻连接到运放的反相输入端(-)。
  2. 反馈电阻将运放的输出信号反馈到反相输入端(-)。
  3. 运放的非反相输入端(+)通常连接到地或参考电压源。

根据反馈原理,在稳定工作状态下,反向放大器的负反馈将使输入电流接近于零。根据欧姆定律,输入电流通过输入电阻产生的电压与输出电压成比例。

根据虚短和虚断点理想条件,可以得出反向放大器的放大倍数为:
放大倍数(Av) = -(Rf / Rin)

其中,Rf为反馈电阻,Rin为输入电阻。

由于反向放大器的特性,输出信号与输入信号之间存在180度的相位差,且放大倍数为负值。当输入信号为正时,输出信号为负;当输入信号为负时,输出信号为正。

反向放大器常用于信号放大、滤波、调节增益等应用。通过调整反馈电阻和输入电阻的比例,可以实现不同的放大倍数,并控制输出信号的幅度。

在这里插入图片描述
同向放大器是一种电子设备,常用于放大电信号。它的工作原理基于放大器中的晶体管或其他增益元件。

同向放大器的主要原理是将输入信号通过增益元件进行放大,并输出放大后的信号。增益元件通常是一个晶体管,例如双极性晶体管(BJT)或场效应晶体管(FET)。

在同向放大器中,输入信号被传送到晶体管的基极(对于BJT)或栅极(对于FET)。晶体管被偏置,以确保它在其工作区域内正常工作。当输入信号施加在晶体管上时,它会引起晶体管中的电流和电压的变化。

晶体管中的电流和电压变化会导致输出信号的放大。通过调整晶体管的工作点,可以控制输出信号的幅度和偏置。同向放大器通常采用反馈网络来提高线性度和稳定性。

在这里插入图片描述
电压跟随器(Voltage Follower)是一种放大器电路,它具有高输入阻抗、低输出阻抗和1倍的电压增益。它的主要功能是将输入电压信号复制到输出端,同时提供更低的输出阻抗。

电压跟随器的原理很简单:输入信号被连接到放大器的非反馈输入端,而输出信号则从放大器的输出端获取。由于没有反馈网络,所以该电路没有电压增益,信号只是通过放大器进行缓冲传递。这使得输出信号与输入信号具有相同的幅度,但输出阻抗远低于输入阻抗。

XPT2046

在这里插入图片描述

简介:XPT2046 是一款 4 线制电阻式触摸屏控制器,内含 12 位分辨率 125KHz 转换速率逐步逼近型 A/D 转换器
XPT2046 支持从 1.5V 到 5.25V 的低电压 I/O 接口。XPT2046 能通过执行两次 A/D 转换查出被按的屏幕位置, 除此之外,还可以测量加在触摸屏上的压力。内部自带 2.5V 参考电压,可以作为辅助输入、温度测量和电池监测之用,电池监测的电压范围可以从 0V 到 6V。
XPT2046 片内集成有一个温度传感器。 在 2.7V 的典型工作状态下,关闭参考电压,功耗可小于 0.75mW。
XPT2046 采用微小的封装形式:TSSOP-16,QFN-16 和 VFBGA-48。 工作温度范围为-40℃~+85℃。与 ADS7846、TSC2046、AK4182A 完全兼容。

在我们单片机上,已经内置了XPT2046控制器,我们只需要根据它的时序结构,就可以实现模数转换

XPT2046时序

XPT2046 数据接口是串行接口,其典型工作时序如图 12 所示,图中展示的信号来自带有基本串行接口的单片机或数据信号处理器。(SPI通信)
在这里插入图片描述
片选信号CS保持低电平;对于DLCK,上升沿表示输入,下降沿表示输出;然后进行数据输入到DIN,最后将信号进行读出DOUT;

代码:

#include <REGX52.H>
#include<INTRINS.H>//引脚定义
sbit XPT2046_DIN=P3^4;
sbit XPT2046_CS=P3^5;
sbit XPT2046_DLCK=P3^6;
sbit XPT2046_DOUT=P3^7;//读出信号unsigned int XPT2046_ReadAD(unsigned char Command)
{unsigned char i;unsigned int Data=0;XPT2046_DLCK=0;//串行时钟置于低电平XPT2046_CS=0;//片选信号置于低电平for(i=0;i<8;i++){XPT2046_DIN=Command&(0x80>>i);//信号输入XPT2046_DLCK=1;//上升沿输入XPT2046_DLCK=0;}//这是一个12位的AD转换器,可输出12位的分辨率for(i=0;i<16;i++){XPT2046_DLCK=1;XPT2046_DLCK=0;//下降沿输出//需要通过不断的上升下降表示接受不同的数据位if(XPT2046_DOUT)Data|=0x8000>>i;}XPT2046_CS=1;//片选置于高电平return Data>>8;//返回8位的数字信号
}

在这里插入图片描述

这是从高位开始输入的;位7选择1;位6-4表示通道的选择,需要参考对应表;位3我们选择8位的转换分辨率的;位2选择单端输入方式;位1与位0选择低电平即可,不用用到总处于供电状态;

单端模式简单,在采样过程完成后,转换过程中可以关闭驱动开关,降低功耗。但这种模式的缺点是精度
直接受参考电压源的精度限制,同时由于内部驱动开关的导通电阻存在,导通电阻与触摸屏电阻的分压作用,也会带来测量误差
差分模式的优点是: +REF 和-REF 的输入分别直接接到 YP、 YN 上,可消除由于驱动开关的导通电阻引入的坐标测量误差。缺点是:无论是采样还是转换过程中,驱动开关都需要接通,相对单端模式而言,功耗增加了。

那么我们就有这样的信号模板

0xxx 1100

在这里插入图片描述
我们根据原理图,选出对应的输出配置:

#define XPT2046_VBAT 0xAC
#define XPT2046_AUX 0xEC
#define XPT2046_XP 0x9C
#define XPT2046_YP 0xDC

AD模数转换代码:

将分压电阻,热敏电阻,光敏电阻转换为对应的数字信号并显示于屏幕上;
XPT2046.h:

#ifndef __XPT2046_H__
#define __XPT2046_H__//输入端口地址的宏定义
#define XPT2046_VBAT 0xAC
#define XPT2046_AUX 0xEC
#define XPT2046_XP 0x9C
#define XPT2046_YP 0xDCunsigned int XPT2046_ReadAD(unsigned char Command);#endif

XPT2046.c

#include <REGX52.H>
#include<INTRINS.H>//引脚定义
sbit XPT2046_DIN=P3^4;
sbit XPT2046_CS=P3^5;
sbit XPT2046_DLCK=P3^6;
sbit XPT2046_DOUT=P3^7;//读出信号unsigned int XPT2046_ReadAD(unsigned char Command)
{unsigned char i;unsigned int Data=0;XPT2046_DLCK=0;XPT2046_CS=0;for(i=0;i<8;i++){XPT2046_DIN=Command&(0x80>>i);XPT2046_DLCK=1;XPT2046_DLCK=0;}for(i=0;i<16;i++){XPT2046_DLCK=1;XPT2046_DLCK=0;if(XPT2046_DOUT)Data|=0x8000>>i;}XPT2046_CS=1;return Data>>8;
}

Delay.h

#ifndef __DELAY_H__
#define __DELAY_H__void Delayms(unsigned int x);#endif

Delay.c

void Delayms(unsigned int x)		//@11.0592MHz
{unsigned char i, j;while(x--){i = 2;j = 199;do{while (--j);} while (--i);}
}

LCD1602.c

#include <REGX52.H>//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0//函数定义:
/*** @brief  LCD1602延时函数,12MHz调用可延时1ms* @param  无* @retval 无*/
void LCD_Delay()
{unsigned char i, j;i = 2;j = 239;do{while (--j);} while (--i);
}/*** @brief  LCD1602写命令* @param  Command 要写入的命令* @retval 无*/
void LCD_WriteCommand(unsigned char Command)
{LCD_RS=0;LCD_RW=0;LCD_DataPort=Command;LCD_EN=1;LCD_Delay();LCD_EN=0;LCD_Delay();
}/*** @brief  LCD1602写数据* @param  Data 要写入的数据* @retval 无*/
void LCD_WriteData(unsigned char Data)
{LCD_RS=1;LCD_RW=0;LCD_DataPort=Data;LCD_EN=1;LCD_Delay();LCD_EN=0;LCD_Delay();
}/*** @brief  LCD1602设置光标位置* @param  Line 行位置,范围:1~2* @param  Column 列位置,范围:1~16* @retval 无*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{if(Line==1){LCD_WriteCommand(0x80|(Column-1));}else if(Line==2){LCD_WriteCommand(0x80|(Column-1+0x40));}
}/*** @brief  LCD1602初始化函数* @param  无* @retval 无*/
void LCD_Init()
{LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动LCD_WriteCommand(0x01);//光标复位,清屏
}/*** @brief  在LCD1602指定位置上显示一个字符* @param  Line 行位置,范围:1~2* @param  Column 列位置,范围:1~16* @param  Char 要显示的字符* @retval 无*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{LCD_SetCursor(Line,Column);LCD_WriteData(Char);
}/*** @brief  在LCD1602指定位置开始显示所给字符串* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  String 要显示的字符串* @retval 无*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=0;String[i]!='\0';i++){LCD_WriteData(String[i]);}
}/*** @brief  返回值=X的Y次方*/
int LCD_Pow(int X,int Y)
{unsigned char i;int Result=1;for(i=0;i<Y;i++){Result*=X;}return Result;
}/*** @brief  在LCD1602指定位置开始显示所给数字* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  Number 要显示的数字,范围:0~65535* @param  Length 要显示数字的长度,范围:1~5* @retval 无*/
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=Length;i>0;i--){LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');}
}/*** @brief  在LCD1602指定位置开始以有符号十进制显示所给数字* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  Number 要显示的数字,范围:-32768~32767* @param  Length 要显示数字的长度,范围:1~5* @retval 无*/
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{unsigned char i;unsigned int Number1;LCD_SetCursor(Line,Column);if(Number>=0){LCD_WriteData('+');Number1=Number;}else{LCD_WriteData('-');Number1=-Number;}for(i=Length;i>0;i--){LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');}
}/*** @brief  在LCD1602指定位置开始以十六进制显示所给数字* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  Number 要显示的数字,范围:0~0xFFFF* @param  Length 要显示数字的长度,范围:1~4* @retval 无*/
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{unsigned char i,SingleNumber;LCD_SetCursor(Line,Column);for(i=Length;i>0;i--){SingleNumber=Number/LCD_Pow(16,i-1)%16;if(SingleNumber<10){LCD_WriteData(SingleNumber+'0');}else{LCD_WriteData(SingleNumber-10+'A');}}
}/*** @brief  在LCD1602指定位置开始以二进制显示所给数字* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  Number 要显示的数字,范围:0~1111 1111 1111 1111* @param  Length 要显示数字的长度,范围:1~16* @retval 无*/
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=Length;i>0;i--){LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');}
}

LCD1602.h

#ifndef __LCD1602_H__
#define __LCD1602_H__//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);#endif

main.c

#include <REGX52.H>
#include"Delay.h"
#include"LCD1602.h"
#include"XPT2046.h"unsigned int ADValue;void main()
{LCD_Init();LCD_ShowString(1,1,"ADJ NTC  GR");while(1){ADValue=XPT2046_ReadAD(XPT2046_XP);   //读取AIN0,可调电阻LCD_ShowNum(2,1,ADValue,3);ADValue=XPT2046_ReadAD(XPT2046_YP);   //读取AIN1,热敏电阻LCD_ShowNum(2,6,ADValue,3);ADValue=XPT2046_ReadAD(XPT2046_VBAT);   //读取AIN2,光敏电阻LCD_ShowNum(2,11,ADValue,3);Delayms(100);//延迟100ms,会根据实况不断刷新数据}
}

AD的实例代码

产生PWM的方法


在这里,我们利用软件程序进行实现PWM,就是利用计数器和某一个值进行比较,根据比较结果输出一个对应的高低电平;像图中的,只要比较值大于计数器的值,那么就输出0,比较值大于等于计数器的值,那么就输出1;

DA信号输出的呼吸灯代码

Timer0.c

#include <REGX52.H>/*** @brief 定时器0初始化* @param 无* @reval 无*/
void Timer0Init(void)		//100us @11.0592MHz
{TMOD &= 0xF0;		//设置定时器模式TMOD |=0x01;TL0 = 0xA4;		//设置定时初值TH0 = 0xFF;		//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 1;		//定时器0开始计时ET0=1;     //允许T0中断EA=1;      //CPU开放总中断PT0=0;      //定时器0中断优先级
}

Timer0.h

#ifndef __TIMER0_H__
#define __TIMER0_H__void Timer0Init();#endif

Delay.h

#ifndef __DELAY_H__
#define __DELAY_H__void Delay(unsigned int xms);#endif

Delay.c


void Delay(unsigned int xms)
{unsigned char i, j;while(xms--){i = 2;j = 239;do{while (--j);} while (--i);}
}

main.c

#include <REGX52.H>
#include"Delay.h"
#include"Timer0.h"sbit DA=P2^1;unsigned char Counter,Compare;//计数值和比较值
unsigned char i;void main()
{Timer0Init();while(1){for(i=0;i<100;i++)//利用循环不断增加{Compare=i;Delay(10);//延长周期,不然LED闪烁过快}for(i=100;i>0;i--){Compare=i;Delay(10);}}
}//通过100us中断一次,将计数值与比较值比较,赋上对应的值
void Timer0_Routine() interrupt 1
{TL0 = 0xA4;		TH0 = 0xFF;		Counter++;Counter%=100;if(Counter<Compare){DA=1;}else{DA=0;}}

在这里插入图片描述

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

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

相关文章

C语言基础入门详解三

前些天发现了一个蛮有意思的人工智能学习网站,8个字形容一下"通俗易懂&#xff0c;风趣幽默"&#xff0c;感觉非常有意思,忍不住分享一下给大家。 &#x1f449;点击跳转到教程 一、C语言之函数指针 #include<stdio.h> #include<stdlib.h> /**函数指针 …

百度文心一言接入教程-Java版

原文链接 前言 前段时间由于种种原因我的AI BOT网站停运了数天&#xff0c;后来申请了百度的文心一言和阿里的通义千问开放接口&#xff0c;文心一言的接口很快就通过了&#xff0c;但是文心一言至今杳无音讯。文心一言通过审之后&#xff0c;很快将AI BOT的AI能力接入了文心…

uniapp使用echarts

uniapp使用echarts 1.下载资源包2.引入资源包3.代码示例注意事项 1.下载资源包 https://echarts.apache.org/zh/download.html 2.引入资源包 将资源包放入项目内 3.代码示例 <template><div style"width:100%;height:500rpx" id"line" ref&…

【网络】应用层——HTTP协议

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《网络》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; &#x1f3c0;认识HTTP协议 上篇文章中&#xff0c;本喵带着大家对HTTP有了一个初步的认识&#xff0…

使用Django自带的后台管理系统进行数据库管理的实例

Django自带的后台管理系统主要用来对数据库进行操作和管理。它是Django框架的一个强大功能&#xff0c;可以让你快速创建一个管理界面&#xff0c;用于管理你的应用程序的数据模型。 使用Django后台管理系统&#xff0c;你可以轻松地进行以下操作&#xff1a; 数据库管理&…

动态SQL 语句-更复杂的查询业务需求也能轻松拿捏

文章目录 动态SQL 语句-更复杂的查询业务需求动态SQL-官方文档为什么需要动态SQL动态SQL-基本介绍基本介绍动态SQL 必要性解决方案分析 动态SQL 常用标签动态SQL-案例演示if 标签应用实例where 标签应用实例choose/when/otherwise 应用实例forEach 标签应用实例trim 标签应用实…

【公益】Q学友联合福田人力资源局开展“侨香社区促就业 技能培训强本领”

落实《“十四五”就业促进规划》文件精神&#xff0c;进一步提高就业劳动者就业技能水平&#xff0c;提高居民就业率&#xff0c;侨香社区党委坚持以党建为引领&#xff0c;整合多方资源&#xff0c;深入开展“我为群众办实事”&#xff0c;切合群众实际、满足群众需求&#xf…

深度学习技巧应用24-深度学习手撕代码与训练流程的联系记忆方法

大家好,我是微学AI,今天给大家介绍一下深度学习技巧应用24-深度学习手撕代码与训练流程的联系记忆方法,大家都知道深度学习模型训练过程是个复杂的过程,这个过程包括数据的收集,数据的处理,模型的搭建,优化器的选择,损失函数的选择,模型训练,模型评估等步骤,其中缺少…

Java基础_网络编程

Java基础_网络编程 网络编程三要素InetAddress网络模型 UDP通信程序单播发送数据接收数据聊天室 组播广播 TCPTCP通信程序三次握手和四次挥手 来源Gitee地址 网络编程三要素 IP: 设备在网络中的地址&#xff0c;是唯一的标识端口号: 应用程序在设备中唯一的标识。协议: 数据在…

【Qt】利用Tool Button控件创建下拉菜单按钮

功能描述 利用qt进行界面设计和开发&#xff0c;创建下拉按钮。 详细实现 1、在qt侧工具栏利用设计打开.ui文件 2、创建按钮 创建一个Tool Button按钮&#xff0c;并在属性窗口中的QToolButton栏中选中MenuButtonPopup属性。 3、创建action 在Action编辑器创建对应的ac…

SQL编译优化原理

最近在团队的OLAP引擎上做了一些SQL编译优化的工作&#xff0c;整理到了语雀上&#xff0c;也顺便发在博客上了。SQL编译优化理论并不复杂&#xff0c;只需要掌握一些关系代数的基础就比较好理解&#xff1b;比较困难的在于reorder算法部分。 文章目录 基础概念关系代数等价 j…

k8s webhook实例,java springboot程序实现 对Pod创建请求添加边车容器 ,模拟istio实现日志文件清理

k8s webhook实例&#xff0c;java springboot程序实现 对Pod创建请求添加边车容器 &#xff0c;模拟istio实现日志文件清理 大纲 背景与原理实现流程开发部署my-docker-demo-sp-user服务模拟业务项目开发部署my-sidecar服务模拟边车程序开发部署服务my-docker-demo-k8s-opera…

零拷贝原来这么简单!

我们总会在各种地方看到零拷贝&#xff0c;那零拷贝到底是个什么东西。 接下来&#xff0c;让我们来理一理啊。 拷贝说的是计算机里的 I/O 操作&#xff0c;也就是数据的读写操作。计算机可是一个复杂的家伙&#xff0c;包括软件和硬件两大部分&#xff0c;软件主要指操作系统…

uniapp h5 竖向的swiper内嵌视频实现抖音短视频垂直切换,丝滑切换视频效果,无限数据加载不卡顿

一、项目背景&#xff1a;实现仿抖音短视频全屏视频播放、点赞、评论、上下切换视频、视频播放暂停、分页加载、上拉加载下一页、下拉加载上一页等功能。。。 二、前言&#xff1a;博主一开始一直想实现类似抖音进入页面自动播放当前视频&#xff0c;上下滑动切换之后播放当前…

excel要如何自动累加某个单元格上方的所有单元格?

输入公式 SUM(INDIRECT("A1:A"&ROW()-1)) 运行实例如下图 注意图中b4&#xff0c;和b5单元格都输入相同的公式。 此方法可以避免写vba&#xff0c;以前此类问题的解决都是通过vba代码进行处理 对函数进行解析 主要使用了 INDIRECT() 2、公式说明&#xff1a;…

Leetcode | Binary search | 22. 74. 162. 33. 34. 153.

22. Generate Parentheses 要意识到只要还有左括号&#xff0c;就可以放到path里。只要右括号数量小于左括号&#xff0c;也可以放进去。就是valid的组合。recurse两次 74. Search a 2D Matrix 看成sorted list就好。直接用m*n表示最后一位的index&#xff0c;并且每次只需要 …

打印Winform控件实现简陋版的分页打印(C#)

本文的代码可以从这里获取&#xff1a;winformDemo.rar 张祥裕/分享的资源名称 - Gitee.com 作者的水平有限&#xff0c;如有错误&#xff0c;望指正。 为了简单起见&#xff0c;纸张大小&#xff0c;打印机等信息按照默认的来&#xff0c;本文的实现方案是&#xff1a;打印Pa…

C语言:反转一个单链表

Lei宝啊&#xff1a;个人主页 题目&#xff1a; 描述&#xff1a; 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 接口&#xff1a; struct ListNode* reverseList(struct ListNode* head){} 示例&#xff1a; 输入&#xff1a; head [1…

全局ip代理安全吗? 手机设置全局代理方法详解

全局IP代理并不一定是安全的&#xff0c;因为全局IP代理会将所有网络流量都通过代理服务器进行转发&#xff0c;包括敏感信息和隐私数据。如果代理服务器受到黑客攻击或存在安全漏洞&#xff0c;可能会导致数据泄露和其他安全问题。因此&#xff0c;在使用全局IP代理时&#xf…

Spring Boot项目的创建

hi 大家好,又见面了,今天继续讲解Spring Boot 文章目录 &#x1f436;1.什么是Spring Boot?&#x1f436;2.Spring Boot的优势&#x1f436;3.Spring Boot项目创建&#x1f33c;3.1使用ieda创建&#x1f95d;3.1.1下载插件Spring Boot Helper&#x1f95d;3.1.2创建项目 &…