学习笔记|矩阵按键控制原理|数值转化为键码|密码锁|STC32G单片机视频开发教程(冲哥)|第十四集:矩阵按键原理及实践

文章目录

  • 1.矩阵按键是什么
  • 2.矩阵按键的控制原理
  • 3.矩阵按键程序的编写
    • 将数值转化为键码
    • 完整代码:
      • demo.c:
      • key.c:
      • key.h:
  • 密码锁(简易版)
    • 需求分析:
  • 总结
  • 课后练习:

1.矩阵按键是什么

这个矩阵按键也是我们这个开发版上最后一个GPIO的一个应用,如果对IO回的输入跟输出还有什么问题的话,一定要回过头去看一下我们之前的程序理清楚思路。
之前的按键电路图:
在这里插入图片描述
1个按键占用一个IO口的。
在按键数量较多时,为了减少I/O口的占用,将按键排列成矩阵排列的形式的按键阵列我们称位矩阵按键。

2.矩阵按键的控制原理

电路图:
在这里插入图片描述

按键识别原理:端口默认为高电平,实时读取到引脚为低电平是表示按下。再次读取到高电平,表示松开。

第一步:现将P0.0-P0.3输出低电平,P0.6-P0.7输出高电平,如果有按键按下,按下的那一列的IO就会变成低电平,就可以判断出哪一列按下了。

第二步:现将P0.0-P0.3输出高电平,P0.6-P0.7输出低电平,如果有按键按下,按下的那一行的IO就会变成低电平,就可以判断出哪一行按下了。

第三步:行列组合一下就可以判断出是哪个按键按下了。

按键按下后导线导通,哪条线上有高电平,就会被拉低为低电平,从而检测出是哪条线路,二次检查,交叉节点就是有按键按下的按键位置。

3.矩阵按键程序的编写

先完成矩阵按键的功能编写。
复制9.TIM多任务为10.矩阵按键,用到P0端口,还是在之前的KEY模块基础上进行修改:
在key.h中定义:#define MateixKEY P0 //矩阵按键的引脚
定义函数MateixKEY_Read:
u8 MateixKEY_Read(void); //矩阵按键读取当前是哪一个按钮按下,返回值是按键序号
在key.c中实现函数MateixKEY_Read:
先增加函数头,并把实现思路复制过来作为编写依据,围绕这三步,编写矩阵按键的读取程序:
MateixKEY = 0XC0; //1100 0000 P0.6-P0.7输出高电平,
在这里插入图片描述

增加延时函数MateixKEY_delay留反应时间:
MateixKEY_delay(); //留反应时间
MateixKEY_delay的实现,并添加函数头:

void MateixKEY_delay(void)
{u8 i;i = 60; //根据之前的毫秒延时函数,可以算出此处延时的时间while(--i);
}

第一步:假设P0.7按下, 则为0100 0000,如果想实现哪路按下哪位变成1,可以采用异或运算。
即:0100 0000 ^1100 0000 = 1000 0000
则有:keystate = MateixKEY^0XC0;

第二步:第二次扫描,高位输出低电平,低位输出高电平:MateixKEY = 0X0f; //0000 1111
保存按键状态,假设P0.0按下, 则为0000 1110^0000 1111 = 0000 0001,这里要采用|=,0000 0001 | 1000 0000 = 1000 0001 = 0x81
在这里插入图片描述
keystate |= (MateixKEY^0X0f);是为了避免把之前的数值覆盖。
第三步:keystate中已经保存了行、列的状态,行列组合一下就可以判断出是哪个按键按下了。
printf(“%02x\r\n”,keystate); //强制变为2位,以16进制显示。
return keystate;
在demo.c中调用:
将10ms扫描按键的代码部分注释掉,只检测MateixKEY_Read,加入该函数,编译,运行。按动按键,串口打印对应的16进制数值。

将数值转化为键码

u8 key_val = 0; //表示按键的键码
这里采用switch关键词,直接有模板插入,编写switch函数:

	switch (keystate) //单选开关函数{case 0x41:	key_val = 1;break;case 0x42:	key_val = 2;break;case 0x44:	key_val = 3;break;case 0x48:	key_val = 4;break;case 0x81:	key_val = 5;break;case 0x82:	key_val = 6;break;case 0x84:	key_val = 7;break;case 0x88:	key_val = 8;break;default:  	key_val = 0;break;}

关闭数码管初始化显示,main函数中新建变量:u8 KEY_NUM = 0; //保存矩阵按键的键码
读取矩阵按键的键码保存在KEY_NUM中,并在数码管最后1位显示:

			KEY_NUM = MateixKEY_Read();SEG7 = KEY_NUM; 	//在数码管最后一位显示

编译下载,按动按键就可以判断是哪个按键按下了。

完整代码:

demo.c:

#include "COMM/stc.h"		//调用头文件
#include "COMM/usb.h"
#include "seg_led.h"
#include "key.h"			//调用头文件
#include "beep.h"
#include "tim0.h"#define MAIN_Fosc 24000000UL	//定义主时钟char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";bit TIM_10MS_Flag;		//10ms标志位void sys_init();	//函数声明
void delay_ms(u16 ms);void Timer0_Isr(void);void main()					//程序开始运行的入口
{u8 KEY_NUM = 0; 		//保存矩阵按键的键码sys_init();				//USB功能+IO口初始化usb_init();				//usb库初始化Timer0_Init();EA = 1;					//CPU开放中断,打开总中断。//数码管初始化,显示0-7
//	SEG0 = 0;
//	SEG1 = 1;
//	SEG2 = 2;
//	SEG3 = 3;
//	SEG4 = 4;
//	SEG5 = 5;
//	SEG6 = 6;
//	SEG7 = 7;LED = 0x0f;	//赋初值,亮一半灭一半,可以写8位的变量.从7开始数到0while(1)		//死循环{
//		if( DeviceState != DEVSTATE_CONFIGURED ) 	//
//			continue;if( bUsbOutReady ){usb_OUT_done();}if(TIM_10MS_Flag == 1)   //将需要延时的代码部分放入{TIM_10MS_Flag = 0;		//TIM_10MS_Flag 变量清空置位
//			KEY_Deal();				//P3上所有端口都需要执行一遍BEEP_RUN();				//蜂鸣运行//			if(KEY_ReadState(KEY1)== KEY_RESS)	//判断KEY1按钮是否为单击
//			{
//				BEEP_ON(2);							//蜂鸣20ms
//				LED0 = 0;
//			}
//			else if(KEY_ReadState(KEY1)== KEY_LONGPRESS) //判断KEY1按钮是否为长按
//			{
//				BEEP_ON(2);							//蜂鸣20ms
//				LED1 = 0;
//			}
//			else if(KEY_ReadState(KEY1)== KEY_RELAX)	//判断KEY1按钮是否为松开
//			{
//				LED = 0XFF;
//			}KEY_NUM = MateixKEY_Read();SEG7 = KEY_NUM; 	//在数码管最后一位显示}}
}void sys_init()		//函数定义
{WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快EAXFR = 1; //扩展寄存器(XFR)访问使能CKCON = 0; //提高访问XRAM速度P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口P3M0 = 0x00;P3M1 = 0x00;P3M0 &= ~0x03;P3M1 |= 0x03;//设置USB使用的时钟源IRC48MCR = 0x80;    //使能内部48M高速IRCwhile (!(IRC48MCR & 0x01));  //等待时钟稳定USBCLK = 0x00;	//使用CDC功能需要使用这两行,HID功能禁用这两行。USBCON = 0x90;
}void delay_ms(u16 ms)	//unsigned int
{u16 i;do{i = MAIN_Fosc/6000;while(--i);}while(--ms);
}void Timer0_Isr(void) interrupt 1 //1ms进来执行一次,无需其他延时,重复赋值
{static timecount = 0;SEG_LED_Show();		//数码管刷新timecount++;		//1ms+1if(timecount>=10)	//如果这个变量大于等于10,说明10ms到达{timecount = 0;TIM_10MS_Flag = 1;	//10ms到了}
}

key.c:

#include "key.h"			//调用头文件
u16 Count[8] = {0,0,0,0,0,0,0,0};	//按键的时间状态变量初始化8位
u8 LastState = 0;					//8位变量,b0=1 则表示key0上一次按下过//========================================================================
// 函数名称:KEY_Deal
// 函数功能:按键状态的获取
// 入口参数:无
// 函数返回:无
// 当前版本: VER1.0
// 修改日期: 2023-1-1
// 当前作者:
// 其他备注:循环读取8个端口的状态,并将按下的时间赋值给Count数组,然后按下的状态赋值给变量LastState
//========================================================================
void KEY_Deal(void) 			//检查所有的按键状态,10ms执行一次
{u8 i = 0;for(i=0;i<8;i++)			//for循环变量 循环8次,i取值为0-7,代表P30-P37的状态查询{if(~KEY & (1<<i) )					//如果持续按下,变量加1{if(Count[i] < 60000)			// Count是u16类型,最大值小于65535,故增加限定条件。Count[i] ++;					//如果持续按下,这个变量加1}else					//如果按键松开,变量清0{if(Count[i] > 0 )	//如果这个按键是按下过的,{LastState |= (1<<i);	//这个变量相应的标志位置1,单独写对应位}else{LastState &= ~(1<<i);	//仅操作这个变量相应的标志位清0}Count[i] = 0;					//如果松开,计数变量清0}}}
//========================================================================
// 函数名称:KEY_ReadState
// 函数功能:读取指定的按钮的状态
// 入口参数: @keynum; 按钮的端口号,例如P32的端口号是2,
// 函数返回:见KEY的返回值的各种状态,看其他备注
// 当前版本: VER1.0
// 修改日期: 2023-1-1
// 当前作者:
// 其他备注: 函数返回值如下:
状态	功能
//#define KEY_NOPRESS 0 	//按键未按下	0
//#define KEY_FLCKER 1 		//消抖	1
//#define KEY_RESS 2		//单击	2
//#define KEY_PRESSOVER 3 	//单击结束	3
//#define KEY_LONGPRESS 4 	//长按3s	4
//#define KEY_LONGOVER 5 	//长按结束	5
//#define KEY_RELAX 6 		//按键松开	6
//========================================================================u8  KEY_ReadState(u8 keynum) 	//读取指定按键的状态,10ms执行1次
{if(Count[keynum] > 0)			//判断按键是按下的{if(Count[keynum] < 3)		//按下小于30ms,返回消抖状态{return KEY_FLCKER;}else if(Count[keynum] == 3)	//按正好等于30ms,返回单击状态{return KEY_RESS;}else if(Count[keynum] < 300 ) //按下小于3000ms,返回单击结束{return KEY_PRESSOVER;}else if(Count[keynum] == 300 ) //按下正好等于3000ms,返回长按{return KEY_LONGPRESS;}else					//长按结束{return KEY_LONGOVER;}}else						//按键已经松开了,返回KEY_RELAX状态{if(LastState &(1<<keynum))			//按键之前按下过,要判断上1s是不是高电平,如果上1s是低电平,说明是按键按下//例如,要判断P32,P30,31,32,左移2位,//按键已经松开了{return KEY_RELAX;}else			//按键之前没有按下过,返回未按下{return KEY_NOPRESS;}}
}
//========================================================================
// 函数名称:MateixKEY_delay
// 函数功能:矩阵按键读取专用延时函数
// 入口参数:无
// 函数返回:无
// 当前版本: VER1.0
// 修改日期: 2023
// 当前作者:
// 其他备注:
//========================================================================
void MateixKEY_delay(void)
{u8 i;i = 60; //根据之前的ms延时的函数,可以算出此处延时的时间while(--i);
}
//========================================================================
// 函数名称:MateixKEY_Read
// 函数功能:矩阵按键读取当前是哪一个按钮按下
// 入口参数:无
// 函数返回:0表示没有按键按下,1-8表示当前是第几个按键按下
// 当前版本: VER1.0
// 修改日期: 2023-1-1
// 当前作者:
// 其他备注:
//========================================================================
u8 MateixKEY_Read(void) 	//矩阵按键读取当前是哪一个按钮按下,返回值是按键序号
{u8 keystate;				//表示当前的按钮状态值u8 key_val = 0;				//表示按键的键码
//	第一步:现将P0.0-P0.3输出低电平,P0.6-P0.7输出高电平,如果有按键按下,按下的那一列的IO就会变成低电平,就可以判断出哪一列按下了。MateixKEY = 0XC0;			//1100 0000  P0.6-P0.7输出高电平,MateixKEY_delay();			//留反应时间keystate = (MateixKEY^0XC0);	//保存按键状态,假设P0.7按下, 则为0100 0000,如果想实现变成哪路按下变成1,用异或//	第二步:现将P0.0-P0.3输出高电平,P0.6-P0.7输出低电平,如果有按键按下,按下的那一行的IO就会变成低电平,就可以判断出哪一行按下了。MateixKEY = 0X0f;			//0000 1111  高位输出低电平,低位输出高电平MateixKEY_delay();			//留反应时间keystate |= (MateixKEY^0X0f);	//保存按键状态,假设P0.0按下, 则为0000 1110^0000 1111 = 0000 0001,这里要采用|=,为了避免把之前的数值覆盖。//	第三步:行列组合一下就可以判断出是哪个按键按下了。
//	printf("%02x\r\n",keystate); //强制变为2位,以16进制显示。switch (keystate) //单选开关函数{case 0x41:	key_val = 1;break;case 0x42:	key_val = 2;break;case 0x44:	key_val = 3;break;case 0x48:	key_val = 4;break;case 0x81:	key_val = 5;break;case 0x82:	key_val = 6;break;case 0x84:	key_val = 7;break;case 0x88:	key_val = 8;break;default:  	key_val = 0;break;}return key_val;}

key.h:

#ifndef __KEY_H
#define __KEY_H#include "COMM/stc.h"			//调用头文件
#include "COMM/usb.h"//------------------------引脚定义------------------------//
#define KEY P3 			//定义一个按键 引脚选择P32-P36#define KEY1 2			//按键1
#define KEY2 3			//按键2
#define KEY3 4			//按键3
#define KEY4 5			//按键4#define MateixKEY P0    //矩阵按键的引脚//------------------------变量声明------------------------//
//状态	功能
#define KEY_NOPRESS 0 		//按键未按下	0
#define KEY_FLCKER 1 		//消抖	1
#define KEY_RESS 2			//单击	2
#define KEY_PRESSOVER 3 	//单击结束	3
#define KEY_LONGPRESS 4 	//长按3s	4
#define KEY_LONGOVER 5 		//长按结束	5
#define KEY_RELAX 6 		//按键松开	6//------------------------函数声明-----------------------//
void KEY_Deal(void);			//检查所有的按键状态
u8  KEY_ReadState(u8 keynum);	//读取指定按键的状态u8 MateixKEY_Read(void);		//矩阵按键读取当前是哪一个按钮按下,返回值是按键序号#endif

密码锁(简易版)

在这里插入图片描述

由于KEY_NUM = MateixKEY_Read();执行后,会持续输出1,需要修改,3s内只输出1次即可,让它符合今天的主题。
先定义一个静态变量,这是一个很常见的用法,static u8 keystate_Last; //表示当前的按钮上一次的状态值
增加判断条件:

	if(keystate_Last != keystate)	//如果本次获取到的按键状态值和之前的不一样{keystate_Last = keystate;   //把本次的按键状态值写入进去switch (keystate) //单选开关函数{case 0x41:	key_val = 1;break;case 0x42:	key_val = 2;break;case 0x44:	key_val = 3;break;case 0x48:	key_val = 4;break;case 0x81:	key_val = 5;break;case 0x82:	key_val = 6;break;case 0x84:	key_val = 7;break;case 0x88:	key_val = 8;break;default:  	key_val = 0;break;}printf("%d\r\n",(int)key_val);  //强制转化为整形变量}

需求分析:

1.通过LED0模拟门锁状态,LED点亮表示门锁打开,熄灭表示门锁锁上;
增加横线显示值,SEG_Tab[22]=
默认显示横线:u8 Show_Tab[8] = {21,21,21,21,21,21,21,21};
新增变量:u8 KEY_Str = 0; //表示当前输入了几个密码
2.增加8位数码管,可以动态显示8位的密码,无密码时显示 “- - - - - - - -”;
3.通过矩阵按键可以输入1-8的数字表示密码,并依次显示在数码管上;
4.每输入一个数字,蜂鸣器响20ms表示有数字按下;
5.密码正确打开LED0,密码错误蜂鸣响2秒;
根据条件,修改demo.c中的main函数代码如下:

void main()					//程序开始运行的入口
{u8 KEY_NUM = 0; 		//保存矩阵按键的键码u8 KEY_Str = 0; 		//表示当前输入了几个密码位sys_init();				//USB功能+IO口初始化usb_init();				//usb库初始化Timer0_Init();EA = 1;					//CPU开放中断,打开总中断。//数码管初始化,显示0-7
//	SEG0 = 0;
//	SEG1 = 1;
//	SEG2 = 2;
//	SEG3 = 3;
//	SEG4 = 4;
//	SEG5 = 5;
//	SEG6 = 6;
//	SEG7 = 7;//LED = 0x0f;	//赋初值,亮一半灭一半,可以写8位的变量.从7开始数到0LED = 0xff;	//赋初值,密码锁应用初始状态熄灭所有LEDwhile(1)		//死循环{
//		if( DeviceState != DEVSTATE_CONFIGURED ) 	//
//			continue;if( bUsbOutReady ){usb_OUT_done();}if(TIM_10MS_Flag == 1)   //将需要延时的代码部分放入{TIM_10MS_Flag = 0;		//TIM_10MS_Flag 变量清空置位
//			KEY_Deal();				//P3上所有端口都需要执行一遍BEEP_RUN();				//蜂鸣运行//			if(KEY_ReadState(KEY1)== KEY_RESS)	//判断KEY1按钮是否为单击
//			{
//				BEEP_ON(2);							//蜂鸣20ms
//				LED0 = 0;
//			}
//			else if(KEY_ReadState(KEY1)== KEY_LONGPRESS) //判断KEY1按钮是否为长按
//			{
//				BEEP_ON(2);							//蜂鸣20ms
//				LED1 = 0;
//			}
//			else if(KEY_ReadState(KEY1)== KEY_RELAX)	//判断KEY1按钮是否为松开
//			{
//				LED = 0XFF;
//			}KEY_NUM = MateixKEY_Read();		//当前矩阵按键的键值//SEG7 = KEY_NUM; 	//在数码管最后一位显示if( KEY_NUM > 0)				//如果有按键按下{KEY_NUM = 0;						//键值先清空,清空按键BEEP_ON(2);							//蜂鸣20msShow_Tab[KEY_Str] = KEY_NUM; 		//表示当前输入了几个密码 = KEY_NUM;		//将当前的按键状态保存到数组KEY_Str++;							//输入的密码位数+1if(KEY_Str ==8)		//如果密码已经等于8位,{if((Show_Tab[0]==1)&&(Show_Tab[1]==1)&&(Show_Tab[2]==1)&&(Show_Tab[3]==1)&&(Show_Tab[4]==1)&&(Show_Tab[5]==1)&&(Show_Tab[6]==1)&&(Show_Tab[7]==1)){LED0 = 0;			//如果密码正确,LED0点亮}else{BEEP_ON(200);	//密码错误,蜂鸣2s。单位是10ms,2000ms=2s}}}}}
}

编译下载,发现按键后均显示0:KEY_NUM = 0;位置有误,应该放在调用以后再置0.
重新测试,8位输入后不能自动清空,应该添加代码,到达长度后回到初始值显示横杠:SEG0 = SEG1 = SEG2 = SEG3 = SEG4 = SEG5 = SEG6 = SEG7 = 21;
重新测试,输入错误后,复位,再按键输入,显示有问题:KEY_Str ==8后忘记归0了。
经过修改,功能已正常实现。
完整代码请参考:《STC单片机原理-教学视频配套附件-20230731.zip

总结

1.了解矩阵按键的工作原理和代码编写的过程

课后练习:

给今天的门锁增加如下功能:
1.LED0(门锁)打开后,5秒后自动关闭;
2.增加门内的手动开门按钮,按下按钮门锁打开;
3.10秒内没有输入密码自动数码管熄灭省电;有按键按下时再显示。
4.用for去改写一下密码判断的地方。

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

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

相关文章

Zookeeper 启动失败【Cannot open channel to 3 at election address...】

文章目录 完整报错信息解决方法1.检查文件夹权限2.未监听所有IP3.IP映射名称与 ID 不对应 完整报错信息 Cannot open channel to 3 at election address hadoop121/192.168.10.121:3888 java.net.ConnectException 解决方法 1.检查文件夹权限 检查当前用户是否拥有 Zookeep…

string的使用和模拟实现

&#x1f493;博主个人主页:不是笨小孩&#x1f440; ⏩专栏分类:数据结构与算法&#x1f440; C&#x1f440; 刷题专栏&#x1f440; C语言&#x1f440; &#x1f69a;代码仓库:笨小孩的代码库&#x1f440; ⏩社区&#xff1a;不是笨小孩&#x1f440; &#x1f339;欢迎大…

Pytorch从零开始实战02

Pytorch从零开始实战——彩色图像识别 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——彩色图像识别环境准备数据集模型选择模型训练数据可视化 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#xff0c;Pytorch2.0.1cu118…

Day 01 web前端基础知识

首先我们要了解什么事前端&#xff1f; 先简单用文字介绍一下&#xff1a; 一、入门知识 Web前端是指网站或应用程序的用户界面部分。它包括HTML、CSS、JavaScript等语言和技术&#xff0c;用于创建用户可浏览和交互的网页。Web前端的特点在于其交互性和动态性&#xff0c;可…

非常详细的trunk-based分支管理流程配置及使用

非常详细的trunk-based分支管理流程配置及使用。 目前业界主流的版本管理流程是Gitflow 和 trunk-based。 Gitflow流行的比较早。但是目前的流行度要低于 trunk-based模式工作流。trunk-based模式被誉为是现代化持续集成的最佳实践。 他俩的核心区别是,Gitflow是一个更严格…

如何优化你的Vue.js应用以获得最佳性能

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

vue3+ts+uniapp小程序封装获取授权hook函数

vue3tsuniapp小程序封装获取授权hook函数 小程序授权的时候&#xff0c;如果点击拒绝授权&#xff0c;然后就再也不会出现授权了&#xff0c;除非用户手动去右上角…设置打开 通过uni官方api自己封装一个全局的提示: uni.getSetting :http://uniapp.dcloud.io/api/other/settin…

前端综合练手小项目

导读 本篇文章主要以小项目的方式展开&#xff0c;其中给出的代码中均包含详细地注释&#xff0c;大家可以参照理解。下面4个小项目中均包含有 HTML、CSS、JavaScript 等相关知识&#xff0c;可以拿来练手&#xff0c;系统提升一下自己的前端开发能力。 废话少说&#xff0c;…

《Envoy 代理:云原生时代的流量管理》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f6e0;️ 全栈技术 Full Stack: &#x1f4da…

SCRUM产品负责人(CSPO)认证培训课程

课程简介 Scrum是目前运用最为广泛的敏捷开发方法&#xff0c;是一个轻量级的项目管理和产品研发管理框架。产品负责人是Scrum的三个角色之一&#xff0c;产品负责人在Scrum产品开发当中扮演舵手的角色&#xff0c;他决定产品的愿景、路线图以及投资回报&#xff0c;他需要回答…

微服务如何改变软件开发:实战经验与最佳实践分享

文章目录 什么是微服务&#xff1f;微服务实战经验1. 定义明确的服务边界2. 使用API网关3. 自动化部署和持续集成4. 监控和日志记录 微服务最佳实践1. 文档和通信2. 弹性设计3. 安全性4. 版本控制5. 监控和警报 微服务的未来 &#x1f389;欢迎来到架构设计专栏~微服务如何改变…

C++版本的OpenCV实现二维图像的卷积定理(通过傅里叶变换实现二维图像的卷积过程,附代码!!)

C版本的OpenCV库实现二维图像的卷积定理过程详解 前言一、卷积定理简单介绍二、不同卷积过程对应的傅里叶变换过程1、“Same”卷积2、“Full”卷积3、“Valid”卷积 三、基于OpenCV库实现的二维图像卷积定理四、基于FFTW库实现的二维图像卷积定理五、总结与讨论 前言 工作中用…

计算机视觉--距离变换算法的实战应用

前言&#xff1a; Hello大家好&#xff0c;我是Dream。 计算机视觉CV是人工智能一个非常重要的领域。 在本次的距离变换任务中&#xff0c;我们将使用D4距离度量方法来对图像进行处理。通过这次实验&#xff0c;我们可以更好地理解距离度量在计算机视觉中的应用。希望大家对计算…

QML android 采集手机传感器数据 并通过udp 发送

利用 qt 开发 安卓 app &#xff0c;采集手机传感器数据 并通过udp 发送 #ifndef UDPLINK_H #define UDPLINK_H#include <QObject> #include <QUdpSocket> #include <QHostAddress>class UdpLink : public QObject {Q_OBJECT public:explicit UdpLink(QObjec…

C#,数值计算——Hashfn1的计算方法与源程序

1 文本格式 using System; using System.Collections; using System.Collections.Generic; namespace Legalsoft.Truffer { public class Hashfn1 { private Ranhash hasher { get; set; } new Ranhash(); private int n { get; set; } public Hash…

【C++11保姆级教程】列表初始化(Literal types)和委派构造函数(delegating))

文章目录 前言一、列表初始化 (List Initialization)1.1数组初始化1.2结构体初始化1.3容器初始化1.4列表初始化的优势 二、委派构造函数 (Delegating Constructors)2.1委派构造函数是什么&#xff1f;2.2委派构造函数示例代码2.3调用顺序2.3委派构造函数优势 总结 前言 C11引入…

SpringCLoud——Nacos配置中心

Nacos实现配置管理 统一配置管理 配置更新热更新 统一配置的创建是在UI界面中完成的&#xff1a; 首先我们点击【配置管理】然后点击【配置列表】&#xff1a; 然后我们就看到了配置管理界面&#xff0c;但是此时这里是空的&#xff0c;我们可以创建一些配置文件&#xff1a…

Springboot 实践(17)spring boot整合Nacos配置中心

前文我们讲解了Nacos服务端的下载安装&#xff0c;本文我们降价spring boot整合nacos&#xff0c;实现Nacos服务器配置参数的访问。 一、启动Nacos服务&#xff0c;创建三个配置文件&#xff0c;如下所示 Springboot-Nacos-Client-dev.yaml文件配置参数 Springboot-Nacos-Clie…

微信小程序自动化发布

参考:https://developers.weixin.qq.com/miniprogram/dev/devtools/ci.html 参考:https://www.npmjs.com/package/miniprogram-ci npm install miniprogram-ci -S上传文件 xx.js const isNodeJs typeof process ! undefined && process.release ! null &&…

智能文本纠错API的应用与工作原理解析

引言 在数字时代&#xff0c;文本撰写和传播变得日益重要&#xff0c;无论是在学校里写论文、在职场中发送邮件&#xff0c;还是在社交媒体上发表观点。然而&#xff0c;文字错误、标点符号错误、语法问题和不当的表达常常会削弱文本的质量&#xff0c;降低信息传达的效果。为…