STM32HAL-最简单的长、短、多击按键框架

news2024/11/17 0:45:16

目录

 概述 

一、开发环境

二、STM32CubeMx配置

三、编码 

四、运行结果

五、总结


 概述 

       本文章使用最简单的写法实现长、短、多击按键框架,非常适合移植各类型单片机,特别是资源少的芯片上。接下来将在stm32单片机上实现,只需占用1个定时器作为时钟扫描按键即可。

一、开发环境

1、硬件平台
     STM32F401CEU6
     内部Flash : 512Kbytes,SARM : 96 Kbytes

二、STM32CubeMx配置

 2.1、系统时钟配置

2.2、下载调试配置

2.3、TIM配置(1ms中断)

2.4、usart1配置

2.5、生成代码

2.6、编译工程

三、编码 

1、usart.c添加打印

/* USER CODE BEGIN 1 */
#include "stdio.h"
#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
 
  return ch;
}
 
int fgetc(FILE * f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}

/* USER CODE END 1 */

2、tim1.c

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    tim.c
  * @brief   This file provides code for the configuration
  *          of the TIM instances.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "tim.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

TIM_HandleTypeDef htim1;

/* TIM1 init function */
void MX_TIM1_Init(void)
{

  /* USER CODE BEGIN TIM1_Init 0 */

  /* USER CODE END TIM1_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM1_Init 1 */

  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 84-1;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 1000-1;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM1_Init 2 */

  /* USER CODE END TIM1_Init 2 */

}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{

  if(tim_baseHandle->Instance==TIM1)
  {
  /* USER CODE BEGIN TIM1_MspInit 0 */

  /* USER CODE END TIM1_MspInit 0 */
    /* TIM1 clock enable */
    __HAL_RCC_TIM1_CLK_ENABLE();

    /* TIM1 interrupt Init */
    HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
  /* USER CODE BEGIN TIM1_MspInit 1 */

  /* USER CODE END TIM1_MspInit 1 */
  }
}

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{

  if(tim_baseHandle->Instance==TIM1)
  {
  /* USER CODE BEGIN TIM1_MspDeInit 0 */

  /* USER CODE END TIM1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_TIM1_CLK_DISABLE();

    /* TIM1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn);
  /* USER CODE BEGIN TIM1_MspDeInit 1 */

  /* USER CODE END TIM1_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */
#include "stdio.h"
#include "button.h"

int timeCount = 0;
int timeCount_1ms = 0;

SystemButtonObj sys_btn_obj;

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
	if(htim->Instance == TIM1){
		timeCount++;
        timeCount_1ms++; 

        if ((timeCount_1ms % 10) == 0) {    //10ms
			timeCount_1ms = 0;
			
			GPIO_PinState PinState = HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin);	//down isr
			if ((PinState == false) && (sys_btn_obj.flag == false)) {
				sys_btn_obj.flag = true;
			}
			button_handler(&sys_btn_obj, PinState);
		}

		if(timeCount == 1000){
			timeCount = 0;
			//printf("time + 1s\n");
		}
	}
}

/* USER CODE END 1 */

3、在根目录创建button文件夹,分别有button.c、button.h文件组成。
1)、button.c文件

#include<stdbool.h>
#include "button.h"



void button_handler(SystemButtonObj *btn_obj, uint8_t press_state)
{
	//printf("btn_obj->flag:%d\r\n", btn_obj->flag);
	
	if (btn_obj->flag == false) {
		return;
	}	

	if (press_state == BUTTON_RELEASE) { //释放按键
		
		if ((btn_obj->dow_counter != 0) && (btn_obj->long_press == 1)) {
			btn_obj->long_press = 0;
			btn_obj->dow_counter = 0;
			return;
		}
		
		if (btn_obj->long_press == 1) {
			btn_obj->flag = false;
			return;
		}
		
		if (btn_obj->dow_counter > 2) {
			btn_obj->click_cnt++;
			//printf(" btn_obj->click_cnt %d, SHORT_PRESS_RELEASE_CNT %d LONG_PRESS_TRIGGER_TIME %d \r\n", btn_obj->click_cnt, SHORT_PRESS_RELEASE_CNT, LONG_PRESS_TRIGGER_TIME);
		}
		
		if (btn_obj->click_cnt) {
			btn_obj->up_counter++;
			
			if (btn_obj->up_counter > DOUBLE_PRESS_RELEASE_CNT) {  
				//printf(" btn_obj->up_counter %d SHORT_PRESS_RELEASE_CNT %d\r\n", btn_obj->up_counter, SHORT_PRESS_RELEASE_CNT);
				if (btn_obj->click_cnt == 1) {
					printf("counter %d, short \r\n", btn_obj->up_counter);
                    sys_btn_obj.press_event = ET_SHORT_PRESS_EVENT;
				} else if (btn_obj->click_cnt == 2) {
                    sys_btn_obj.press_event = ET_DOUBLE_PRESS_EVENT;    
					printf("counter %d, double \r\n", btn_obj->up_counter);
				} else {
                    sys_btn_obj.press_event = ET_MULTIHIT_PRESS_EVENT;
					printf("counter %d, multihit \r\n", btn_obj->up_counter);
				}
				btn_obj->click_cnt = 0;
				btn_obj->up_counter = 0;
				btn_obj->flag = false;
			}
		}
		
		btn_obj->dow_counter = 0; //清除计数变量
	} 
	
	if (press_state == btn_obj->press_status) { //低电平有效
		//printf(" hahahaha press_state %d \r\n", press_state);
		btn_obj->dow_counter++; //计算次数
		//printf("counter %d, press_state:%d\r\n", btn_obj->dow_counter, press_state);
		
		// 不松手的长按
		if ((btn_obj->dow_counter > LONG_PRESS_TRIGGER_TIME) && (btn_obj->long_press == 0)) {
			btn_obj->long_press = 1;
			sys_btn_obj.press_event = ET_LONG_PRESS_EVENT;
			printf("long press\r\n");
		}
		
		if (btn_obj->dow_counter > RESTART_TRIGGER_TIME) { //超长时间,重启事件
			printf("restart press\r\n");
			sys_btn_obj.press_event = ET_RESTART_PRESS_EVENT;
		}
		
	}
	
}


void key_event_handler(void)
{

    switch (sys_btn_obj.press_event)
    {
        case ET_IDLE_PRESS_EVENT:
            // printf("ET_IDLE_PRESS_EVENT\r\n");
            break;
        case ET_SHORT_PRESS_EVENT:
            printf("ET_SHORT_PRESS_EVENT\r\n");
            sys_btn_obj.press_event = ET_IDLE_PRESS_EVENT;
            break;
        case ET_DOUBLE_PRESS_EVENT:
            printf("ET_DOUBLE_PRESS_EVENT\r\n");
            sys_btn_obj.press_event = ET_IDLE_PRESS_EVENT;
            break;
        case ET_MULTIHIT_PRESS_EVENT:
            printf("ET_MULTIHIT_PRESS_EVENT\r\n");
            sys_btn_obj.press_event = ET_IDLE_PRESS_EVENT;
            break;
        case ET_LONG_PRESS_EVENT:
            printf("ET_LONG_PRESS_EVENT\r\n");
            sys_btn_obj.press_event = ET_IDLE_PRESS_EVENT;
            break;
        case ET_RESTART_PRESS_EVENT:
            printf("ET_RESTART_PRESS_EVENT\r\n");
            sys_btn_obj.press_event = ET_IDLE_PRESS_EVENT;
            break;
        default :
            break;
    }
}

2)、button.h文件

#ifndef __BUTTON_H__
#define __BUTTON_H__


#ifdef __cplusplus
extern "C" {
#endif

#define BUTTON_TIMER_INTERVAL		(50)
#define LONG_PRESS_TRIGGER_TIME		(1500 / BUTTON_TIMER_INTERVAL)
#define RESTART_TRIGGER_TIME		((8 * 1000) / BUTTON_TIMER_INTERVAL)
//#define SHORT_PRESS_RELEASE_CNT		(200 / BUTTON_TIMER_INTERVAL)
#define DOUBLE_PRESS_RELEASE_CNT	(400 / BUTTON_TIMER_INTERVAL)

enum {  
	BUTTON_PRESS = 0,  
	BUTTON_RELEASE = 1, 
};

typedef enum {
    ET_IDLE_PRESS_EVENT,
    ET_SHORT_PRESS_EVENT,
    ET_DOUBLE_PRESS_EVENT,
    ET_MULTIHIT_PRESS_EVENT,
    ET_LONG_PRESS_EVENT,
    ET_RESTART_PRESS_EVENT,
}BTN_EVENT_TYPE;

typedef struct {
	uint8_t 		flag:1;
	uint8_t			press_status:1;
	uint8_t			long_press:1;
	uint8_t			double_press:1;
	uint8_t			click_cnt;
	uint8_t			up_counter;
	uint8_t			dow_counter;
	BTN_EVENT_TYPE  press_event;
} SystemButtonObj;

extern SystemButtonObj sys_btn_obj;


void button_handler(SystemButtonObj *btn_obj, uint8_t press_state);
void key_event_handler(void);


#ifdef __cplusplus
}
#endif

#endif 

 3)、main.c文件

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "iwdg.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "button.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_TIM1_Init();
//  MX_IWDG_Init();
  /* USER CODE BEGIN 2 */
	HAL_TIM_Base_Start_IT(&htim1);
	printf("heihei button \r\n");
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  key_event_handler();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

注意:keil上需要勾选Use MicroLIB,否则CubeMX生成的串口工程无法打印问题

四、运行结果

      

五、总结

        好了,终于介绍完毕,以后裸机开发,有了按键框架方便很多,可移植到C51或者资源更少的芯片上,感谢参阅 ^_^。

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

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

相关文章

spring 启动顺序

BeanFactoryAware 可在Bean 中获取 BeanFactory 实例 ApplicationContextAware 可在Bean 中获取 ApplicationContext 实例 BeanNameAware 可以在Bean中得到它在IOC容器中的Bean的实例的名字。 ApplicationListener 可监听 ContextRefreshedEvent等。 CommandLineRunner 整…

MySQL学习——选项文件的使用

MySQL 的许多程序都可以从选项文件&#xff08;有时也被称为配置文件&#xff09;中读取启动选项。选项文件提供了一种方便的方式来指定常用的选项&#xff0c;这样你就不必每次运行程序时都在命令行上输入这些选项。 要确定一个程序是否读取选项文件&#xff0c;你可以使用 -…

【工具箱】嵌入式系统存储芯片——CS创世 SD NAND

大家都知道MCU是一种"麻雀"虽小&#xff0c;却"五脏俱全"的主控。它的应用领域非常广泛&#xff0c;小到手机手表&#xff0c;大到航空航天的设备上都会用到MCU.市面上目前几个主流厂商有意法半导体&#xff08;其中最经典的一款就是STM32系列&#xff09;…

SSL证书国产化对提升我国网络安全的重要性

在互联网时代&#xff0c;数据安全和隐私保护成为全球关注的焦点。SSL证书作为保障网络通信安全的关键技术&#xff0c;其重要性不言而喻。然而&#xff0c;长期以来&#xff0c;我国在SSL证书领域过度依赖国外产品和技术&#xff0c;不仅存在安全隐患&#xff0c;也制约了我国…

LNMP网络架构的搭建

操作准备&#xff1a;准备三台虚拟机 安装 MySQL 服务 &#xff08;1&#xff09;准备好mysql目录上传软件压缩包并解压 cd /opt mkdir mysql tar xf mysql-boost-5.7.44.tar.gz &#xff08;2&#xff09;安装mysql环境依赖包 yum -y install ncurses ncurses-devel bison…

计算机网络之曼彻斯特编码和差分曼彻斯特编码

目录 前言 曼彻斯特编码 定义 策略 思路 差分曼彻斯特编码 定义 策略 思路 结束语 前言 今天是坚持写博客的第十九天&#xff0c;很高兴自己又坚持了一天&#xff0c;今天想送给自己一句李白《行路难》当中的诗词&#xff0c;希望我自己和大家都可以铭记于心&#x…

27、matlab傅里叶变换:fft()函数

1、fft 快速傅里叶变换 语法 Y fft(X) 使用快速傅里叶变换 (FFT) 算法计算 X 的离散傅里叶变换 (DFT)。 Y fft(X,n) 返回 n 点 DFT。 Y fft(X,n,dim) 返回沿维度 dim 的傅里叶变换。例如&#xff0c;如果 X 是矩阵&#xff0c;则 fft(X,n,2) 返回每行的 n 点傅里叶变换含…

微软不再允许Windows 11通过1@1.com绕过登录 但还有其他办法可以继续用

微软不再允许 Windows 11 通过 11.com 和 nothankyou.com 绕过登录&#xff0c;但断网的情况下使用 OOBE\BYPASSNRO 命令仍然是有效的。如果你在安装或重置系统时仍然需要创建本地账户&#xff0c;请直接使用 OOBE 命令。 在 Windows 11 家庭版和专业版中用户必须保持设备联网…

尚硅谷2024新版3小时速通Docker教程

尚硅谷2024新版3小时速通Docker教程 百度网盘&#xff1a;https://pan.baidu.com/s/1SncgHbdJehvZspjcrrbLSw?pwd6c27

linux 系统监控脚本

1.对CPU的监控函数 function GetCpu(){cpu_numgrep -c "model name" /proc/cpuinfocpu_usertop -b -n 1 | grep Cpu | awk {print $2} | cut -f 1 -d "%"cpu_systemtop -b -n 1 | grep Cpu | awk {print $4} | cut -f 1 -d "%"cpu_idletop -b -…

Github 2024-06-06 Go开源项目日报 Top10

根据Github Trendings的统计,今日(2024-06-06统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Go项目10Ollama: 本地大型语言模型设置与运行 创建周期:248 天开发语言:Go协议类型:MIT LicenseStar数量:42421 个Fork数量:2724 次关注人…

当边缘计算用在定位设备

什么是边缘计算&#xff1f; 边缘计算是个比较高大上的概念&#xff0c;在这里就不提众多官方与非官方的定义了&#xff0c;只说说自己的理解。 边缘计算就是在最靠近物理设备的使用现场&#xff0c;利用有限的硬件资源&#xff0c;完成设备层数据采集、协议转换、数据上传、…

Java | Leetcode Java题解之第120题三角形最小路径和

题目&#xff1a; 题解&#xff1a; class Solution {public int minimumTotal(List<List<Integer>> triangle) {int n triangle.size();int[] f new int[n];f[0] triangle.get(0).get(0);for (int i 1; i < n; i) {f[i] f[i - 1] triangle.get(i).get(i…

Chrome浏览器打开无痕模式的方法

快捷键&#xff1a;同时按住CtrlshiftN 如图&#xff0c;系统会新开一个无痕标签页&#xff0c;不需要了点右上角关闭就可以了。

探索计算机视觉:开启智能图像处理的新纪元

第一部分&#xff1a;计算机视觉概述与基本原理 计算机视觉&#xff0c;作为人工智能领域的重要分支&#xff0c;旨在让计算机具备处理和理解图像和视频数据的能力。随着深度学习技术的飞速发展&#xff0c;计算机视觉已经在许多实际应用场景中取得了显著的成果&#xff0c;如…

山东大学软件学院项目实训-创新实训-基于大模型的旅游平台(二十七)- 微服务(7)

11.1 : 同步调用的问题 11.2 异步通讯的优缺点 11.3 MQ MQ就是事件驱动架构中的Broker 安装MQ docker run \-e RABBITMQ_DEFAULT_USERxxxx \-e RABBITMQ_DEFAULT_PASSxxxxx \--name mq \--hostname mq1 \-p 15672:15672 \-p 5672:5672 \-d \rabbitmq:3-management 浏览器访问1…

RabbitMQ-直连交换机(direct)使用方法

RabbitMQ-默认读、写方式介绍 RabbitMQ-发布/订阅模式 目录 1、概述 2、直连交换机 3、多重绑定 4、具体代码实现 4.1 生产者部分 4.2 消费者部分 5、运行代码 6、总结 1、概述 直连交换机&#xff0c;可以实现类似路由的功能&#xff0c;消息从交换机发送到哪个队列…

详细分析Mysql中的SQL_MODE基本知识(附Demo讲解)

目录 前言1. 基本知识2. Demo讲解2.1 ONLY_FULL_GROUP_BY2.2 STRICT_TRANS_TABLES2.3 NO_ZERO_IN_DATE2.4 NO_ENGINE_SUBSTITUTION2.5 ANSI_QUOTES 前言 了解Mysql内部的机制有助于辅助开发以及形成整体的架构思维 对于基本的命令行以及优化推荐阅读&#xff1a; 数据库中增…

【C语言】详解函数(下)(庖丁解牛版)

文章目录 1. 前言2. 数组做函数形参3. 函数嵌套调用和链式访问3.1 嵌套调用3.2 链式访问 1. 前言 详解C语言函数(上)的链接&#xff1a;http://t.csdnimg.cn/EGsfe 经过对函数的初步了解之后,相信大家已经对C语言标准库里的函数已经有初步的认知了&#xff0c;并且还学会了如…

HashMap第2讲——put方法源码及细节

上篇文章介绍了HashMap在JDK 1.8前后的四大变化&#xff0c;今天就进入到put方法的源码解析。HashMap的设计非常巧妙&#xff0c;细节也很多&#xff0c;今天来看看部分细节&#xff0c;后续的文章会一一介绍。 ps&#xff1a;学习源码的目的不仅仅是为了了解它的运行机制&…