当前位置: 首页 > news >正文

嵌入式计算器模块实现

嵌入式计算器模块规划

计算器混合算法解析
上面我们的算法理论已经完善, 我们只用给一个混合运算式, 计算器就可以帮助我们计算出结果.

但是存在一个痛点, 每次计算算式,都要重新编译程序, 所以我们想到了, 利用单片机, 读取用户输入的按键, 组成算式, 输入给机器, 这样我们就可以利用上面的算法, 再次计算出结果了.

大致流程如下:

image-20240624100125749

所以, 我们第一步做的,就是stm32利用矩阵按键识别键值

第二步,就是单片机把读取到的键值, 组合成算式

第三步,就是把算式传给算法,计算出结果

第四步, 就是把结果清零

拓展:第五步,可以把结果转换成语音播报

第一步: 矩阵按键,读取键值

(1)读取原理

首先我们要了解矩阵按键, 是干什么的, 顾名思义,矩阵按键,就是几行几列,依次排开的,按钮, 我们如果知道行,知道列,就可以锁定那个按键,所以我们只需要让单片机知道,我们按下的是哪一行,哪一列,那么单片机通过提前布局好的按键键值,就可以知道我们按下的是哪个按键了.

image-20240624101158298

(2)按键布局

如下图, 即为我们矩阵按键的键盘布局:

第一行 ( ) / *

第二行 1 2 3 +

第三行 4 5 6 -

第四行 7 8 9 Esc

第五行 ← 0 → =

image-20240624102450597

(3)按键原理图

矩阵按键原理图:

image-20240624103255572

(4)单片机io口识别原理

我们锁定行列, 此矩阵按键有五行,四列, 我们就先识别按下哪一列吧,然后后面再锁定行,这样就可以得到坐标了.

单说, 按下按键, 怎么io口怎么识别出按下按键呢?

举一个例子, 单片机io口,相当于装满水的水杯, 单片机会检测io口水杯, 是满的,还是空的. 用户按下按键,就相当于, 把水倒掉,那么我们就可以让单片机检测到按键.

image-20240624122114389

所以, 单片机检测io口,端口被称作输入口,顾名思义就是读取io口状态, 并把io口状态,反馈给单片机,那么水倒哪里了呢? 我们按下按键, 水就倒到了地下. 所以我们按键另一端按键接地是持续输出低电平的输出口.

<1>识别列

我们把上述的步骤, 复制四份, 我们就可以判断按下是哪一列了

image-20240624122801579

此时,四个列检测io口, 链接四个按键,按键另一端连接的是地, 这个地可以用io口输出低电平代替,方便后续矩阵键盘拓展.

image-20240624131512384

但是我们有四列, 五行, 所以, 每列都有,五个按钮, 我们紧接着, 再把他们排列起来.

image-20240624131141800

<2>识别行

此时, 我们通过判断 PA1,PA2,PA3,PA4那个io口变化了,就可以识别到是哪列按键按下了,

但是我们是矩阵按键,还要进行行的识别.

其实,识别方法同理,我们只需要把, io口类型进行反转,把列控制端口全反转成输出低电平, 现在检测io口状态的变成每行的端口,当按下第一行按钮时候,对应的端口就会变成低电平, 单片机检测到,就可以识别到行 如下图所示

image-20240624132339632

进行拓展后,就变成了矩阵按键,

image-20240624132534304

<3> 识别原理总结

我们识别原理就是,先赋予列检测io口,高电平,设置其端口类型为输入口,读取按键状态,按键另一端,是输出口,持续输出低电平.

当我们按下按键的时候, 输入口io口的高电平会通过按键,送到低电平,此时单片机检测到低电平, 就判定是哪一列的按键按下了.

此时列已经锁定了, 下面开始锁定行,此时按下仍然处于按下状态.

我们此时设置控制行的io口,为输入口,检测按键状态, 控制列的io口,设置为输出低电平,那么此时按键是按下状态, 对应的行io口,电平就会从高电平->低电平, 那么单片机就会检测到io口状态变化, 我们就可以锁定对应的行.

行和列已经锁定,那么我们通过计算就可以得到我们按下的是矩阵按键的哪一个按键了.

<4>代码实现

我们使用线性反转法的核心思想,就是锁定行和列的坐标, 通过反转io口类型,检测io口状态,根据按键按下的状态,进而锁定坐标.

为了更快的进入列的选择,我们把四列io口,全部设置成中断形式,对应的行io口,全部设置为推挽输出低电平, 四列io口的中断触发方式,设置成下降沿触发.

①锁定列

这样我们就可以很快的进行, 锁定列了;

配置 PA1 ,PA2, PA3, PA4 为下降沿触发中断

1.中断初始化
void Exti_key_config(void)
{//定义官方文档结构体EXTI_InitTypeDef   EXTI_InitStructure;GPIO_InitTypeDef   GPIO_InitStructure;NVIC_InitTypeDef   NVIC_InitStructure;//初始化//使能时钟 PA  AFIORCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);	//io口初始化, 设置//使能内部上拉GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	GPIO_Init(GPIOA, &GPIO_InitStructure);/* Connect EXTI1 line to PA1 pin */GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);/* Connect EXTI2 line to PA2 pin */GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource2);/* Connect EXTI3 line to PA3 pin */GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource3);/* Connect EXTI4 line to PA4 pin */GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource4);//中断端口的设置(外部中断线 1,2,3和4,  端口模式, 什么触发: 下降沿 , 开启等)/* Configure EXTI0 line */EXTI_InitStructure.EXTI_Line = EXTI_Line1 | EXTI_Line2 | EXTI_Line3 | EXTI_Line4;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);//下面配置中断优先级/* Configure EXTI1 interrupt */NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);/* Configure EXTI2 interrupt */NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;NVIC_Init(&NVIC_InitStructure);/* Configure EXTI3 interrupt */NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;NVIC_Init(&NVIC_InitStructure);/* Configure EXTI4 interrupt */NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;NVIC_Init(&NVIC_InitStructure);
}	
2.触发中断

char key_number; // 1–4 (代表一到四列)

_Bool key_button_down; //代表按键按下

void EXTI1_IRQHandler(void)
{if (EXTI_GetITStatus(EXTI_Line1) != RESET){delay(0x20000);	//中断服务函数当中 , 是不能用大延时的,快进		快出/* Your code goes here */key_number = 1;key_button_down = 1;//中断服务函数当中 , 是不能用大延时的,快进		快出delay(0x20000);	EXTI_ClearITPendingBit(EXTI_Line1);}
}void EXTI2_IRQHandler(void)
{if (EXTI_GetITStatus(EXTI_Line2) != RESET){//中断服务函数当中 是不能用大延时的,快进		快出delay(0x20000);	/* Your code goes here */key_number = 2;key_button_down = 1;//中断服务函数当中 , 是不能用大延时的,快进快出delay(0x20000);	EXTI_ClearITPendingBit(EXTI_Line2);}
}void EXTI3_IRQHandler(void)
{if (EXTI_GetITStatus(EXTI_Line3) != RESET){//中断服务函数当中 , 是不能用大延时的,快进快出delay(0x20000);	/* Your code goes here */key_number = 3;key_button_down = 1;//中断服务函数当中 , 是不能用大延时的,快进快出delay(0x20000);	EXTI_ClearITPendingBit(EXTI_Line3);}
}void EXTI4_IRQHandler(void)
{if (EXTI_GetITStatus(EXTI_Line4) != RESET){//中断服务函数当中 , 是不能用大延时的,快进快出delay(0x20000);	/* Your code goes here */key_number = 4;key_button_down = 1;//中断服务函数当中 , 是不能用大延时的,快进快出delay(0x20000);	EXTI_ClearITPendingBit(EXTI_Line4);}
}
3.锁定列数值
extern char key_number;
extern char chose_column;//选中的列
void find_column(void)
{if(key_number == 1){chose_column = 1;}elseif(key_number == 2){chose_column = 2;}		elseif(key_number == 3){chose_column = 3;}elseif(key_number == 4){chose_column = 4;}	else{}		
}
②锁定行

此时列已经锁定, 我们把列io口,全变成输出低电平, 控制行的io口,变成输入口,高电平, 此时单片机检测io的变化,就可以检测到哪行按下了.

1.端口类型转换
/* 切换为推挽输出模式 GPIO_Mode_Out_PP*/
//下面进行判断是哪个行(对调模式)
//GPIOA, GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4
void exchange_Mode(void)
{GPIO_InitTypeDef   GPIO_InitStructure;//初始化//使能时钟 PA  AFIORCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);	//io口初始化, 设置//使能内部上拉GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	GPIO_Init(GPIOA, &GPIO_InitStructure);	/* 切换为下拉输入输入模式  GPIO_Mode_IPD *///GPIOA, GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7//GPIOB, GPIO_Pin_0 | GPIO_Pin_10	//io口初始化, 设置//使能内部上拉GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;	GPIO_Init(GPIOA, &GPIO_InitStructure);	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;	GPIO_Init(GPIOB, &GPIO_InitStructure);		}	

2.锁定行

电平反转, 类型反转,当检测到行io口电平变成低电平,就可以锁定行了

extern char chose_line;//选中的行
void find_line(void)	//行
{GPIO_SetBits(GPIOA, GPIO_Pin_1);GPIO_SetBits(GPIOA, GPIO_Pin_2);GPIO_SetBits(GPIOA, GPIO_Pin_3);GPIO_SetBits(GPIOA, GPIO_Pin_4);GPIO_ResetBits(GPIOA, GPIO_Pin_5);GPIO_ResetBits(GPIOA, GPIO_Pin_6);GPIO_ResetBits(GPIOA, GPIO_Pin_7);GPIO_ResetBits(GPIOB, GPIO_Pin_0);GPIO_ResetBits(GPIOB, GPIO_Pin_10);delay(0x20000);if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5) == SET){delay(0x20000);while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5) == SET);chose_line = 1;}elseif(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6) == SET){delay(0x20000);while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6) == SET);chose_line = 2;}elseif(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7) == SET){delay(0x20000);while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7) == SET);chose_line = 3;}elseif(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == SET){delay(0x20000);while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == SET);chose_line = 4;}elseif(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10) == SET){delay(0x20000);while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10) == SET);chose_line = 5;}	
}
③ 计算键值

//根据所在行列 ,计算出特定符号

char compute_sign(char lines,char columns)
{//算出特定需要char counter;char sign;counter = (lines-1)*4 + columns;
/* 行  1	2	3	4 (列)
1   (	)	/	*
2	1	2	3	+
3	4	5	6	-
4	7	8	9	Esc
5	<-	0	->	=*/	switch(counter){case 1:	sign = '(';break;case 2:sign = ')';break;case 3:sign = '/';break;case 4:sign = '*';break;case 5:sign = '1';break;case 6:sign = '2';break;case 7:sign = '3';break;case 8:sign = '+';break;case 9:sign = '4';break;case 10:sign = '5';break;case 11:sign = '6';break;case 12:sign = '-';break;		case 13:sign = '7';break;		case 14:sign = '8';break;		case 15:sign = '9';break;		case 16:sign = 'x';break;		case 17:sign = '<';break;		case 18:sign = '0';break;		case 19:sign = '>';break;		case 20:sign = '=';break;		default:sign = 0;break;		}return sign;
}
④ main函数调用展示键值
<1>软件初始化
void Software_Init(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//中断控制器分组设置OLED_Init();Delay_Init();
//	uart_init();//波特率115200uart1_init(115200);//线性反转第一波(等待按键按下)button_key_config();Exti_key_config();init_collect_data();//按键收集中缀式初始化
}
<2>按键展示在OLED上
//按键展示
void show_keyboard(void)
{int counter;//展示选中的数字OLED_ShowChar(80, 0, show_sign, OLED_8X16);if(collect_space.counter == collect_space.insert_locate && (show_sign != '<') && (show_sign != '>')){OLED_ClearArea(0, 40, 128, 16);//for循环输出字符for(counter = 0; counter < collect_space.counter ;counter++){OLED_ShowChar(5+(counter)*14, 40, collect_space.data_symbol[counter], OLED_8X16);}		}elseif(collect_space.counter != collect_space.insert_locate){OLED_ClearArea(0, 40, 128, 16);//for循环输出字符for(counter = 0; counter < collect_space.counter ;counter++){OLED_ShowChar(5+(counter)*14, 40, 			collect_space.data_symbol[counter], OLED_8X16);}}OLED_Update();	
}
<3>循环检测按键按下
	while(1){//按键按下if(key_button_down == 1){//识别按键scan_keyboard();	//注意,此时按键应该抬起//拾取按键到中缀式collect_Key_information(show_sign);//按键展示show_keyboard();//擦屁股, 恢复读取模式 线性反转第一波(等待按键按下)button_key_config();Exti_key_config();	key_button_down = 0;}}

第二步: 单片机键值, 组合成算式字符串

(1)收集框架

我们收集的算式, 包括,加减乘除,‘0’-‘9’,还有左右括号,至于等于号,就不需要了,因为按完算式后,按下等于号, 相当于计算结果,等计算出结果后, 我们再按下等于,相当于清零,所以我们要做一下区分.

image-20240624170617115

(2)中缀式数据结构

所以, 我们定义一个中缀算式的数据结构

#define data_MaxSize   100
//中缀式处理结构体
struct CollectSpace
{char data_symbol[data_MaxSize];	//存储中缀式符号的数组int counter;					//最后一个字符的数组位置int insert_locate;					//当前需要插入的位置_Bool Start_Mode;				//是否开始计算_Bool clear;					//是否清零		
};	

(3)读取开始运算标志,计算结果

如果第一次按下等于号 ,就开始计算

if(collect_space.Start_Mode == 1)	//判断中缀式处理结构,是否进入计算模式
{//中缀式结构数组 --> 后缀式
Conversion_expression(collect_space.data_symbol,Suffix_expression);//转换后缀式//计算数值Calculate_result = Calculate_value(Suffix_expression);OLED_Clear();//结果OLED_Printf(0,0, OLED_8X16,"%.2f", Calculate_result);//总算式OLED_ShowString(0,20, collect_space.data_symbol,OLED_8X16);OLED_Update();collect_space.Start_Mode = 0;	//停止计算
}

(4)收集按键信息

①分按键类型,进入不同模式

收集的信息, 分为数字,运算符和等于号,

我们分别根据类型, 进入不同的模式进行处理:

image-20240624180928671

判断对应类型,进入不同处理模式

void collect_Key_information(char collect_key)
{//获得按键//查询功能if(collect_key >= '0' && collect_key <= '9'){char_input.character_Mode = 1;	//数字模式}elseif(collect_key == '+' || collect_key == '-' || collect_key == '*' || collect_key == '/' || collect_key == '(' || collect_key == ')'	)		{char_input.character_Mode = 2;	//运算符模式}elseif(collect_key == '<'||collect_key == '>'){char_input.character_Mode = 3;	//移动编辑模式}elseif(collect_key == 'x'){char_input.character_Mode = 4;	//编辑删除模式}elseif(collect_key == '='){char_input.character_Mode = 5;	//运算结果模式}deal_mode(collect_key);
}
② 根据不同模式,进入不同的处理
<1>数字模式

数字可以插入第一个位置和 第字符个数+1的位置

处理方法: 先腾出要插入的位置,然后把对应位置插入

if(char_input.character_Mode == 1)
{//合法性判断(可以插入第一个位置, 和 第(字符个数 + 1)的位置)直接使用物理序号if(collect_space.insert_locate >= 0 && collect_space.insert_locate <= collect_space.counter){for(j = collect_space.counter; j > collect_space.insert_locate; j--){collect_space.data_symbol[j] = collect_space.data_symbol[j-1];}collect_space.data_symbol[collect_space.insert_locate] = deal_key;//合法后 , 字符数量加1collect_space.counter++;//默认下次光标插入位置++collect_space.insert_locate++;}
}
<2>运算符模式

(可以插入第一个位置, 和 第(字符个数 + 1)的位置)直接使用物理序号

if(char_input.character_Mode == 2)	//加入合法性判断
{//合法性判断(可以插入第一个位置, 和 第(字符个数 + 1)的位置)直接使用物理序号if(collect_space.insert_locate >= 0 && collect_space.insert_locate <= collect_space.counter){for(j = collect_space.counter; j > collect_space.insert_locate; j--){collect_space.data_symbol[j] = collect_space.data_symbol[j-1];}collect_space.data_symbol[collect_space.insert_locate] = deal_key;//合法后 , 字符数量加1collect_space.counter++;//默认下次光标插入位置++collect_space.insert_locate++;}}
<3>移动编辑模式

这里, 我们只是切换了光标序号,所以我们下次插入字符的时候,就不能直接覆盖了,而是腾出位置,然后插入了

if(char_input.character_Mode == 3)	//移动编辑插入字符模式
{//光标跟踪if(deal_key == '<'){if(collect_space.insert_locate > 0){collect_space.insert_locate--;		}}else if(deal_key == '>'){if(collect_space.insert_locate < collect_space.counter){collect_space.insert_locate++;}}
}
<4>删除字符模式

我们删除字符前, 要做删除位置合法性判断(删除位置 = 插入位置的前一个字符)

//合法性判断(可以删除的位置 0 ~ 数组的collect_space.counter-1)

if(char_input.character_Mode == 4)	//删除字符模式
{//删除位置合法性判断(删除位置 = 插入位置的前一个字符)deletesapce.now_delete = collect_space.insert_locate-1;//合法性判断(可以删除的位置 0 ~ 数组的collect_space.counter-1)if(deletesapce.now_delete >= 0 && deletesapce.now_delete < collect_space.counter){//删除光标处的前一个字符 === //把光标后的字符移动到此为止(覆盖)//临界 data[collect_space.counter-2 ] = data[collect_space.counter-1 ];//==> j = collect_space.counter-2 =得出范围=> j < collect_space.counter-1for(j = deletesapce.now_delete; j < collect_space.counter-1; j++){collect_space.data_symbol[j] = collect_space.data_symbol[j+1];}//数组个数减去1collect_space.counter--;//光标位序减去1collect_space.insert_locate--;}
}
<5>运算模式

当我们第一次按下按键,我们就进入运算模式, 并且加一个自锁变量,下次等于就是清零变量,collect_space.clear ^= 1;

if(char_input.character_Mode == 5)	//运算模式
{//开启计算结果,并将计算数值装入中缀式if(collect_space.clear == 0){collect_space.data_symbol[collect_space.counter] = '\0';collect_space.Start_Mode = 1;	//中缀式结构 进入下次计算的待计算模式(擦屁股)//分情况collect_space.counter = 0;collect_space.insert_locate = 0;//初始的时候, 是数组, 0collect_space.clear ^= 1;}elseif(collect_space.clear == 1)	//将计算清零(归零):擦屁股{//清空屏幕OLED_Clear();OLED_Update();collect_space.clear ^= 1;}}

第三步,计算结果

我们通过观看博客原理,即可

https://blog.csdn.net/qq_57484399/article/details/138288148

第四步,屏幕显示

我们可以直接调用OLED显示函数,显示结果

但是如果我们需要使用语音,读出结果的话,就要对每一位进行分个进行读取,然后结合个十百千万以及汉语的语言习惯了,我会单独出一个博客,讲解,如果把自然数小数进行语音播报.

第五步, 清零

再次按下等于号,即可清零

相关文章:

嵌入式计算器模块实现

嵌入式计算器模块规划 计算器混合算法解析 上面我们的算法理论已经完善, 我们只用给一个混合运算式, 计算器就可以帮助我们计算出结果. 但是存在一个痛点, 每次计算算式,都要重新编译程序, 所以我们想到了, 利用单片机, 读取用户输入的按键, 组成算式, 输入给机器, 这样我们就…...

tomcat定时重启

Tomcat定时重启&#xff08;linux&#xff09; 1. 编写脚本 在tomcat的bin目录下&#xff0c;使用vim restart.sh&#xff0c;编写restart.sh脚本&#xff0c;插入一下内容&#xff0c;最后并保存&#xff01; #!/bin/bash# 初始化全局环境变量 . /etc/profilecd /usr/loca…...

构建LangChain应用程序的示例代码:48、如何使用非文本生成工具创建多模态代理

多模态输出&#xff1a;图像和文本 这个示例展示了如何使用非文本生成工具来创建多模态代理。 本例仅限于文本和图像输出&#xff0c;并使用UUID在工具和代理之间传输内容。 本例使用Steamship生成和存储生成的图像。生成的内容默认受到身份验证保护。 您可以在这里获取Ste…...

【笔记】记录一次全新的Java项目部署过程

记录一次全新的Java项目部署过程 环境:CentOS7一、初始环境准备 yum install wget -y yum install vim -y yum install net-tools -y mkdir /data mkdir /data/html mkdir /data/backend一、安装JDK 17 安装JDK17# 下载rpm wget https://download.oracle.com/java/17/latest/…...

达梦数据库系列—14. 表空间的备份和还原

目录 1、表空间备份 2、表空间还原 3、表空间恢复 4、增量还原恢复 1、表空间备份 表空间只能在联机状态下进行备份。 BACKUP TABLESPACE TBS BACKUPSET /dm/backup/dm_bak/ts_bak_01; 完全备份 BACKUP TABLESPACE TBS FULL BACKUPSET /dm/backup/dm_bak/ts_full_bak_01…...

奔驰G350升级原厂自适应悬挂系统有哪些作用

奔驰 G350 升级自适应悬挂系统后&#xff0c;可根据行车路况自动调整悬架高度和弹性&#xff0c;从而提升驾乘的舒适性和稳定性。 这套系统的具体功能包括&#xff1a; • 多种模式选择&#xff1a;一般有舒适、弯道、运动及越野等模式。例如&#xff0c;弯道模式在过弯时能为…...

一个启动脚本例子

一、全部代码 #!/bin/bash DATE$(date %Y%m%d)SOURCE"abc.jar" TARGET"backup/abc.jar.jew.$DATE"if [ -f "$SOURCE" ]; thencp "$SOURCE" "$TARGET" firm -f abc.jar mv abc_1.jar abc.jarpidNumps -ef | grep $SOURCE |…...

grpc学习golang版( 六、服务器流式传输 )

系列文章目录 第一章 grpc基本概念与安装 第二章 grpc入门示例 第三章 proto文件数据类型 第四章 多服务示例 第五章 多proto文件示例 第六章 服务器流式传输 第七章 客户端流式传输 第八章 双向流示例 文章目录 一、前言二、定义proto文件三、拷贝任意文件进项目四、编写serve…...

ubuntu语音库ALSA报错具体原因

在ubuntu中使用pyaudio或portaudio时总会有下面的提示&#xff0c;不胜其烦。 ALSA lib pcm_dsnoop.c:612:(snd_pcm_dsnoop_open) unable to open slave ALSA lib pcm_dmix.c:1018:(snd_pcm_dmix_open) unable to open slave ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unkn…...

Java高级重点知识点-17-异常

文章目录 异常异常处理自定义异常 异常 指的是程序在执行过程中&#xff0c;出现的非正常的情况&#xff0c;最终会导致JVM的非正常停止。Java处 理异常的方式是中断处理。 异常体系 异常的根类是 java.lang.Throwable&#xff0c;&#xff0c;其下有两个子类&#xff1a;ja…...

DM达梦数据库函数分析(与mysql对应函数区别及用法分析)

💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快! 💝💝💝如有需要请大家订阅我的专栏【数据库系列】哟!我会定期更新相关系列的文章 💝💝💝关注!关注!!请…...

ROS2用c++开发参数节点通信

1.创建节点 cd chapt4/chapt4_ws/ ros2 pkg create example_parameters_rclcpp --build-type ament_cmake --dependencies rclcpp --destination-directory src --node-name parameters_basic --maintainer-name "joe" --maintainer-email "1027038527qq.com&…...

docker 部署jitsi meet

1. 部署环境&#xff1a; 1.1 vm 虚拟机 安装的 centos 7 1.2 centos7安装docker 和 docker-compose 2.docker命令 官网部署文档地址&#xff1a;&#xff08;文档地址有可能失效&#xff09; Self-Hosting Guide - Docker | Jitsi Meet 2.1Download and extract the late…...

【Pytest自动化测试详解】

目录 一、前言pytest是一个非常成熟的全功能的Python测试框架&#xff0c;主要特点&#xff1a; 二、pytest安装 2.1、安装 pip install -U pytest 2.2、验证安装 pytest --version # 会展示当前已安装版本 2.3、pytest文档 官方文档&#xff1a;https:…...

6-14题连接 - 高频 SQL 50 题基础版

目录 1. 相关知识点2. 例子2.6. 使用唯一标识码替换员工ID2.7- 产品销售分析 I2.8 - 进店却未进行过交易的顾客2.9 - 上升的温度2.10 - 每台机器的进程平均运行时间2.11- 员工奖金2.12-学生们参加各科测试的次数2.13-至少有5名直接下属的经理2.14 - 确认率 1. 相关知识点 left …...

深度挖掘数据资产,洞察业务先机:利用先进的数据分析技术,精准把握市场趋势,洞悉客户需求,为业务决策提供有力支持,实现持续增长与创新

在当今日益激烈的商业竞争环境中&#xff0c;企业想要实现持续增长与创新&#xff0c;必须深入挖掘和有效运用自身的数据资产。数据不仅是企业运营过程中的副产品&#xff0c;更是洞察市场趋势、理解客户需求、优化业务决策的重要资源。本文将探讨如何通过利用先进的数据分析技…...

亚马逊广告如何设置关键词竞价获取最优广告投入产出比 (ACOS)

在投放亚马逊商品广告的时候&#xff0c;从我们通常的理解来说&#xff0c;关键词竞价CPC设置的越高&#xff0c;广告投入产出比 (ACOS)越高&#xff0c;所以我们通常希望CPC越低越好&#xff0c;但是从我们实际投放广告来看&#xff0c;CPC与ACOS并不是线性相关。有时候CPC设定…...

vision mamba-yolov8:结合Vmamba的yolov8目标检测改进实现

1.vision mamba结构与原理 Mamba成功的关键在于S6模型&#xff0c;该模型为NLP任务设计&#xff0c;通过选择性扫描空间状态序列模型&#xff0c;将二次复杂度降低至线性。但由于视觉信号&#xff08;如图像&#xff09;的无序性&#xff0c;Mamba的S6模型不能直接应用&#xf…...

2025秋招NLP算法面试真题(十一)-Transformer的并行化

正文 本文主要谈一下关于 Transformer的并行化。文章比较短&#xff0c;适合大家碎片化阅读。 Decoder不用多说&#xff0c;没有并行&#xff0c;只能一个一个的解码&#xff0c;很类似于RNN&#xff0c;这个时刻的输入依赖于上一个时刻的输出。 对于Encoder侧&#xff1a; …...

如何在本地一键配置最强国产大模型

自从OpenAI的ChatGPT横空出世以来&#xff0c;国内外各类大语言模型&#xff08;LLM&#xff09;层出不穷&#xff0c;其中不乏Google的Gemini、Claude、文心一言等等。相较于竞争激烈的商业模型赛道&#xff0c;以Llama为代表的开源大模型的进步速度也十分惊人。 伴随着大语言…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

Linux 下 DMA 内存映射浅析

序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程&#xff0c;可以参考这篇文章&#xff0c;我觉得写的非常…...

第八部分:阶段项目 6:构建 React 前端应用

现在&#xff0c;是时候将你学到的 React 基础知识付诸实践&#xff0c;构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段&#xff0c;你可以先使用模拟数据&#xff0c;或者如果你的后端 API&#xff08;阶段项目 5&#xff09;已经搭建好&#xff0c;可以直接连…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例

目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码&#xff1a;冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...

2.3 物理层设备

在这个视频中&#xff0c;我们要学习工作在物理层的两种网络设备&#xff0c;分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间&#xff0c;需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质&#xff0c;假设A节点要给…...