定时器之输出捕获

简介

IC Input Capture )输入捕获
输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前 CNT 的值将被锁存到 CCR 中,可用于测量 PWM 波形的频率、占空比、脉冲间隔、电平持续时间等参数
每个高级定时器和通用定时器都拥有 4 个输入捕获通道
可配置为 PWMI 模式,同时测量频率和占空比
可配合主从触发模式,实现硬件全自动测量
在图中红圈位置

 

         因为输入捕获和输出比较的CH1的输出和输入引脚是共用的,所以同一个CH通道只能使用输入捕获和输出比较的其中一个

频率测量

对比测频法和测周法

测频法:(适合测量高频信号)由图可知,每接收一个上升沿计一次,所以会测到多个周期,所以在闸门时间内,最好要多出现一些上升沿,计次数量N多一些,可以减小误差。

(特性:测量结果更新慢一些,数值相对稳定;自带均值滤波,在闸门时间内波形频率有变化,得到的是这段时间内的平均频率,值比较平滑)

测周法:(适合测量低频信号)低频信号,周期比较长,测周法计次就会比较多,有助于减小误差

(特性:结果更新块以下,数据跳变也很快,出结果的速度取决于测量的频率)

这两种测频方法都存在这正负一误差,要想减少误差,就只能多计点数,当计次N足够大时,正负一误差的影响就会很小

         当有个频率测周法和测频法计次的N相同,就说明误差相同,这就是中介频率。

        对应图上:当待测信号频率小于中介频率时,测周法误差更小;当待测信号频率大于中介频率时,测频法误差更小。

详细介绍电路图

        从CH1等通道输入频率信号,(异或门是给三相电路使用的,暂时不介绍)然后经过输入滤波器中,过滤毛刺信号,边沿检测器即选择上升沿触发或者是下降沿触发,这里的输入滤波器和边沿检测器有两套,如果我们从CH1中输入信号,接下来可以选择输入TI1FP1到IC1或者输出TI1FP2到IC2中,这样设计的目的主要有两个:

        ①可以灵活切换后续捕获电路的输入,可以通过CH1输入IC1,也可以通过CH2输入IC1;

        ②可以把一个引脚的输入,同时映射到两个捕获单元,这是PWMI的经典结构,可以分为第一个捕获通道,使用上升沿触发,用来捕获周期,第二个捕获通道,使用下降沿触发,用来捕获占空比,这样就可以同时捕获周期和占空比

        接下来就来到了预分频器,分频后的触发信号就可以触发捕获电路进行工作了,每来一次信号,CNT的值就会向CCR转运一次,转运的同时会产生一个事件,这个事件会在状态寄存器值标志位,可以产生中断(如果需要在捕获到信号后采取行动,就可以开启这个捕获中断)

        采取上升沿触发捕获,没触发一次上升沿就会把CNT的值转运到CCR中,每传递信号两次,就会产生两个CCR的值,这两个CCR的差值就是两个相邻上升沿的时间间隔,也就是周期,取倒数就是测周法得出的频率了。

注意:每次我们捕获完一个周期后,要把CNT的值清零,这样才能捕获下次的频率长度(可以使用主从触发模式实现)

CCMR1寄存器中的ICF位可以控制滤波器的参数

 工作原理:以采样频率对输入信号采样,当连续多个值都是同一电平值时,输出才为这个电平值,如果信号出现高频抖动,导致连续采样的N个值不全都一样,输出则不会变化,这样就可以达到滤波的效果,采样频率越低,采样个数N越大,滤波效果就越好;

CCER寄存器:

        CC1P位:可以选择极性;

        CC1E位:控制输出使能或者失能;

CCER寄存器:       

        CC1S位:可以对数据选择器进行选择;

        ICPS位:可以配置分频器;

硬件电路自动在捕获之后完成CNT的清零工作:

        TI1FP1和TI1的边沿信号都可以通向从模式控制器,这个从模式中就有电路可以自动完成CNT的清零。(完成自动化操作的利器)

主从触发模式

主模式,从模式,触发源选择的简称

主模式:可以将定时器内部的信号,映射到TRGO引脚,用于触发别的外设;

从模式:接收其他外设或者自身外设的一些信号,用于控制自身定时器的运行,也就是被别的信号控制;

触发源选择:就是选择从模式的触发信号源的;

假如我们想要CNT置零,我们触发源选择会选择TI1FP1,得到TRGI去触发执行从模式中的Reset

 手册中14.4.2有详细介绍

输入捕获基本结构

注意:①CNT清零和CNT传入CCR1是有先后顺序的;

②CNT的值时有上限的,即ARR最大可设置为65535,则CNT最大也是65535,所以如果频率太低,可能会导致CNT计数溢出,不能精准计算出频率;

③从模式的触发源只有TI1FP1和TI1FP2,没有3和4,如果要使用CNT自动把CNT置零,则只能使用1和2

PWMI基本结构

CCR1就是整个周期的值,CCR2则是高电平时的值,且把CNT的值赋予CCR2不会导致CNT清零,则CCR2/CCR1即为占空比

本节内容主要对应数据手册中的14.3.5和14.3.6

代码实操

输入捕获模式测频率

这里是输入PWM信号

逻辑:初始化TIM2的通道1,产生一个PWM波形,再通过函数修改频率和占空比,在OLED模块上实时显示此时的频率。

        这里我们在之前写的PWM控制LED呼吸灯的程序上做修改,因此需要多加一个修改频率的函数。

        这里我们需要修改ARR、PSC或者CCR的值来实现修改频率和占空比,因为调节ARR会影响占空比,所以我们通过调节PSC的值来修改频率,通过修改CCR的值来修改占空比。

要单独修改PSC的值,需要用到

void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);

 第三个参数即是指定的定时器预分频器的重装载的模式,一个是更新事件后生效,一个是立即生效

这里我们选择更新事件后生效

void PWM_PSC(uint16_t PSC)
{TIM_PrescalerConfig(TIM2, PSC, TIM_PSCReloadMode_Update);
}

这样我们就写好了修改PSC和CCR的值的函数

接下来写配置输入捕获的函数(按照下图的顺序)

先查看有关IC的配置函数

可以看到,OC的配置是有四个函数的,而IC也有四个通道,却只有一个函数配置,这是因为可以在这个函数的结构体参数中配置选择哪个通道(可能存在交叉配置,所以合在一起会更方便)

void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);

 这个函数可以快速配置两个通道,把外设电路结构配置成PWMI模式

void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);

给输入捕获结构体赋一个初始化值

void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);

 选择输入从模式的触发源TRGI

void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);

选择输出主模式的触发源TRGO

void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);

选择从模式

void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);

分别配置通道1、2、3、4的分频器

void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);

 分别读取四个通道的CCR

uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);

输出比较的模式下,CCR是只写的;输出捕获模式下,CCR是只读的;

写程序过程

1、打开GPIO和TIM 的时钟

我们计划用TIM3的通道1,所以GPIO需要初始化PA6,TIM需要初始化TIM3

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//配置TIM3的CH1对应的GPIO口PA6RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
2、配置GPIO,选择为上拉输入模式
	GPIO_InitTypeDef GPIO_InitStructure;//上拉输入(看手册推荐浮空,但是影响不大)GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);
3、配置时基单元,让CNT在内部时钟的驱动下自增运行
	//选择时基单元的时钟,选择为内部时钟TIM_InternalClockConfig(TIM3);//时基单元初始化TIM_TimeBaseInitTypeDef TimeBaseInitStructure;//指定时钟分频(与本次操作没太大关系)TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//计数器模式TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//ARR(防止测量的频率太小,导致计数溢出)TimeBaseInitStructure.TIM_Period = 65536 - 1;//PSC(此时频率为1Hz)TimeBaseInitStructure.TIM_Prescaler = 72 - 1;//重复计数器的值(高级计数器特有的,我们没有直接赋0)TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM3, &TimeBaseInitStructure);TIM_ClearFlag(TIM3, TIM_FLAG_Update);
4、配置输入捕获单元
	TIM_ICInitTypeDef TIM_ICInitStruct;//选择通道TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//配置滤波器(不会改变原信号的频率)TIM_ICInitStruct.TIM_ICFilter = 0x0F;//边沿检测,极性选择TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//触发信号分频器(不分频就是每次触发都有效,二分频则是每隔一次有效一次,以此类推)TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//选择触发信号从哪个引脚输入(配置数据选择器——直连通道和交叉通道)TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;TIM_ICInit(TIM3, &TIM_ICInitStruct);
5、选择从模式的触发源
	//触发源选择//配置TRGI的触发源为TI1FP1TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
6、选择触发从模式后需要执行的操作
	//配置从模式为ResetTIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
7、打开定时器
	//启动定时器TIM_Cmd(TIM3, ENABLE);

 初始化函数总体

#include "stm32f10x.h"                  // Device headervoid IC_Init(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//配置TIM3的CH1对应的GPIO口PA6RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;//上拉输入(看手册推荐浮空,但是影响不大)GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//选择时基单元的时钟,选择为内部时钟TIM_InternalClockConfig(TIM3);//时基单元初始化TIM_TimeBaseInitTypeDef TimeBaseInitStructure;//指定时钟分频(与本次操作没太大关系)TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//计数器模式TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//ARR(防止测量的频率太小,导致计数溢出)TimeBaseInitStructure.TIM_Period = 65536 - 1;//PSC(此时频率为1Hz)TimeBaseInitStructure.TIM_Prescaler = 72 - 1;//重复计数器的值(高级计数器特有的,我们没有直接赋0)TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM3, &TimeBaseInitStructure);TIM_ClearFlag(TIM3, TIM_FLAG_Update);TIM_ICInitTypeDef TIM_ICInitStruct;//选择通道TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//配置滤波器(不会改变原信号的频率)TIM_ICInitStruct.TIM_ICFilter = 0x0F;//边沿检测,极性选择TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//触发信号分频器(不分频就是每次触发都有效,二分频则是每隔一次有效一次,以此类推)TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//选择触发信号从哪个引脚输入(配置数据选择器——直连通道和交叉通道)TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;TIM_ICInit(TIM3, &TIM_ICInitStruct);//触发源选择//配置TRGI的触发源为TI1FP1TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);//配置从模式为ResetTIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);//启动定时器TIM_Cmd(TIM3, ENABLE);
}

当我们需要读取最新周期的频率是,只需要读取CCR的值再除以N即可

所以需要在编写一个读取CCR的值的函数

uint32_t IC_GetFreq(void)
{//在之前我们设置了PSC为72-1,fc=72M/(PSC+1)=1MHz//Freq=fc/N,且N=CCRreturn 1000000 / TIM_GetCapture1(TIM3);
}

然后就可以在主函数中调用试试

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"int main(void)
{OLED_Init();PWM_Init();IC_Init();OLED_ShowString(1,1,"Freq:00000Hz");//用于社会PSC和CCR的值PWM_CCR(50);PWM_PSC(720-1);while(1){OLED_ShowNum(1,6,IC_GetFreq(),5);}
}

此时会发现Freq=fc/N,fc=72M/(PSC+1),N=CCR得出频率应该是为1000Hz才对,但是OLED上却显示了1001Hz,这是电路中某处发生了变化的问题,也在正负一的误差之内,可以接受。

改善

想要解决的话,可以把计算Freq值的函数改为

uint32_t IC_GetFreq(void)
{//在之前我们设置了PSC为72-1,fc=72M/(PSC+1)=1MHz//Freq=fc/N,且N=CCRreturn 1000000 / (TIM_GetCapture1(TIM3) + 1);
}

这样就好了

PWMI测量频率占空比

按照下图配置

只需升级一下代码——把选择通道的代码修改一下即可

普通办法就是复制一份配置输入捕获单元的代码,把通道选择改为CH2,极性选择改为下降沿触发,数据选择器改为交叉输入

这样是可行的,但是ST公司特地为这步骤封装了一个函数,使用这个函数可以快速配置为PWMI模式(即配置为相反的配置,原是CH1,上升沿,直连通道,函数则是CH2,下降沿,交叉通道)

	//配置输入捕获单元TIM_ICInitTypeDef TIM_ICInitStruct;//选择通道TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//配置滤波器(不会改变原信号的频率)TIM_ICInitStruct.TIM_ICFilter = 0x0F;//边沿检测,极性选择TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//触发信号分频器(不分频就是每次触发都有效,二分频则是每隔一次有效一次,以此类推)TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//选择触发信号从哪个引脚输入(配置数据选择器——直连通道和交叉通道)TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;TIM_ICInit(TIM3, &TIM_ICInitStruct);//CH2TIM_ICInitTypeDef TIM_ICInitStruct;TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;TIM_ICInitStruct.TIM_ICFilter = 0x0F;TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Falling;TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_IndirectTI;TIM_ICInit(TIM3, &TIM_ICInitStruct);

上下两组代码等价 

	//配置输入捕获单元TIM_ICInitTypeDef TIM_ICInitStruct;//选择通道TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//配置滤波器(不会改变原信号的频率)TIM_ICInitStruct.TIM_ICFilter = 0x0F;//边沿检测,极性选择TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//触发信号分频器(不分频就是每次触发都有效,二分频则是每隔一次有效一次,以此类推)TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//选择触发信号从哪个引脚输入(配置数据选择器——直连通道和交叉通道)TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;TIM_ICInit(TIM3, &TIM_ICInitStruct);TIM_PWMIConfig(TIM3, &TIM_ICInitStruct);

注意:该函数只支持CH1和CH2的转换,其他不支持

这样就编写好了PWMI的初始化函数

接下来编写获取占空比的函数

uint32_t PWMI_GetDust(void)
{//理论知识:高电平持续时间存在CCR2中,整个周期持续时间存在CCR1中//占空比即CCR2/CCR1//两个值都需要补一个数return (TIM_GetCapture2(TIM3)+1) * 100 / (TIM_GetCapture1(TIM3)+1);
}

在主函数中调用实践

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"int main(void)
{OLED_Init();PWM_Init();IC_Init();OLED_ShowString(1,1,"Freq:00000Hz");OLED_ShowString(2,1,"Dust:000%");//用于社会PSC和CCR的值PWM_CCR(50);PWM_PSC(720-1);while(1){OLED_ShowNum(1,6,IC_GetFreq(),5);OLED_ShowNum(2,6,PWMI_GetDust(),3);}
}

性能分析

测频率的范围:因为计数器最多可计到65535,则能测量的最低频率为1M/65535,大约15Hz,可以通过加大预分频的值,可以测得更小的频率;

高频应该使用测频法来测量;

误差分析:出来正负一误差外,还有可能由晶振造成误差

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

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

相关文章

多线程进阶:Callable和JUC的常见类

Callable 这是一个接口,类似于Runnable。 Runnable用来描述一个任务,描述的任务没有返回值。 Callable也是用来描述一个任务,描述的任务是有返回值的。 如果需要使用一个线程单独的计算出某个结果来,此时用Callable是比较合适…

【好玩的开源项目】Windows 12网页版的部署与使用体验

【好玩的开源项目】Windows 12网页版的部署与使用体验 一、Windows 12网页版介绍1.1 Windows 12网页版简介1.2 项目地址 二、本次实践介绍2.1 本地环境规划2.2 本次实践介绍 三、安装httpd软件3.1 检查yum仓库3.2 安装httpd软件3.3 启动httpd服务3.4 查看httpd服务3.5 防火墙和…

springboot+canal+mysql+redis缓存双写一致性

canal官网地址:https://github.com/alibaba/canal/wiki/QuickStart 基本上按照官网的步骤来就行 准备 首先服务器上要安装好jdk,因为canal运行需要jdk,同时把canal对应的端口在服务中开放,否则连接不上 对于自建 MySQL , 需要先开启 Binl…

QT-day5

1、添加注册功能到数据库 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMessageBox> //消息对话框类头文件 #include <QDebug> #include <QPushButton> #include <QSqlDatabase> //数据库管理类 #include…

ChatGPT详细搭建教程+支持AI绘画

一、AI创作系统 SparkAi系统是基于很火的GPT提问进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT系统&#xff1f;小编这里写一个详细图文教程吧&#x…

SpringBoot 之配置加密

Jasypt库的使用 Jasypt是一个Java简易加密库&#xff0c;用于加密配置文件中的敏感信息&#xff0c;如数据库密码。 Jasypt库与springboot集成&#xff0c;在实际开发中非常方便。 1、引入依赖 <dependency><groupId>com.github.ulisesbocchio</groupId>&…

构建工具Webpack简介

一、构建工具 当我们习惯了Node中使用ES模块化编写代码以后&#xff0c;用原生的HTML、CSS、JS这些东西会感觉到各种不便。比如&#xff1a;不能放心的使用模块化规范&#xff08;浏览器兼容性问题&#xff09;、即使可以使用模块化规范也会面临模块过多时的加载问题。 这时候…

当当网商品详情数据接口

当当网商品详情数据接口可以通过当当网的开放平台获取相关信息。您可以注册当当开放平台账号&#xff0c;并按照要求提交申请获取API接口的调用凭证。获得授权后&#xff0c;您将会收到一组AccessKey和SecretKey。使用编程语言&#xff08;如Java&#xff09;调用API接口&#…

《计算机网络》——应用层

2.1 应用层协议原理&#xff08;P54&#xff09; 研发网络应用的核心是写出能够运行在不同端系统和通过网络彼此交流的程序。 2.1.1 网络应用程序体系结构 两种主流的应用体系结构&#xff1a;客户-服务器体系结构、对等体系结构。 客户-服务器体系&#xff1a;服务器是一个…

适合新手自学的网络安全基础技能“蓝宝书”:《CTF那些事儿》

CTF比赛是快速提升网络安全实战技能的重要途径&#xff0c;已成为各个行业选拔网络安全人才的通用方法。但是&#xff0c;本书作者在从事CTF培训的过程中&#xff0c;发现存在几个突出的问题&#xff1a; 1&#xff09;线下CTF比赛培训中存在严重的“最后一公里”问题&#xf…

【项目实战】Linux系统下jar包自启动

什么是jar包自启动 在Linux系统中&#xff0c;"jar包自启动"是指通过配置将Java程序打包成可执行的Jar文件&#xff0c;并设置其在系统启动时自动运行。以下是与jar包自启动相关的一些概念&#xff1a; Jar文件&#xff1a;Jar&#xff08;Java Archive&#xff09…

51单片机光照强度检测自动路灯开关仿真( proteus仿真+程序+报告+讲解视频)

51单片机光照强度检测自动路灯开关仿真( proteus仿真程序报告讲解视频&#xff09; 仿真图proteus7.8及以上 程序编译器&#xff1a;keil 4/keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;S0052 讲解视频 基于51单片机的光照检测自动路灯控制仿真设计( proteus仿…

Day56:组件库封装-TypeScript入门

配置 安装tsc工具进行编译 npm i typescript -g 查看版本号&#xff1a;tsc -v 编译ts代码-需要使用tsc编译之后才能运行&#xff0c;TS为JS的衍生&#xff0c;浏览器不能直接识别TS语法&#xff1a;tsc xxx.ts 运行ts代码&#xff1a;node xxx.js 或者直接运行ts代码——t…

【从0学习Solidity】52. EIP712 类型化数据签名

【从0学习Solidity】 52. EIP712 类型化数据签名 博主简介&#xff1a;不写代码没饭吃&#xff0c;一名全栈领域的创作者&#xff0c;专注于研究互联网产品的解决方案和技术。熟悉云原生、微服务架构&#xff0c;分享一些项目实战经验以及前沿技术的见解。关注我们的主页&#…

ChatGPT的问世给哪些行业带来了冲击?

目录 引言Chat GPT 对行业的影响在线客服和智能客服行业传统自动回复机器人的局限性Chat GPT 的提升能力 教育培训行业个性化学习需求的挑战Chat GPT 的个性化优势 金融保险行业客户服务的变革Chat GPT 的智能化应用 医疗健康领域自助诊断及咨询的便利性Chat GPT 在医疗领域的应…

vue项目打包部署到服务器,报错。

这个是因为后端部署服务器时&#xff0c;名称没有对上&#xff0c;不是前端的问题&#xff0c;后端配置名称和前端的包名称保持一致就可以了。

轻量级c语言开源日志库log.c介绍 - 实现不同级别和参数化日志打印

前言 c语言没有现成的日志库&#xff0c;如果要记录日志&#xff0c;需要自己封装一个日志库。如果要实现日志级别和参数打印&#xff0c;还是比较麻烦的&#xff0c;正好在github找到了一个c语言开源日志库&#xff0c;可以实现日志级别打印&#xff0c;参数打印&#xff0c;…

SAP PO运维(四):适配器消息监控

登录SAP PO系统,点击“Configuration and Monitoring Home”,使用PISUPER账号登录: 2、选择“适配器引擎->消息监控器”: 3、查看是否有报错消息: 双击报错的数字,筛选出报错的条目(可以根据状态、接口命名空间等来筛选):常见的报错消息有: 接口配置问题:字段为空值…

好题记录 Leetcode 394.字符串解码 中等难度

方法一&#xff1a;递归 思路很简单&#xff0c;比较好理解&#xff0c;注意细节处理&#xff01;&#xff01;&#xff01; class Solution { public:string decodeString(string s) {string ans;for(int i0;s[i]!0;i){if(s[i]>a&&s[i]<z)anss[i];if(s[i]>…

十四、流式编程(4)

本章概要 终端操作 数组循环集合组合匹配查找信息数字流信息 终端操作 以下操作将会获取流的最终结果。至此我们无法再继续往后传递流。可以说&#xff0c;终端操作&#xff08;Terminal Operations&#xff09;总是我们在流管道中所做的最后一件事。 数组 toArray()&…