带编码器的直流减速电机——基于STM32F407

2023-11-14

首先,什么是编码器?

编码器是将信号或数据进行编制、转换为可用以通讯、传输和存储的信号形式的设备。在这里,编码器就是能够将电机的转动信息(比如转速、转动角度等)转换为脉冲信号的设备。按照原理可分为(常见的)光电编码器(光学式)和霍尔编码器(磁式)。

接着,编码器的作用以及为什么要用编码器?

如上所述,编码器能够将电机的机械几何位移转化为脉冲信号或数字量。也就是说,有了编码器,我们通过检测编码器输出的脉冲信号,就能获取电机转动角度、转速等相关信息。这样我们不但能定性的控制电机的转向、转速,还能定量的测量。

那么,编码器的原理是什么以及怎么运用呢?

简单来说,就是电机带动码盘转动,码盘的结构使得当电机在转动时会产生A、B两相的脉冲信号,且这两路脉冲信号的相位差为90度(即正交)。如下图:
(图源自网络)
由于A、B信号正交,因此可以根据两个信号哪个先哪个后来判断方向,根据每个信号脉冲数量的多少及每圈电机产生多少脉冲数就可以算出当前行走的距离,如果再加上定时器的话还可以计算出速度。

好了,现在我们的处境是,我们有一个带编码器的直流减速电机,我们知道当电机转动的时候,它会产生A、B两相正交脉冲信号,通过检测脉冲信号我们就可以获取电机的运动状况。
那么,我们通过什么手段来检测脉冲数呢?
其中一种思路是,我们通过定时器的输入捕获或者GPIO引脚的外部中断来检测边沿变化,以此来检测脉冲数。这方法好像没毛病,当电机正常运转时行得通。但是如果电机输出的脉冲信号出现了毛刺呢?这样误差就来了,怎么办?通过软件编写算法来滤去毛刺似乎有点困难,于是我们想到通过硬件来处理这个毛刺。(而STM32正好有硬件编码器,nice!)
这里的脉冲输入是一种特殊的输入捕获情况,因此stm32专门在定时器中提供了编码器模式,可大大简化解析过程。

STM32的编码器接口模式
在该模式下能计算电机输出脉冲信号的个数,且stm32根据其内部机制能够消除毛刺的干扰。

配置过程:
由于编码器接口模式是一种特殊的输入捕获,所以要先配置一下输入捕获(毕竟你要通过捕获边沿来检测脉冲)。在输入捕获过程中,我们把A6、A7复用为TIM3,作为输入捕获的引脚,对电机的A、B相脉冲进行输入捕获。
输入捕获配置完成之后再配置一下编码器模式就可以开始工作了。

于是紧接着我们来看看编码器模式的配置函数TIM_EncoderInterfaceConfig:
STM32官方库函数
其输入参数中,TIMx就是输入捕获时设置的TIM3,polarity就分别是TI1和TI2的捕获极性(TI1是定时器输入通道1,TI2同理),即A、B两相信号的捕获极性(上升沿捕获或者下降沿捕获),重点来说说编码器的模式TIM_EncoderMode:
当模式选为TIM_EncoderMode_TI1时,计数器仅在TI1的边沿处计数
当模式选为TIM_EncoderMode_TI2时,计数器仅在TI2的边沿处计数
当模式选为TIM_EncoderMode_TI12时,计数器在TI1和TI2边沿处均计数
也就是说,模式1,我只以A相的脉冲信号为我的检测信号,TI2我就不管了。(B只是相对A滞后了90度,其它都是一样的,所以检测A就够了)。其它同理。
模式1和模式2显然就没什么差别了,那模式3前者有何不同呢?
这就涉及到网友们所说的编码器软件四倍频技术了:
四倍频
如图,A、B两相正交信号,如果根据模式1或模式2对脉冲信号进行检测,假设我们上升沿捕获一次,那么图中的信号我们只检测到3个上升沿,也就是三个脉冲。但是如果采用模式3,对TI1和TI2检测上升沿,那么同一段时间我们检测到6个上升沿。如果下降沿也检测,那么一共就是12个边沿跳变。每个实际来的脉冲会被检测4次,同样是12/4=3个脉冲,但是这样的话精度大大提高了。
入口参量:(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising ,TIM_ICPolarity_Rising);
通过这样配置,我们就完成了编码器软件的初始化。通过以上配置,我们完成了TIM3输入捕获的初始化以及编码器接口模式的相关配置,每来一个跳变沿,计数值变化一次。

至此,为了避免我们忘了初衷,现在我们来回顾一下我们最开始用编码器的初衷,前面我们说要用编码器来干嘛来着?获取电机转动角度、转速。
现在的处境是,我们通过STM32的TIM3的编码器模式,能够测出任意时刻的脉冲值了。现在要解决的就是如何将这个脉冲值转换成我们所要得到的信息(即转动角度、转速)。
首先,根据带编码器的直流减速电机的原理,显然无论电机的转速如何,每转产生的脉冲数是固定的。这里假设电机每转产生260个脉冲(具体数据各位自行查看自己的电机参数啦),那么只要我们用‘电机已产生的脉冲数’除以‘260个/转’,就可以得到电机转了多少圈,一圈即为360度,由此便可将脉冲数和转动角度联系起来。
这里要注意一点,由于我们用的是编码器模式3(也就是TIM_EncoderMode_TI12),我们得到的脉冲数是电机实际产生的脉冲数的四倍。则电机实际产生的脉冲数应为‘得到的计数值’除以4。于是,电机转动圈数为脉冲数除以260再除以4。
转动角度算出来了,转速呢?则是根据计数方向(递增计数或递减计数)来判断的,所以我们接下来的工作就是要搞清楚计数方向和编码器信号的关系。
让我们来看一下STM32的中文参考手册:
中文参考手册
网上几乎在这张表的讲解上都是一带而过,真正能把这张表讲清楚的几乎没有。后来看到一个人在表格上做了类似上图的注释,我才终于搞懂了。
大家还记得我们前面提到的TIM_EncoderInterfaceConfig函数吗,里面有个参量就是选择模式的,对吧。让我们再来回顾一下:
STM32官方库函数
注意到各模式后面的“xx edge depending on xx level”了吗?这就是上面这个表里的第二纵列所提到的“相反信号的电平”。
TIM_EncoderMode_TI1: Counter counts on TI1FP1 edge depending on TI2FP2 level,意思就是当选择模式1时,计数器根据TI2的电平高低来记录TI1的边沿信号。
这样说可能不好理解,我们来举个具体的例子:
中文参考手册
如上图,电机转动时产生A、B两相信号通过TI1、TI2输入到TIM3。
假设我们选择的是模式1,即计数器仅在TI1的边沿处计数。我们观察TI1的上升沿,若此时对应的TI2信号处于低电平(下图红框),于是根据表格我们可以得到计数方向为递增,假设计数器递增时电机正向转动,则可判断此时电机正转。
在这里插入图片描述
在这里插入图片描述
再譬如,假设我们选择模式2,即计数器仅在TI2的边沿处计数。我们观察TI2的下降沿,若此时对应的TI1信号为高电平(下图蓝框),于是根据表格我们可以得到计数方向为递减,假设计数器递减时电机反向转动,则可判断此时电机反转。
在这里插入图片描述
在这里插入图片描述
也就是说,当以TI1为计数信号时,需要根据TI2的电平(也就是第二纵列的“相对信号的电平”)来进行判断是向上计数还是向下计数。TI2也同理。
e.g.如果“仅在TI1计数”,当TI1为“上升”沿(表中第三纵列),此时要根据TI2的电平来做判断。根据下图,可知当TI1为上升沿的时候TI2为低电平,则根据上表可得知计数器为向上计数。这在下图得到了验证。
在这里插入图片描述
再例如,如果“仅在TI2计数”时,当TI2为下降沿时,如果TI1为低电平,则为向上计数(上图左侧);当TI2为下降沿时,如果TI1为高电平,则为向下计数(上图中部);当TI2为上升沿时,如果TI1为高电平,则为向上计数(上图左部);当TI2为上升沿时,如果TI1为低电平,则为向下计数(图中中部);
至此为止,我们便实现了这样的操作:通过使用带编码器的直流减速电机产生正交脉冲,通过STM32的TIM的编码器模式对脉冲进行计数,根据计数方向和编码器信号的关系来判断电机转动方向,利用脉冲计数值来计算电机转动位移。

接下来是代码部分,有些容易让人迷惑的地方(至少是让我迷惑了很久):
输入捕获初始化时Period和Prescaler的作用:
这里的period即为计数器的重装载值,prescaler即为预分频系数。注意在编码器模式时,要把TIM理解为计数器,而不是定时器,这样的话,时钟信号就不是系统内部产生的,而是通过PA6、PA7输入到TIM3的TI1和TI2的。
有了这么个理解,再来看Period和Prescaler就不难理解了。Period就是计数器每一次能检测脉冲的最大值,每来一个脉冲计数值就加一,当计数值超过period就溢出中断。Prescaler就是对电机产生的脉冲信号进行分频的分频系数。比如当分频系数为2时,每当电机产生两个脉冲,stm32才认为接收到一个有效脉冲,计数值才加一。

以下为部分代码

//思路:初始化TIM的编码器模式后,在main函数里死循环不断的读取CNT的值,从而来获得电机的脉冲数数据,以此来计算电机的转速、所转圈数等参数
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "pwm.h"
#include "encode.h"
#include "exti.h"
#include "key.h"

u32 pwm = 50000;

int main(void)
{
	uint32_t cnt_temp;			//用于暂存TIM的计数值,即TIM检测到的脉冲的数量
	float pulse;				//电机产生的实际脉冲值
	float round;				//电机转的圈数
	
	encoder_init();				//TIM3编码器模式初始化,A6、A7分别作为A相和B相的脉冲输入
	exti_init();				//外部中断,用于通过按键修改数据(比如PWM)
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//设置系统中断优先级分组2
	delay_init(168);  								//初始化延时函数
	uart_init(115200);								//初始化串口波特率为115200
 	TIM4_PWM_Init(50000-1,84-1);					//TIM4初始化,用于产生PWM供给直流减速电机
													//84M/84=1Mhz的计数频率,重装载值50000,所以PWM频率为100000/50000=2hz,即整个周期为500ms
	while(1)
	{
		TIM_SetCompare1(TIM4,pwm);					//设置供给电机的PWM值
		cnt_temp = read_cnt();						//得到脉冲计数值
		pulse = cnt_temp/4.0f;						//由于是TIM_EncoderMode_TI12,所以要四分频,即除以四,得到实际的脉冲值
		round = cnt_temp/4.0f/260.0f;				//假设电机每转产生260个脉冲,则通过该公式可求出电机转了几圈
		printf("cnt_temp:%d\r\n", cnt_temp);		//向串口打印脉冲计数值
		printf("pulse:%f\r\n", pulse);				//向串口打印实际脉冲值
		printf("round:%f\r\n", round);				//向串口打印电机转了几圈
		delay_ms(1000);								//每1s循环更新一次
//		if(TIM3->CR1&1<<4)	printf("forward");
//		else	printf("backward");
	}
}



//把TIM3理解为一个计数器而不是一个定时器,则没有了时序信号。
//这里TIM3的时钟信号(或者说是计数信号)将由电机编码器输出的脉冲代替,也就是说电机脉冲信号成为TIM3的信号,电机每产生一个脉冲被TIM3检测到,则计数器CNT加一(类比于时序信号时每隔一个时间段计数值加一)
//这样的话,输入捕获的自动重装载值period则影响着脉冲值计数到多少之后就溢出,比如65535的话,则接收到65535个脉冲信号之后计数值置零溢出
//这样的话,输入捕获的预分频系数prescaler的作用是,当我不分频时,来一个电机脉冲信号我计数值就加一,当我二分频时,只有接收到两个脉冲信号我才认为是一个有效脉冲,计数值才加一,简单来说就是计数值总体除以二了
//这样我们就把输入捕获初始化完成了,接下来是编码器模式的初始化
//设为TIM_EncoderMode_TI12模式,即计数器在TI1和TI2上升沿处均计数,再根据设置的极性是TIM_ICPolarity_Rising,也就是在TI1和TI2的上升沿计数器累加(或累减)-->那么到时候要除以二
//这样,编码器的初始化就完成了,接下来我们只要通过函数得出它的计数值,就可以知道电机产生的脉冲数,再根据电机的参数(每转产生多少个脉冲)就可以得到电机转了几圈
#include "encode.h"
#include "sys.h"

//初始化编码器
void encoder_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	TIM_ICInitTypeDef TIM_ICInitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_TIM3);    
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_TIM3);
	
	//Specifies the prescaler value used to divide the TIM clock.
	//也就是说,这里的TIM3的时钟信号其实是由A/B相的频率来决定的,类似于外部时钟,然后分频就是对这个脉冲频率分频,比如二分频就是把两个脉冲记为一个脉冲。
	TIM_TimeBaseStructure.TIM_Prescaler = 1-1;					//这里我们把它设为1,即不分频
	TIM_TimeBaseStructure.TIM_Period = 65535;					//每来一个脉冲信号的上升沿(下面有设置)计数值就累加(或累减),65535则为最大计数值,就溢出了
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
//	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //这里按理来说应该不起作用,因为计数方向是受TI1和TI2信号的影响的
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
	
	TIM_ICStructInit(&TIM_ICInitStructure);						//Fills each TIM_ICInitStruct member with its default value
	//相当于:
	//	void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct)
	//	{
	//	  /* Set the default configuration */
	//	  TIM_ICInitStruct->TIM_Channel = TIM_Channel_1;
	//	  TIM_ICInitStruct->TIM_ICPolarity = TIM_ICPolarity_Rising;
	//	  TIM_ICInitStruct->TIM_ICSelection = TIM_ICSelection_DirectTI;
	//	  TIM_ICInitStruct->TIM_ICPrescaler = TIM_ICPSC_DIV1;
	//	  TIM_ICInitStruct->TIM_ICFilter = 0x00;
	//	}
	TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising ,TIM_ICPolarity_Rising); //配置为编码器模式,计数器在TI1和TI2上升沿处均计数

	TIM_SetCounter(TIM3, 0);		//将脉冲计数值设为零
	TIM_Cmd(TIM3, ENABLE);			//使能TIM3
}

// 读取定时器计数值
uint32_t read_cnt(void)
{
	uint32_t encoder_cnt;
	encoder_cnt = TIM3->CNT;		//读取计数器CNT的值,CNT系uint32_t型的变量
	TIM_SetCounter(TIM3, 0);		//每一次读取完计数值后将计数值清零,重新开始累加脉冲,方便下一次计数
	return encoder_cnt;				//返回的值就是本次读到的计数值
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带编码器的直流减速电机——基于STM32F407 的相关文章

  • STM32在Debug时程序运行时间不对,Debug时定时器中断每次进入断点时间不对,定时器一开启就进入中断的解决办法

    一 Debug时程序时间不对解决办法 1 点击魔术棒 2 点击Debug 点击Settings 3 点击Trace 在Core Clock里修改为你的系统时钟 二 Debug时定时器中断每次进入断点时间不对 在Debug时 程序停下来 定时
  • 如何在 Cortex-M3 (STM32) 上从 RAM 执行函数?

    我正在尝试从 Cortex M3 处理器 STM32 上的 RAM 执行函数 该函数会擦除并重写内部闪存 所以我肯定需要在 RAM 中 但我该怎么做呢 我尝试过的是 使用 memcpy 将函数复制到 RAM 中的字节数组 检查它是否正确对齐
  • 当数据大小较小时,内存到内存 DMA 传输是否需要权衡?

    我正在学习 STM32 F4 微控制器 我正在尝试找出使用 DMA 的限制 根据我的理解和研究 我知道如果数据量较小 即设备使用DMA生成或消耗少量数据 则开销会增加 因为DMA传输需要DMA控制器执行操作 从而不必要地增加系统成本 我做了
  • 139-基于stm32单片机老人居家监护报警系统Proteus仿真+源程序

    资料编号 139 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 MQ4传感器 电位器模拟 MQ2传感器 电位器模拟 蜂鸣器 电机 制作一个基于stm32单片机老人居家监护报警系统Proteus仿真 2 通过MQ2传
  • rt-thread studio中新建5.0不能用

    文章目录 一 版本对比 二 文件和文件夹打斜杠 在使用RT Thread studio创建新工程5 0版本的时候 结果发现新建完成之后程序不能正常运行 但是创建4 10版本的时候却能运行 那肯定是新版本出现了BUG 一 版本对比 首先对比了
  • STM32F4 通过软复位跳转到引导加载程序,无需 BOOT0 和 BOOT1 引脚

    我问这个问题是因为可以在这里找到类似问题的答案 通过应用程序跳转到 STM32 中的引导加载程序 即从用户闪存在引导模式下使用引导 0 和引导 1 引脚 用户 JF002 JF002回答 当我想跳转到引导加载程序时 我在其中一个备份寄存器中
  • STM32F103

    提示 来源正点原子 参考STM32F103 战舰开发指南V1 3PDF资料 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 开发环境硬件普中科技 接线图在g
  • HAL库学习

    CMSIS简介 CMSIS Cortex Microcontroller Software Interface Standard 微控制器软件接口标准 由ARM和其合作的芯片厂商 ST NXP 软件工具厂商 KEIL IAR 共同制定的标准
  • 毕业设计 江科大STM32的智能温室控制蓝牙声光报警APP系统设计

    基于STM32的智能温室控制蓝牙声光报警APP系统设计 1 项目简介 1 1 系统构成 1 2 系统功能 2 部分电路设计 2 1 stm32f103c8t6单片机最小系统电路设计 2 2 LCD1602液晶显示电路设计 2 2 风
  • HAL 锁定和解锁函数如何使用以及为什么?

    我试图理解另一位程序员编写的代码 它使用了I C http en wikipedia org wiki I C2 B2C通信以将数据写入 STM32 微控制器的 EEPROM 一般来说 我理解他的代码是如何工作的 但我不明白他为什么使用HA
  • 硬件基础-电容

    电容 本质 电容两端电压不能激变 所以可以起到稳定电压作用 充放电 电容量的大小 想使电容容量大 使用介电常数高的介质 增大极板间的面积 减小极板间的距离 品牌 国外 村田 muRata 松下 PANASONIC 三星 SAMSUNG 太诱
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • 毕设开题分享 单片机智能教室系统(智能照明+人数统计)

    1 简介 Hi 大家好 今天向大家介绍一个学长做的单片机项目 单片机智能教室系统 智能照明 人数统计 大家可用于 课程设计 或 毕业设计 项目分享 https gitee com feifei1122 simulation project
  • CMSIS & STM32,如何开始? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想在 STM32 上使用 CMSIS 启动项目 网上一搜 没找到具体的教程 有些使用 SPL 开始项
  • 嵌入式开发--STM32G4系列片上FLASH的读写

    这个玩意吧 说起来很简单 就是几行代码的事 但楞是折腾了我大半天时间才搞定 原因后面说 先看代码吧 读操作 读操作很简单 以32位方式读取的时候是这样的 data IO uint32 t 0x0800F000 需要注意的是 当以32位方式读
  • STM32 上的 ADC 单次转换

    我正在研究 STM32 F103x 上的 ADC 编程 并从最简单的情况 单次转换开始 测量内部温度传感器 连接到 ADC1 的值 并使用 USART 将其发送到 COM 端口 目标似乎很明确 但是当我尝试将源代码下载到闪存时 它不会向 C
  • STM32 上的位置无关代码 - 指针

    我已成功在 STM32 上构建并运行位置无关的代码 向量表和 GOT 已修补 一切正常 但我对这样的代码有问题 double myAdd double x return x 0 1 double ptrmyAdd double myAdd
  • STM32F0、ST-link v2、OpenOCD 0.9.0:打开失败

    我在用着发射台 http www ti com ww en launchpad about htmlgcc arm none eabi 4 9 2015q2 为 STM32F0 进行编译 现在我想使用该集合中的 arm none eabi
  • 移动数组中的元素

    我需要一点帮助 我想将数组中的元素向上移动一个元素 以便新位置 1 包含位置 1 中的旧值 new 2 包含 old 1 依此类推 旧的最后一个值被丢弃 第一个位置的新值是我每秒给出的新值 我使用大小为 10 的数组 uint32 t TE

随机推荐

  • 编译原理实验二:Bison

    编译原理实验二 Bison 实验要求 1 了解Bision基础知识 如何将文法产生式转换为Bison语句 2 阅读 src common SyntaxTree c 对应头文件 include SyntaxTree h 理解分析树生成的过程
  • 你对C++头文件了解多少?——盘点C++的常用头文件

    相信大家在编写C C 程序时 最必不可少的部分之一就是头文件了 然而 由于不同的函数所对应的头文件各不相同 就导致一部分人 尤其是我 写代码的时候常常遇到忘记所需头文件的窘境 为了解决这个问题 今天我特意搜集了C 中常用的头文件及其包含的库
  • FICO F.27 Customer statement 打印

    需求 定制化打印 替换标准的F 27打印 类似于采购订单的打印 但是略有不同 查阅资料之后步骤如下 T code F 27 is SAP standard program to produce customer vendor corresp
  • 数据结构简述,时间、空间复杂度,学习网站推荐

    目录 IT 学习路线 相关坚韧大厚书 相关有趣 耐看书或视频 数据结构与算法学习网站推荐 刷题 时间 空间复杂度 数据结构简述 基本概念 数据结构与算法简述和CS综述整理 本文非基础的教程 本文会列出大量学习和参考网站 老惯例 一个文章是一
  • 2022 PostgreSQL 数据库生态大会:拓数派资深工程师 王淏舟将发表主题演讲

    由中国开源软件推进联盟PostgreSQL分会 中科院软件所 CSDN联合举办的 中国PostgreSQL数据库生态大会 将于2月17 19日召开 本届大会以 协同共进 为主题 邀请专家学者 厂商和用户代表 就PostgreSQL在行业和区
  • Vue3开发教程(一、学习Vue前需要了解的内容)

    前言 本文是笔者学习vue前端技术过程的总结 其中包括vue开发需要了解的相关技术如 node ES6 TypeScript vite ElementUI 以vue作为主线来介绍相关技术 最后通过一个典型的前端应用来体会vue的开发 希望笔
  • 最长子序列 JAVA 2019国赛试题F

    试题 F 最长子序列 时间限制 1 0s 内存限制 512 0MB 本题总分 15 分 问题描述 我们称一个字符串 S 包含字符串 T 是指 T 是 S 的一个子序列 即可以从 字符串 S 中抽出若干个字符 它们按原来的顺序组合成一个新的字
  • [SQL]yyyymmdd类型与yyyy-mm-dd日期类型的相互转换

    法1 from unixtime unix timestamp 20171205转成2017 12 05 select from unixtime unix timestamp 20171205 yyyymmdd yyyy mm dd fr
  • 树结构,二叉树,hash树

    目录 1 树的概念 2 二叉树基本操作 3 hash树 1 树的概念 1 树的特性 1 一棵树中的任意两个结点有且仅有唯一的一条路径连通 2 一棵树如果有n个结点 则它一定有n 1条边 3 在一棵树中加一条边将会构成一个回路 2 二叉树 1
  • hibernate注解反向生成表结构

    直接上源码 package com gxy pojo model import java util Date import javax persistence Column import javax persistence Entity i
  • EVE部署

    EVE NG 镜像导入 IOL 镜像位置 opt unetlab addons iol bin qemu 镜像位置 opt unetlab addons qemu 设备图标位置 opt unetlab html images icons E
  • Mac :谷歌浏览器 NET::ERR_CERT_INVALID 此证书已被撤消。网络错误和攻击行为通常是暂时的,因此,此网页稍后可能会恢复正常

    1 美图 2 背景 今天突然访问一个https 1x 5x x xx 网站 然后无法访问 谷歌浏览器访问地址报错如下 XXX 通常会使用加密技术来保护您的信息 Google Chrome 此次尝试连接到 XXX 时 此网站发回了异常的错误凭
  • 安卓使用SQLite数据库

    目录 理论 SQLite构成 SQLite的整体结构图 SQLite数据类型 创建安卓应用 基于Empty Activity模板创建安卓应用CreateDeleteDB 将背景图片拷贝到drawable目录 打开字符串资源文件 string
  • 利用DSP实现ADC采集数据以及DAC输出

    1 解决方案 必要的公式 文字等 在课外实验中 我们选择利用ADC对输入的信号进行采集 然后利用串口控制DAC的输出 实现通过串口控制DAC输出采集到的波形的功能 在本实验中 是通过判断串口发送的数据来实现对相应DAC的控制的 为了方便 我
  • 有些运行符不能重载为友元函数,它们是:=,(),[]和->。

    原因 有人说是因为 C 规定赋值运算符 只能重载为类的非静态成员函数 而不可以重载为类的友元函数 不能重载为类的静态成员应该比较容易理解 因为静态成员函数是属于整个类的 不是属于某个对象的 它只能去操作类静态数据成员 而赋值运算符 是基于对
  • Calendar类获取月份时月份加一而星期数减一

    Java中Calendar MONTH返回的数值其实是当前月距离第一个月有多少个月份的数值 JANUARY在Java中返回 0 所以我们需要 1 Java 中Calendar DAY OF WEEK中返回的是一周中的第几天 所以他会受到 第
  • Windows Cluster 投票权问题

    在日常运维中 如果你的 Windows Cluster 需要升级 重启 意外宕机 网络中断等 你知道该怎么操作才能保证集群的可用性吗 按什么样的顺序怎样关闭或启动集群节点吗 怎么快速恢复你的集群呢 接下来 我们就以实践操作来解决这几个疑问
  • StableDiffusion中LORA模型的使用

    目录 前言 一 LoRA是什么 二 使用方法 1 存放LORA模型 2 使用LORA模型 3 查看结果 总结 前言 1 Sampler 采样方式 在Stable Diffusion WebUI中的Sampling method中进行选择 2
  • 如何成为一个优秀的JAVA程序员 如何成为高级JAVA程序员 细节决定一个程序员的成败

    给一个刚出社会的程序员新生一个建议 想成为一个优秀的程序员 高级程序员 不能眼高手低 不能认为开发新项目 技术研发才学到东西 不能看不起维护系统 不要以为自己懂的技术越多自认为自己很牛叉 假如你忽略了一个问题那么你永远成为不了优秀的程序员
  • 带编码器的直流减速电机——基于STM32F407

    首先 什么是编码器 编码器是将信号或数据进行编制 转换为可用以通讯 传输和存储的信号形式的设备 在这里 编码器就是能够将电机的转动信息 比如转速 转动角度等 转换为脉冲信号的设备 按照原理可分为 常见的 光电编码器 光学式 和霍尔编码器 磁