ADC数模转化器
简介
逐次逼近型ADC
首先这个ADC有八个输入引脚,通过通道选择开关可以选择IN中其中一个进行下一步,通道选择开关是靠地址锁存和译码控制的,把通道的编号输入ADDA,ADDB,ADDC,然后给一个锁存信号ALE,上面对应的通路开关就可以自动拨好了,相当于一个可以通过模拟信号的数据选择器;因此如果想要转换多路信号,只需要一个AD转换器,加一个多路选择开关,想转换哪路,就选中那个对应通道,然后再开始转换就行了。
接下来会把这个未知编码的电压输出到比较器中,DAC会输出一个已知编码的电压,将两者进行比较,如果未知大于已知,则会增大已知量,如果未知小于已知,则会减小已知量,直到二者近似相等,这样以来,DAC输入的数据就是外部电压的编码数据了,这个电压调节的过程就是这个逐词逼近SAR来完成的。
为了快速找到这个值,我们会使用二分法来寻找,并且这个过程如果使用二进制来表示的话,会发现128、64、32这些值都是二进制每一位的位权,这个判断过程相当于是对二进制从高位到低位依次判断是1还是0的过程。对于8位的ADC,从高位到低位依次判断8次就能找到未知电压的编码了;对于12位的ADC,则需要判断12次。
然后DAC的输入数据就是未知电压的编码,然后通过D0等口进行输出;
EOC(End of Convent):转换结束信号;
START:开始转换,给一个输入脉冲,开始转换;
CLOCK:ADC时钟,每一步都需要时钟的推进
VREF+和VREF-是DAC的参考电压:写入一个数据255,对应5V还是3V由它们决定;
STM32的ADC
GPIO端口由16个通道,还分为两个通道,第一个是注入通道,第二个是规则通道;
注入通道:至多同时输入四个通道的数据,但是有四个注入通道数据寄存器,可以一次性把四个数据同时展示出来的
规则通道:至多可以同时输入十六个通道的数据,但是只有一个规则通道数据寄存器,会出现数据覆盖,只能把一个通道的数据展示出来;如果想展示多个数据,就需要搭配DMA转运数据。
开始触发(注入组合规则组都有):触发ADC开始转换的信号有两种,一是软件触发,在程序中调用代码启动转换,二是硬件触发,即图中的开始触发(触发源),主要来自定时器;可以使用定时器中断来实现每过一定时间就触发一次ADC,但是频繁进入中断对程序的正常执行有影响;需要定时完成这种简单的任务的情况,一般都会有硬件的支持,比如这里,给TIM3定一个1ms的时间,把TIM3的更新事件选择为TRGO输出,在ADC这,选择开始触发信号为TIM3的TRGO,这样TIM3的更新事件就能通过硬件自动触发ADC转换了。
ADCCLK:即CLK时钟
在RCC时钟树中,ADCCLK最大14MHz,而我们如果选择二分频,即72/2=36,超出范围,而且选择4分频也是超出范围的,只能选择6和8分频。
ADC基本结构
还可以布置一个模拟看门狗用于监测转换结果的范围,如果超出所设定的阈值,就会通过中断输出控制,向NVIC申请中断;在AD转换器转换完成之后,还有个EOC信号,它会置一个标志位,然后通向NVIC申请中断。
输入通道
转换模式
单次转换、非扫描模式
简单的在序列1中指定我们想要转换的通道,然后就可以触发转换,ADC就会对这个通道进行模数转换,过段时间转换完成后,会把转换结果放在数据寄存器中,同时给EOC标志位置1,转换过程就结束了。我们判断这个EOC标志位,如果转换完了,就可以在数据器中读取结果了。
如果还想在启动转换,想要转换其他通道,则就需要把序列1中的通道更改为目标通道,再触发转换。
指定通道在序列1->触发转换->转换结束->给标志位EOC置1->读结果
多次转换,非扫描模式
相比单次转换,多次转换只用触发转换一次,ADC就会一直转换,不用判断结束和不用多次触发转换,想要读取AD值时,就直接从数据寄存器去就可以了。
单次转换,扫描模式
扫描模式下,可以利用多个序列,可以任意指定任意通道,流程依然是触发转换,然后按序列顺序开始给指定通道转换,直到转换完最后一个序列指定的通道,然后给EOC标志位置1。
连续转换,扫描模式
不想解释....
触发控制
数据对齐
ADC是12位的,但是数据寄存器却是16位的,所以就需要数据对齐;
这里我们常用数据右对齐
转换时间
(采样保持:量化编码过程需要比较多的时间,在量化编码过程中,如果输入的电压发生变化,就很难定位输入电压对应的编码了,所以需要采样保持,在量化编码之前,需要打开采样开关,收集一下外部的电压,比如使用一个小容量的电容存储这个电压,存储好之后,断开采样开关,再进行AD转换,这样就实现了在量化编码过程中,电压始终保持不变)
TCONV = 采样时间 + 12.5个ADC周期
TCONV = 1.5 + 12.5 = 14个ADC周期 = 1μs
即最短转换时间为1us(因为ADCCLK最小为14MHz)
校准
硬件电路
图一电位器产生可调电压的电路:可给PA0产生一个0~3.3V的电压,电阻阻值不可太小,一般为10kΩ;
图二传感器输出电压的电路: N1(麦克风,热敏电阻等可变电阻)可以等效为一个可变电阻,其阻值没法直接测量,所以可以通过和一个固定电阻串联分压,来得到一个可以反映电阻值电压的电路;这个固定电阻一般选择和传感器阻值相近的电阻,这样可以得到一个位于中间电压区域比较好的输出;
图三简单的电压转换电路:比如我们想测一个0~5V的Vin电压,但是ADC只能接收最大为3.3V的电压,根据图中两个电阻的分压,可以得到PA2的电压范围就是0~3.3V,就可以进入ADC转换了。输入电压差太多不适合用这个电路。
代码实操
先介绍相关库函数
ADCCLK的配置函数
用于配置ADCCLK分频器的,可以对APB2的72MHz时钟选择2,、4、6、8分频,输入到ADCCLK
void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);
ADC的库函数
老朋友
void ADC_DeInit(ADC_TypeDef* ADCx);
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct);
开关控制
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
用于开启DMA输出信号
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
中断输出控制
void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);
控制校准的函数 (ADC初始化完成后,依次调用即可)
//复位校准
void ADC_ResetCalibration(ADC_TypeDef* ADCx);
//获取复位校准状态
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);
//开始校准
void ADC_StartCalibration(ADC_TypeDef* ADCx);
//获取开始校准状态
FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);
用于软件触发的函数(即用软件控制触发控制)
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
获取标志位状态(参数写EOC的标志位,判断EOC是否被置1,即转换是否结束)
FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
有关间断的函数
//每隔几个通道间断一次?
void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);
//是否开启间断
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
ADC规则组通道配置(重要)(ADC号,需要指定的通道,序列几的位置,指定通道的采样的时间)
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
是否允许外部触发转换
void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
ADC获取转换值(重要)即获取AD转换的数据寄存器
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
ADC获取双模式转换值(双ADC获取转换值的函数)
uint32_t ADC_GetDualModeConversionValue(void);
注入组的函数(不讲)
void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv);
void ADC_ExternalTrigInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_SoftwareStartInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx);
void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length);
void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset);
模拟看门狗
//是否启用模拟看门狗
void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);
//配置高低阈值
void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold);
//配置看门的通道
void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel);
ADC温度传感器、内部参考电压控制
void ADC_TempSensorVrefintCmd(FunctionalState NewState);
标志位
//获取标志位状态
FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
//清除标志位
void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
//获取中断状态
ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);
//清除中断挂起位
void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);
如图所示步骤编写代码
1、开启GPIO和ADC的时钟,还有ADCCLK分频器
//开启时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//6分频RCC_ADCCLKConfig(RCC_PCLK2_Div6);
2、配置GPIO口,配置为模拟输入模式
//配置GPIO口GPIO_InitTypeDef GPIO_InitStructure;//AIN模拟输入//在AIN模式下GPIO口无效,即断开GPIO口//防止GPIO输入输出对模拟电压造成干扰(ACD专属模式)GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);
3、配置多路开关,把左边的通道接入到右边的规则组列表中
//选择规则组的输入通道//参数3:序号数//参数4:采样时间的参数,需要更快的转换,选择小点的参数//需要稳定的转换,则选择更大的参数ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
4、配置ADC转换器
//初始化ADCADC_InitTypeDef ADC_InitStructure;//ADC工作模式(独立模式)ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//数据对齐(右对齐)ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//外部触发转换选择(外部触发源选择)(None,内部软件触发)ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//连续转换模式(ENABLE-连续模式 or DISABLE-非连续模式)ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//扫描模式(ENABLE-扫描模式 or DISABLE-非扫描模式)ADC_InitStructure.ADC_ScanConvMode = DISABLE;//通道数目(指定在扫描模式下指定用到几个通道0~16)//在非扫描模式下,填任何数值都没用ADC_InitStructure.ADC_NbrOfChannel = 1;ADC_Init(ADC1, &ADC_InitStructure);
5、开关控制
//开启ADC电源ADC_Cmd(ADC1,ENABLE);
6、还可以对ADC进行校准,可以减小误差
//校准//复位校准ADC_ResetCalibration(ADC1);
上列语句是执行复位校准,那应该如何判断复位校准完成了呢?
这个函数是一个返回值,那这个返回值和是否完成校准有什么关系呢?
//获取复位校准状态 ADC_GetResetCalibrationStatus(ADC1);
查看其函数定义
可以看到其获取的就是CR2寄存器里的RSTCAL标志位
再查看手册查询相关寄存器内容
则可得
while(ADC_GetResetCalibrationStatus(ADC1) == SET);
则校准的总代码
//校准//复位校准ADC_ResetCalibration(ADC1);//获取复位校准状态//标志位为1时,表示正在进行复位校准//标志位为0时,表示复位校准结束,则我们要保证复位校准成功//当复位校准未完成就一直循环等待其完成while(ADC_GetResetCalibrationStatus(ADC1) == SET);//开始校准ADC_StartCalibration(ADC1);//获取开始校准状态while(ADC_GetCalibrationStatus(ADC1) == SET);
则初始化函数写好了
#include "stm32f10x.h" // Device headervoid AD_Init(void)
{//开启时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//6分频RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置GPIO口GPIO_InitTypeDef GPIO_InitStructure;//AIN模拟输入//在AIN模式下GPIO口无效,即断开GPIO口//防止GPIO输入输出对模拟电压造成干扰(ACD专属模式)GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//选择规则组的输入通道//参数3:序号数//参数4:采样时间的参数,需要更快的转换,选择小点的参数//需要稳定的转换,则选择更大的参数ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);//初始化ADC(单次转换,非扫描模式)ADC_InitTypeDef ADC_InitStructure;//ADC工作模式(独立模式)ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//数据对齐(右对齐)ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//外部触发转换选择(外部触发源选择)(None,内部软件触发)ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//连续转换模式(ENABLE-连续模式 or DISABLE-非连续模式)ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//扫描模式(ENABLE-扫描模式 or DISABLE-非扫描模式)ADC_InitStructure.ADC_ScanConvMode = DISABLE;//通道数目(指定在扫描模式下指定用到几个通道0~16)//在非扫描模式下,填任何数值都没用ADC_InitStructure.ADC_NbrOfChannel = 1;ADC_Init(ADC1, &ADC_InitStructure);//开启ADC电源ADC_Cmd(ADC1,ENABLE);//校准//复位校准ADC_ResetCalibration(ADC1);//获取复位校准状态//标志位为1时,表示正在进行复位校准//标志位为0时,表示复位校准结束,则我们要保证复位校准成功//当复位校准未完成就一直循环等待其完成while(ADC_GetResetCalibrationStatus(ADC1) == SET);//开始校准ADC_StartCalibration(ADC1);//获取开始校准状态while(ADC_GetCalibrationStatus(ADC1) == SET);
}
获取结果函数
1、软件触发(启动)
//软件触发(启动)ADC_SoftwareStartConvCmd(ADC1, ENABLE);
2、等待转换完成(EOC置1)(等待)
//获取EOC标志位状态(等待)//与之前的判断复位校准是否完成的操作一致//但是与校准有所不同(需要看寄存器描述)//0:转换未完成, 1:转换完成//在之前我们设置采样周期为55.5,转换周期是固定的12.5//加在一起就是68个周期,配置的ADCCLK是72MHz的6分频,即12MHz//12MHz进行68个周期转换才能完成,最终时间为1/12M*68=5.6μs//即while循环会等待5.6μswhile(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
3、读取ADC数据寄存器(读取)
//获取转换值(读取)return ADC_GetConversionValue(ADC1);
整体
//获取转换结果的函数
uint16_t AD_GetValue(void)
{//软件触发(启动)ADC_SoftwareStartConvCmd(ADC1, ENABLE);//获取EOC标志位状态(等待)//与之前的判断复位校准是否完成的操作一致//但是与校准有所不同(需要看寄存器描述)//0:转换未完成, 1:转换完成//在之前我们设置采样周期为55.5,转换周期是固定的12.5//加在一起就是68个周期,配置的ADCCLK是72MHz的6分频,即12MHz//12MHz进行68个周期转换才能完成,最终时间为1/12M*68=5.6μs//即while循环会等待5.6μswhile(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//获取转换值(读取)return ADC_GetConversionValue(ADC1);
}
在主函数中调用
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"uint16_t ADValue;int main(void)
{OLED_Init();AD_Init();OLED_ShowString(1,1,"ADValue");while(1){ADValue = AD_GetValue();OLED_ShowNum(1,9,ADValue,4);}
}
然后旋转电位器,可以发现向左拧ADValue增大,向右拧ADValue则减小。
改善
一、数据抖动
我们会发现数据末尾会发生抖动,这是正常现象,当我们想使用这个值进行判断,再执行某些操作,比如光线的AD值小于某阈值就开灯,大于某阈值就关灯,可能会出现假如值在阈值附近抖动,导致我们的操作不稳定(即LED亮灭不稳定),我们可以使用迟滞比较的方法来完成,设置两个阈值,低于下阈值时,开灯,高于上阈值时,关灯,这样就可以避免输出抖动的问题了(施密特触发器同一个原理)。
如果数据跳变来厉害,还可以采用滤波的方法使AD值更平滑点(均值滤波);
或者裁减分辨率,把数据的尾数去掉。
二、显示电压
如之前所说,输入电压和转换结果一一对应,呈线性关系
我们可以利用这个线性关系,输出电压的值(不是完全准确的)
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"uint16_t ADValue;
float Voltage;int main(void)
{OLED_Init();AD_Init();OLED_ShowString(1,1,"ADValue:");OLED_ShowString(2,1,"Voltage:0.00V");while(1){ADValue = AD_GetValue();Voltage = (float)ADValue / 4095 * 3.3;OLED_ShowNum(1,9,ADValue,4);OLED_ShowNum(2,9,Voltage,1);OLED_ShowNum(2,11,(uint16_t)(Voltage*100)%100,2);Delay_ms(100);}
}
相关文章:

ADC数模转化器
简介 • ADC ( Analog-Digital Converter )模拟 - 数字转换器 • ADC 可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁 • 12 位逐次逼近型 ADC , 1us 转换时间 (12位:分辨率…...

Linux DataEase数据可视化分析工具结合cpolar实现远程访问
文章目录 前言1. 安装DataEase2. 本地访问测试3. 安装 cpolar内网穿透软件4. 配置DataEase公网访问地址5. 公网远程访问Data Ease6. 固定Data Ease公网地址 前言 DataEase 是开源的数据可视化分析工具,帮助用户快速分析数据并洞察业务趋势,从而实现业务…...
使用JAXB将xml转成Java对象
文章目录 使用JAXB将xml转成Java对象1. xml内容2. Java对象类3. 封装的工具类4. 测试 使用JAXB将xml转成Java对象 工作中遇到个问题,需要将xml转对象,之前复杂的xml都是自己用dom4j来解析组装成Java对象,但是对于简单的,看到了JAX…...

第6讲:v-for使用
目录 1.循环遍历 2.v-for遍历整形变量(99乘法表) 3.v-for遍历普通数组 4.v-for遍历数组对象 1.循环遍历 v-for指令基于一个数组渲染一个列表,它和JavaScript的遍历语法相似: v-for”item in list” list 是一个数组, i…...
ubuntu http 服务器响应
代码: h文件 #include <iostream> #include <curl/curl.h>#include <net/if.h> #include <sys/ioctl.h> #include <arpa/inet.h> #include <string.h>#include <event.h> #include <event2/http.h> #include <…...
C语言 结构体位域
在C语言中,结构体位域是一种特殊的结构体成员,它允许在结构体中定义一个二进制位字段,以便在单个字节中存储多个布尔值或枚举值。 结构体位域的定义方式如下: struct { unsigned int bit1: 1; // 定义一个名为bit1的位域&…...

ChatGPT AIGC 非常实用的AI工具集合大全
实战AI 工具箱 AIGC ChatGPT 职场案例60集, Power BI 商业智能 68集, 数据库Mysql8.0 54集 数据库Oracle21C 142集, Office, Python ,ETL Excel 2021 实操,函数,图表,大屏可视化 案例实战 http://t.csdn.cn/zBytu...

Visual Studio Cpp CLR C# 替换
1、首先将文件中所有都替换 你需要的名字 替换为整个解决方案 2、新建工程取名 Laserbeam_upper 3、把原工程下的cpp放进来,并改名Laserbeam_upper 4、在这里逐步添加 属性表配置opencv 5、cpp需要修改的两个地方 6、CLR新建和添加 选类库新建、然后直接粘贴进来…...
typeorm利用mongodb,save的时候更新会出现重复数据的问题。
是因为mongodb把new Object当成插入的数据了,修正方案 ObjectIdColumn({name: _id,})Transform((value) > new ObjectId(value.obj._id.toString()))// ts-ignore_id: ObjectId;Transform((value) > new ObjectId(value.obj._id.toString()))转换下就好了。...

决策树案例分析
决策树(Decision Tree)常用于研究类别归属和预测关系的模型,比如是否抽烟、是否喝酒、年龄、体重等4项个人特征可能会影响到‘是否患癌症’,上述4项个人特征称作‘特征’,也即自变量(影响因素X),‘是否患癌…...

Linux基本操作符(1)
W...Y的主页 😊 代码仓库分享 💕 目录 Linux的登录 Linux下基本指令 指令操作的理解 几个与用户操作符 ls 指令 pwd命令 cd 指令 touch指令 mkdir指令 rmdir指令 && rm 指令 什么叫操作系统,我相信如果是学计算机的都听说过&…...

pg数据表同步到hive表数据压缩总结
1、背景 pg库存放了大量的历史数据,pg的存储方式比较耗磁盘空间,pg的备份方式,通过pgdump导出后,进行gzip压缩,压缩比大概1/10,随着数据的积累磁盘空间告警。为了解决pg的压力,尝试采用hive数据…...

2023-Chrome插件推荐
Chrome插件推荐 一键管理扩展 链接 https://chromewebstore.google.com/detail/lboblnfejcmcaplhnbkkfcienhlhpnni 介绍 一键开启、禁用Chrome插件。 Checker Plus for Gmail™ 链接 https://jasonsavard.com/zh-CN/Checker-Plus-for-Gmail https://chromewebstore.goo…...

VUE使用DXFParser组件解析dxf文件生成图片
<template><div><input type"file" change"handleFileChange" /></div><el-table :data"tableData" style"width: 100%"><el-table-column prop"Control_No" label"序号" width…...

SpringBoot 集成 AKKA
文章目录 应用场景与 SpringBoot 集成示例 应用场景 AKKA 是一个用于构建高并发、分布式和容错应用程序的开源框架。它基于Actor模型,提供了强大的并发抽象和工具,适用于各种业务场景。以下是一些使用AKKA框架的常见业务场景的示例: 实时数据…...

什么是Service Worker?它在PWA中的作用是什么?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ Service Worker的作用是什么?⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前…...

【算法深入浅出】字符串匹配之 KMP 算法
KMP 算法是一种字符串匹配算法。字符串匹配算法的目标是:在字符串 s 中找到与模式串 p 相等的子串,输出其位置。例如:s “abcdef”,p “cdef”,p 在 s 中的位置是 2(从 0 开始计数)。 容易想到…...

放弃webstrom转战vscode
本来是webstrom的忠实用户,无奈webstrom要么需要在网上找一个破解版或者不断的去找激活码,且破解版和激活码的文章总是很多,但是要找到真正有效的却总是要花费不少功夫。终于忍无可忍,转战vscode。(注:文中…...

VSCode 和 CLion
文章目录 一、VSCode1、文档2、插件3、智能编写4、VSCode 与 C(1)安装(2)调试(a)使用 CMake 进行跨平台编译与调试(b)launch.json(c)传参 (3&…...

Learn Prompt- Midjourney Prompt:Prompt 提示语
基础结构 一个基本的提示可以简单到一个单词、短语或表情符号。非常短的提示将在很大程度上依赖于 Midjourney 的默认样式。 完整 prompt:可以包括一个或多个图像链接、多个文本短语或单词,以及一个或多个后缀参数 Image Prompts: 可以将图像 URL 添加…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...

五、jmeter脚本参数化
目录 1、脚本参数化 1.1 用户定义的变量 1.1.1 添加及引用方式 1.1.2 测试得出用户定义变量的特点 1.2 用户参数 1.2.1 概念 1.2.2 位置不同效果不同 1.2.3、用户参数的勾选框 - 每次迭代更新一次 总结用户定义的变量、用户参数 1.3 csv数据文件参数化 1、脚本参数化 …...

高保真组件库:开关
一:制作关状态 拖入一个矩形作为关闭的底色:44 x 22,填充灰色CCCCCC,圆角23,边框宽度0,文本为”关“,右对齐,边距2,2,6,2,文本颜色白色FFFFFF。 拖拽一个椭圆,尺寸18 x 18,边框为0。3. 全选转为动态面板状态1命名为”关“。 二:制作开状态 复制关状态并命名为”开…...

Web APIS Day01
1.声明变量const优先 那为什么一开始前面就不能用const呢,接下来看几个例子: 下面这张为什么可以用const呢?因为复杂数据的引用地址没变,数组还是数组,只是添加了个元素,本质没变,所以可以用con…...