【MSP432电机驱动设计—下篇】霍尔编码器测车轮运行距离与M/T综合公式法测速概念

news2024/12/23 22:10:57

开发板型号为MSP432P401r                        

今日得以继续我的MSP432电赛速通之路,本篇使用MSP432编程学习霍尔编码器M/T公式法测速概念,最终实现用外部中断方式测得小车行走路程,文章学习讲解原理、附上实例实践、附上关键代码、附上整体测试工程供下载测试使用。

这是一个装有13线霍尔编码器的电机,今日我们将学会如何使用它来进行测距离与测速概念:

学习之前需要确保自己 已经掌握以下有关MSP432的知识:

TB6612驱动电机、串口通信、定时器捕获、定时器配置PWM输出等

如果有关TB6612驱动电机怎么写还是不熟练,可以看我这篇文章:

【MSP432电机驱动学习—上篇】TB6612带稳压电机驱动模块、MG310电机、霍尔编码器_NULL指向我的博客-CSDN博客

如果串口通信不熟悉,可以看这篇:

MSP432学习笔记10:串口接收字符串命令并执行任务_NULL指向我的博客-CSDN博客

MSP432学习笔记3:串口通信初步配置收发_NULL指向我的博客-CSDN博客 

 如果定时器捕获的基础又忘了,可以看这篇:

MSP432学习笔记9:定时器A-----捕获_NULL指向我的博客-CSDN博客

 如果都学习过了,比较熟悉了,我们就接着往下进行学习:

编码器及原理简介:

测速测正反转原理简介:

编码器是一种用来测量机器旋转或位移的传感器,能够测量机械部件在旋转或直线运动时的位移信息或速度等信息。

电机旋转时,编码器的码盘与电机同轴旋转

霍尔编码器圆盘上分布有磁极,当圆盘随电机主轴转动时,会输出两路相位差90°的方波,用这两路方波可测出电机的转速和转向。

霍尔编码器一般是13线的,就是转一圈每项会输出13个脉冲,这个精度基本能够满足大部分使用场景的要求,其次要结合电机减速比来计算,进行相应的乘计算得出车轮子转一圈,编码器会输出多少脉冲,比如13线霍尔编码器装载于减速比为20的电机上,那车轮转一圈,霍尔编码器的脉冲数就是13*20=260个。

从该图中我们发现,这个连接了编码器的电机,共有六条接线,有俩条是电机的正负接线,有俩条是编码器的地线,另外俩条线称为:编码器B相与编码器A相的线便是我们需要深入学习的编码器信号输出脚,我们暂且从下文开始分别称他们为E1B与E1A :

E1A和E1B是13线霍尔编码器的两个输出信号,用于输出轴旋转方向和位置信息。

E1A是正交方波信号,当轴逆时针旋转时,E1A会先于E1B产生信号变化,用于判断旋转方向。

E1B是正交方波信号,当轴顺时针旋转时,E1B会先于E1A产生信号变化,用于判断旋转方向。

两个信号数量相同,相位差90度,可以通过对信号的计数和相位差计算来确定轴的位置。

编码器相关参数了解:

霍尔编码器分辨率(PPR):

霍尔编码器的分辨率是指它所能检测到的旋转或线性位移量的最小变化量。

分辨率通常取决于以下几个因素:

1. 传感器本身的特性:

霍尔编码器使用霍尔效应传感器或磁电阻传感器来测量磁场变化,这些传感器的特性会直接影响分辨率。不同类型的传感器具有不同的灵敏度和噪声水平,因此会对分辨率产生影响。

2. 磁场的强度和分布:

霍尔编码器的分辨率还受到磁场的强度和分布的影响。较强的磁场可以提高编码器的灵敏度,从而提高分辨率。同时,磁场的均匀性和稳定性也对分辨率产生影响。

3. 编码器的工作频率和采样率:

编码器的工作频率和采样率决定了对旋转或位移变化的采样频率。较高的工作频率和采样率可以提高分辨率,但也会增加系统的复杂性和成本。

4. 信号处理和解码算法:

最后,编码器所采用的信号处理和解码算法也会影响分辨率。一些高级的算法可以有效地提高分辨率,并处理传感器噪声和非线性等问题。

5.其他因素:

机械传动装置的精度、机械松动等。

霍尔编码器精度:

霍尔编码器的精度通常是以位/转或弧度/转来衡量的。具体的精度取决于编码器的设计和制造质量。通常情况下,高精度的霍尔编码器的精度会比较高,误差较小。

对于位/转的精度,计算公式为:

精度 = (编码器所能输出的位数) / (电机输出轴每转的脉冲数)

编码器倍频:

某编码器有N个筛格\线,理论上电机带动转一圈,只能输出N个信号,倍频可以使这个信号变为原来的n倍。

这个倍频不是体现在硬件电路上的,而是体现在编程捕获信号处理上的:

编码器输出的脉冲一般占空比都是50%的矩形方波,A相通道与B相通道的相位差为90°

只用通道A,且只捕获上升沿,即为1倍频:

只用通道A,且捕获上升沿与下降沿,即为2倍频:

即用通道A又用通道B,且都是上升下降沿捕获,就是4倍频:

编码器相关数学计算:

首先看 购买的电机与编码器的电气参数:

 

 由图可知,我购买的是260线霍尔编码器,车轮转动一圈会输出260个脉冲,4倍频后就是1040

最终推荐使用公式三M/T综合法,前俩种用来递进式理解公式三的M/T综合法原理:

M法测速计算公式1——高速:

这是建立在电机运转高速,脉冲频率相当高的情况下使用,此时脉冲的俩个上升沿之间间隔时间极其短,不方便测量了拿出来作数学运算,会有较大误差。

因此采用在采样时间内计数上升沿个数,然后作计算的方式

假设:

1.编码器单圈总脉冲数为C

2.统计时间为T,(一般为1S)

3.T时间内计数捕获的脉冲数位M0

4.需要求得的转速为n(圈/秒)

这个公式在电机高速运转下,T时间内捕获的脉冲数M0足够大时,计算相对简便精确,

但在低速状态下误差十分大,因为M0基数小,是个位数级别的了,少一个脉冲计数,计算结果就会有很大误差,下图举例为:

上升沿捕获,刚好最大误差少记数一个脉冲的情况:

 如果是上升沿与下降沿捕获计数(2倍频),那最大误差就可能少记数达到2个脉冲了

 双通道4倍频捕获计数,可以让脉冲数乘4倍捕获,也许可以提高公式1在低速下的准确性,但也不是根本上解决问题的办法

T法测速计算公式2.1——低速:

此公式适用于电机运转低速,脉冲频率低的时候使用,此时脉冲的俩个上升沿之间时间间隔比较长,可以拿来作数学计算,算出脉冲的频率了:

假设1:

1.编码器单圈总脉冲数为C

2.捕获的俩个脉冲间隔时间为TE

 下图公式表示求出1S内有多少个编码器周期,就表示捕获计数到了多少次上升沿,借此计算转速

T法测速计算公式2.2——低速:  

 此公式也是用来计算电机低速时的转速的,其实这个公式最终化简后与2.1是一样的,只不过是同一个公式,俩种理解罢了。

 这里的理解是,假定一个固定频率为F0的高速脉冲,测量编码器周期内高速脉冲上升沿个数,以求得转速。

M\T 综合测速公式3——兼顾:

这种方法综合了M 法和T 法各自的优势,既测量编码器脉冲数又测量一定时间内的高频脉冲数。

在一个相对固定的采样时间内,假设:

1.编码器单圈总脉冲数C(常数)

2.编码器脉冲数产生 M0个 (测量值)

3.固定频率为F0的高频脉冲(常数)

4.采样时间内高频脉冲计数值为M1

由于M/T 法公式中的 F0和C 是常数,所以转速n 就只受 M0和 M1的影响。

1、高速时, M0增大, M1减小,相当于M 法

2、低速时, M1增大, M0减小,相当于T 法。

使用示波器观察编码器的输出波形:

编程说明:

首先我们编写函数让TB6612能够驱动起来,包含分派引脚,组织接线,初始化引脚,初始化定时器,编写加减速、正反转函数等,这些在上篇都已经讲过了,此处不多加赘述,我直接贴代码透露引脚分配与函数组成,此处就只贴出TB6612.h文件中内容了,其余代码会在后续完整贴出,这里不影响理解就行:

 介绍代码实现功能:

以下为上位机的有效命令,通过串口A0发送给MSP432,MSP432接收后会做相应控制:

要使电机加速:上位机发送ADD\r\n\0                       
要使电机减速:上位机发送REDUCE\r\n\0
要使电机正转:上位机发送COROTATION\r\n\0
要使电机反转:上位机发送REVERSE\r\n\0
要使电机停转:上位机发送STOP\r\n\0

以下为上位机发送其余错误指令后MSP432的回应:
ERROR!\r\n

首先写好宏定义,引脚位带操作,声明函数等:

#include <ti/devices/msp432p4xx/driverlib/driverlib.h>

//定义定时器中断需要的初始化变量
//定义调整占空比的变量 占空比 = PWM_DIVA/CCR0 
//占空比越大电机转速也越大
#define CLKDIV 48   //时钟分频
#define CCR0 99			//时基(改变此项频率会变)

#define CCR1_MIN 3	//PWMA最小值
#define CCR1_MAX 99	//PWMA最大值		

#define DIV_PWM 3   //PWMA加减分度值,改变此项能改变PWMA的加减分度


// 位带操作
//定义引脚名称,STBY引脚接5V或者3.3V皆可
#define AIN1   BITBAND_PERI(P4OUT,0)
#define AIN2   BITBAND_PERI(P4OUT,1)
#define PWMA   BITBAND_PERI(P7OUT,6)


extern uint16_t PWM_DIVA;//改变占空比作用的变量

void inint_TB6612(void);

void speedup_A(void);     //加速
void speeddown_A(void);		//减速
void set_A(uint16_t i);		//设置正反转

 然后就是串口通信相关编程,基本思路是:定义好串口命令,填上对应逻辑即可:

 定义串口用到的变量数组:

#include "string.h"

void handle_uart(void);

//定义串口程序需要用到的变量
char USART0_save[20];  //存字符串命令的数组
char USART0_xb=0;			 //帮助数组下标位移
char USART0_flag=0;    //接收完成标志
//定义命令字符串,用于与接收进行比较 ,不可修改
const char str1_order[]="ADD\r\n\0";        //加占空比
const char str2_order[]="REDUCE\r\n\0";     //减占空比
const char str3_order[]="COROTATION\r\n\0"; //正转
const char str4_order[]="REVERSE\r\n\0";    //反转
const char str5_order[]="STOP\r\n\0";       //停转
char error_receive[]="ERROR!\r\n";          //错误命令

 串口接收中断的编写处理:

//串口服务函数,串口1接收命令,存在数组中
void EUSCIA0_IRQHandler(void)
{
	uint32_t status = UART_getEnabledInterruptStatus(EUSCI_A0_BASE);
	if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)      //接收中断
	{
		USART0_save[USART0_xb++]=MAP_UART_receiveData(EUSCI_A0_BASE);
		if(USART0_xb== 20){USART0_xb=0;	}							      //下标最大不超过20
		if(USART0_save[USART0_xb-1]=='\0'){USART0_flag=1;}  //命令以\0结尾	
	}
}

中断接收标志处理函数的编写,整体函数其实就是一个由众多if()语句组成的判断处理函数,一进入就是一个最大的前提:if(USART0_flag==1),即串口接收中断服务函数确认接收到了完整字符串并存在了数组之中,将USART0_flag标志置1,此时就是对数组中字符串命令进行判定操作的时机,然后就是五条命令的判断:先判断命令长度,再根据其判断是否为接受到的命令字符串,根据情况发送不同回应,最后别忘了清空数组与数组下标索引(变量)。

此函数直接放于主函数while(1)循环中即可,随时判断进入:


//串口中断处理函数:
void handle_uart(void)
{
	if(USART0_flag==1)
				{
						printf("%s",USART0_save);            //先重复接受到的字符串
						USART0_flag=0;								           //再清理标志位
				
				//先判断命令长度,再根据其判断是否为接受到的命令字符串,根据情况发送不同回应
						if(USART0_xb==6)
						  {
							 if(strncmp(USART0_save,str1_order,6)==0)            //接收到命令1,执行加速(加占空比)
							 {printf("PWM_DIVA=%d\r\n",PWM_DIVA);speedup_A();}
							 else  
								 printf("%s",error_receive);
						  }
						else if(USART0_xb==9)																	
						  {
							 if(strncmp(USART0_save,str2_order,9)==0) 						//接收到命令2,执行减速(减占空比)
							 { printf("PWM_DIVA=%d\r\n",PWM_DIVA);speeddown_A();}
							 else  
								 printf("%s",error_receive);
						  }
						else if(USART0_xb==13)																	//接收到命令3,执行正转
						  {
							 if(strncmp(USART0_save,str3_order,13)==0) 
							 { printf("SET COROTATION\r\n");set_A(1);}
							 else  
								 printf("%s",error_receive);
						  }
						else if(USART0_xb==10)
						  {
							 if(strncmp(USART0_save,str4_order,10)==0) 						//接收到命令4,执行反转
							 { printf("SET REVERSE\r\n");set_A(2);}
							 else  
								 printf("%s",error_receive);
						  }
						else if(USART0_xb==7)
						  {
							 if(strncmp(USART0_save,str5_order,7)==0) 						//接收到命令5,执行停转
							 { printf("SET STOP\r\n");set_A(0);}
							 else  
								 printf("%s",error_receive);
						  }							
						else 
							printf("%s",error_receive);
						
						printf("\r\n");						
						memset(USART0_save,0,sizeof(USART0_save)); //处理完命令别忘了将数组清零,以便接收下个命令
						USART0_xb=0;                               //重置数组下标	
				}
}

 示波器测量波形视频演示:

示波器测电机编码器输出信号视频

此阶段完整工程下载地址:

https://download.csdn.net/download/qq_64257614/87965347?spm=1001.2014.3001.5503

 

编码器测距离在MSP432的编程实战:

在经过前面的示波器显示波形模块的学习后,我们对编码器在电机不同状态下的输出信号有了更感性的认知了,但我们可以循序渐进,首先尝试使用编码器测距离,这个不涉及时间的概念,因此相对逻辑也更简单些,代码也可顺延上个阶段的代码进行继续编程:

  介绍代码实现功能:

以下为上位机的有效命令,通过串口A0发送给MSP432,MSP432接收后会做相应控制:

要使电机加速:上位机发送ADD\r\n\0                       
要使电机减速:上位机发送REDUCE\r\n\0
要使电机正转:上位机发送COROTATION\r\n\0
要使电机反转:上位机发送REVERSE\r\n\0
要使电机停转:上位机发送STOP\r\n\0

以下为上位机发送其余错误指令后MSP432的回应:
ERROR!\r\n

公式计算问题的解决:

已知我使用的霍尔编码器的线数是13,电机的减速比是20,因此我的电机转一圈,理论上应该有13*20=260个脉冲信号。

当我接受到N个脉冲时,我可以根据N与260的比值了解到轮子转动了究竟多少圈,据此可以计算轮子前进的路程X。

其中还有一个常理需要实地测量计算出来,就是轮子的周长,这个值有俩种获取途径:

1.固守圆规:测量轮子半径直径等,通过圆周长数学公式进行计算得出圆周长C

2.化圆为线:通过使用软质地尺绕轮一圈进行最简单粗暴的直接测量出圆周长C

最后就是路程X的计算公式了,该公式其余都是常量,只有N(脉冲信号个数)需要测量:

X=(N/260)*C

编程问题解决:

编程上,我们只需要弄明白如何获取上升沿或者下降沿次数即可,这里有俩种思路,分别占用不同的单片机资源:

1.占用通用引脚资源:外部中断法:配置一个通用普通引脚为外部中断模式,设置好上升沿或下降沿触发的方式,然后在中断服务部分中使用变量计数中断次数,达到计数脉冲数的目的。

2.占用定时器资源:定时器捕获法:定时器有捕获的模块,我们也可用定时器捕获上升沿、下降沿等,达到计数脉冲的目的。

此处演示最最简单的外部中断法的实现

定义好需要用到的变量、引脚:

//外部中断测速
#define INT_CAP BITBAND_PERI(P4OUT,2)

extern uint32_t CAPTURE;        //外部中断次数记录
extern uint32_t DISTANCE;       //行驶总路程长度单位cm


uint16_t uart_cnt=0;		//串口计时标志
uint16_t uart_flag=0;  //串口发送标志
uint16_t Sta;      //轮子正反转情况1正转0反转

配置好需要的外部中断引脚:

void Interrupt_CAP_inint()  //外部中断初始化
{
	//1.配置GPIO输入 
  MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P4,GPIO_PIN2);	
	//2.清除中断标志位
	MAP_GPIO_clearInterruptFlag(GPIO_PORT_P4, GPIO_PIN2);
	//3.配置触发方式 上升沿
	GPIO_interruptEdgeSelect(GPIO_PORT_P4,GPIO_PIN2,GPIO_LOW_TO_HIGH_TRANSITION);
	//4.开启外部中断
  GPIO_enableInterrupt(GPIO_PORT_P4,GPIO_PIN2);
	//5.开启端口中断
	Interrupt_enableInterrupt(INT_PORT4);
	//6.开启总中断
	Interrupt_enableMaster();
}

编写外部中断服务函数:

//编写GPIO ISR(外部中断中断服务函数)
void  PORT4_IRQHandler(void)
{
	uint16_t status;
	status=GPIO_getEnabledInterruptStatus(GPIO_PORT_P4);
	GPIO_clearInterruptFlag(GPIO_PORT_P4,status);
	GPIO_clearInterruptFlag(GPIO_PORT_P4,status);
	
	if(status & GPIO_PIN2)//对应P4^2中断
	{
		if(Sta==1){CAPTURE++;}		//正转就增加
		if(Sta==0){CAPTURE--;}		//反转就减小
	}	
}	

 然后为了使用串口向上位机报告,我们需要初始化一通用定时器来定时,关键代码如下:

 此处我引用了他人库中的函数,初始化使用了一个周期为0.05s的定时器

#include "timA.h"

TimA0_Int_Init(37499,64); //初始化一个周期为0.05s的通用定时器


//通用定时器中断中断服务函数
void TA0_0_IRQHandler(void)
{
    MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A0_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_0);
		if(++uart_cnt==40)         //每2秒打印一次总运行路程
		{uart_cnt=0;uart_flag=1;}
}

 此段处理发送的函数在主函数while(1)循环直接调用即可。

void handle_printf_distance(void)
{
	if(uart_flag==1)
	{
		uart_flag=0;
		DISTANCE=(CAPTURE*15/260);
		printf("CAPTURE=%d\r\n",CAPTURE);
		printf("DISTANCE=%d\r\n",DISTANCE);//精确到小数点后2位输出距离
	}
}

视频演示:

 最终下载后能每过2S向上位机汇报一次总脉冲与总路程,电机正转加厘米数,反转就减:

 可以从我的视频中发现有个小BUG,那就是当反转时会减去CAPTURE捕获值,但没考虑减到0以下的情况,因此对数据处理在0以下的情况就不是很好,产生了虚高的数。

编码器测距离

测试工程下载:

https://download.csdn.net/download/qq_64257614/87966413?spm=1001.2014.3001.5503

 

编码器M/T公式测速在MSP432的编程思路:

使用MSP432捕获,以及M/T公式法计算速度:

此处沿用上个标题中的串口控制程序来继续编程:

对于编码器A\B相的信号捕获,我们其实有俩种思路,一种是复用引脚为中断,在中断服务函数中记录次数,另一种就是用定时器捕获进行编码器的信号捕获。

我们一般推荐使用定时器捕获编码器信号,外部中断的方式如果次数很多的话,可能会占用相当的MCU资源,况且定时器写代码捕获编码器信号契合度也比较高,更简洁。

本文在此部分点到即止,不展示代码。

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

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

相关文章

微信月活破10亿,安全性靠谁来支撑?

&#x1f449;腾小云导读 微信作为月活过10亿的国民级应用&#xff0c;其安全能力备受关注。值得注意的是&#xff0c;没有足够的特征数据&#xff0c;安全策略将是"无根之木&#xff0c;无源之水"。微信安全数据仓库作为安全业务的特征数据存储中心&#xff0c;每天…

【C/C++】解析 类成员属性

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

JVM类加载双亲委派-JVM(二)

上篇文章说了java类的加载&#xff0c;验证、准备、解析、初始化。类的初始化必须是类加载完才执行&#xff0c;所以类的构造方法初始化是在静态方法之后执行。 JVM类加载机制-JVM&#xff08;一&#xff09; 一、类加载和双亲委派机制 前面类加载主要通过类加载器实现&…

JavaWeb小记——登录、注册

目录 登录项目 步骤 1.首先写一个前台页面&#xff0c;一个form表单——login.jsp 2.后台获取前台输入的参数&#xff0c;并作校验 3.写一个JDBC工具类&#xff0c;用来连接数据库&#xff0c;本案例使用Druid连接池 4.写一个登录工具类&#xff0c;在数据库中查询数据&…

【云原生】k8s的pod基础(上)

1.pod的相关知识 1.1 pod的基础概念 pod是kubernetes中最小的资源管理组件&#xff0c;Pod也是最小化运行容器化应用的资源对象。一个Pod代表着集群中运行的一个进程。kubernetes中其他大多数组件都是用绕着Pod来进行支撑和扩展Pod功能的&#xff0c;例如&#xff0c;用于管…

C++面试需求

一.auto 1.介绍&#xff1a; auto 是一个用于类型推导的关键字。它允许变量的类型在编译时根据其初始化值自动推断 例子&#xff1a; &#xff08;1&#xff09;自动类型推导变量 // C program to demonstrate working of auto // and type inference#include <bits/std…

shell正则入门

1.系统通配符 * #所有 . #当前目录 .. #当前目录的上一级目录 - #当前目录的上一次所在的目录 ~ #家目录 # #注释&#xff0c;超级管理员的命令行提示符 $ #引用变量&#xff0c;普通用户的命令行提示符 ? #匹配任意…

Spring Cloud Alibaba体系使用Nacos作为服务注册发现与配置中心

文章目录 Nacos介绍服务注册发现Nacos Discovery引入Nacos DiscoveryProvider和Consumer示例ProviderConsumer Nacos Discovery Starter其他配置选项 服务注册发现Nacos Config引入Nacos Config快速接入配置自动刷新profile粒度控制自定义namespace配置支持自定义Group支持自定…

UE5.2 LyraDemo源码阅读笔记(二)

UE5.2 LyraDemo源码阅读笔记&#xff08;二&#xff09; 创建了关卡中的体验玩家Actor和7个体验玩法入口之后。 接下来操作关卡中的玩家与玩法入口交互&#xff0c;进入玩法入口&#xff0c;选择进入B_LyraFrontEnd_Experience玩法入口&#xff0c;也就是第3个入口。触发以下请…

vue进阶-elementPlus

Element Plus官网 Element Plus 基于 Vue 3&#xff0c;面向设计师和开发者的组件库。减少开发者关注css&#xff0c;重心关注业务逻辑。 1. 入门 1.1 安装 npm install element-plus --save1.2 快速开始 1、main.js 引入并 use element-plus import { createApp } from …

C#,数值计算——灰色码(Gray Codes)的计算方法与源代码

一个 n位灰色码 序列&#xff0c;就是2的n次方 个 整数&#xff1b; 第一个数字为0&#xff1b; 相邻两个数字的二进制只有一位不一样&#xff1b; 第一个数字和最后一个数字的二进制也只有一位不一样。 using System; namespace Legalsoft.Truffer { /// <summary&…

ARM Exynos4412 硬件中断和GIC管理、PWM控制 6.28

day7 1.中断 硬件中断&#xff1a;直接让外部的硬件产生中断&#xff0c;CPU获取中断源并执行异常处理流程 1.需求&#xff1a;&#xff08;中断的原理一样&#xff0c;但外设是按键&#xff09;按键产生中断&#xff0c;并在中断处理中串口发送消息 2.原理图&#xff1a;U…

Mysql 5.6使用配置文件my.ini来设置长时间连接数据库

对于已经安装了mysql和未安装都是同样的步骤。在C:\Program Files (x86)\MySQL\MySQL Server 5.6下生成一个my.ini文件。然后删除或者修改my-default.ini的名字。 一、my.ini配置文件如下 [mysqld] basedirC:\Program Files (x86)\MySQL\MySQL Server 5.6 datadirC:\Program F…

STM32F407 基本定时器使用

介绍STM32F407基本定时器的配置方法&#xff0c;分别介绍轮询方式、中断方式使用定时器完成定时。 【1】定时器介绍 定时器相关的章节在STM32F4xx参考手册第14、15、16、17章节。 【2】基本定时器配置示例 增加一个Timer.c文件&#xff0c;代码如下 #include "timer.h…

【sql】SQL回顾总结,超级全

SELECT&#xff1a;语句用于从数据库中选取数据 从 "Websites" 表中选取 "name" 和 "country" 列 SELECT name,country FROM Websites 从 "Websites" 表中选取所有列 SELECT * FROM Websites; SELECT DISTINCT&#xff1a;用于返…

Nacos(一):简介 如何安装 服务注册与发现 集群 权重 与Eureka区别

一、简介 1、应用场景 当服务调用越来越多&#xff0c;服务的地址需要管理起来&#xff0c;并实现动态调用而不是硬编码在接口中。此时需要一个注册中心来帮助我们管理服务。 流程如下&#xff1a; 商品微服务注册IP和端口到注册中心订单微服务先从注册中心获取到商品微服务…

45 # 实现文件拷贝功能

下面实现边读边写的文件拷贝功能&#xff0c;这样不会淹没系统的可用内存&#xff0c;合理读写 const fs require("fs"); const path require("path");function copy(source, target, callback) {const SIZE 3;const buffer Buffer.alloc(SIZE);let r…

OPENCV 训练分类器一

第一步&#xff0c;安装OPENCV 见最新openCV-Python安装教程(opencv-python版本4.4.0, Python版本: 3.9)_python安装opencv_这个人不是画家的博客-CSDN博客 第二步&#xff0c;下面是修正过后的Python 将文件夹下面所有的图片转换成灰色小图像&#xff0c;用于存正片用的。…

Python几种字符串格式化方法

Python 字符串格式化方法 文章目录 Python 字符串格式化方法1.python中的字符串格式化--百分号 %2. 字符串格式化-数字精度控制 m.n3. 字符串格式化--快速写法 f"{变量}"4. 案例&#xff1a;股价计算小程序 1.python中的字符串格式化–百分号 % %的主要作用将数据转换…

android switch的使用

一、前言&#xff1a;很多app都有开关这个功能&#xff0c;开关控件的使用跟checkbox好像也差不多。 二、上代码 创建一个activity:SwitchDefaultActivity public class SwitchDefaultActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListene…