【03】STM32F407 HAL 庫框架設計學習

【03】STM32F407 HAL 庫框架設計學習

摘要

本文旨在為初學者提供一個關于STM32F407微控制器HAL(Hardware Abstraction Layer)庫框架設計的詳細學習教程。通過本文,讀者將從零開始,逐步掌握STM32F407的基本知識、HAL庫的配置步驟、HAL庫函數的使用方法,并通過配套的例程和代碼注釋加深理解。本文內容涵蓋基礎知識、配置步驟、HAL庫函數詳解、配套例程和總結,并附有思維導圖以幫助讀者更好地理解知識結構。


初學者重要提示

在開始學習STM32F407和HAL庫之前,請注意以下幾點:

  1. 硬件準備
    • 確保你擁有STM32F407開發板,并熟悉其硬件結構。
    • 準備好調試工具,如ST-Link或類似設備。
  2. 軟件安裝
    • 安裝STM32CubeMX和STM32CubeIDE。
    • 安裝STM32Cube_FW_F4固件庫。
  3. 開發環境配置
    • 確保STM32CubeMX和STM32CubeIDE已正確配置,并能夠生成和編譯項目。
  4. 學習資源
    • 熟悉STM32F407的數據手冊和HAL庫參考手冊。
    • 參考STM32CubeMX和STM32CubeIDE的用戶指南。
  5. 編程基礎
    • 熟悉C語言編程基礎。
    • 理解基本的嵌入式系統概念,如中斷、DMA等。

1. 基礎知識

1.1 STM32F407簡介

STM32F407是STMicroelectronics公司推出的一款高性能32位微控制器,基于ARM Cortex-M4內核,工作頻率高達168MHz。它集成了豐富的外設,如GPIO、UART、SPI、I2C、PWM、ADC、DAC等,適用于多種嵌入式應用。

1.2 HAL庫簡介

HAL(Hardware Abstraction Layer)庫是ST公司為STM32系列微控制器提供的標準軟件庫,旨在為開發者提供一個統一的接口,簡化硬件操作。HAL庫將硬件操作抽象為函數調用,使得開發者無需深入了解底層硬件細節,即可完成復雜的硬件操作。

1.3 開發環境搭建

在開始使用STM32F407和HAL庫之前,需要先搭建開發環境。以下是搭建開發環境的步驟:

  1. 安裝STM32CubeMX:STM32CubeMX是一個圖形化配置工具,用于配置STM32微控制器的外設和時鐘。
  2. 安裝STM32CubeIDE:STM32CubeIDE是基于Eclipse的集成開發環境,用于STM32項目的開發和調試。
  3. 安裝STM32Cube_FW_F4:這是STM32F4系列的HAL庫和底層固件庫,包含HAL庫的源代碼和頭文件。

2. 配置步驟

2.1 使用STM32CubeMX配置STM32F407

  1. 打開STM32CubeMX,選擇STM32F407VG芯片。
  2. 配置時鐘:在“Clock Configuration”選項卡中,配置系統時鐘為168MHz。
  3. 配置GPIO:在“Pinout & Configuration”選項卡中,配置GPIO引腳的功能。例如,配置GPIOA的第5引腳為LED輸出。
  4. 配置其他外設:根據需要配置其他外設,如UART、SPI、I2C等。
  5. 生成代碼:完成配置后,點擊“Generate Code”按鈕,選擇保存路徑,生成初始化代碼。

2.2 在STM32CubeIDE中配置項目

  1. 導入生成的代碼:在STM32CubeIDE中,選擇“File” -> “Import” -> “STM32CubeMX Project” -> “Existing STM32CubeMX Project”,導入生成的代碼。
  2. 配置項目:在“Project Explorer”中,右鍵點擊項目,選擇“Properties”,配置項目屬性,如調試配置、編譯選項等。
  3. 構建項目:點擊“Build”按鈕,構建項目,確保沒有錯誤。

3. HAL庫函數詳解

3.1 GPIO操作

3.1.1 GPIO初始化
HAL_StatusTypeDef HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
  • 參數

    • GPIOx:GPIO端口,如GPIOA、GPIOB等。
    • GPIO_Init:指向GPIO初始化結構體的指針,包含GPIO模式、速度、上下拉配置等信息。
  • 返回值

    • HAL_OK:初始化成功。
    • HAL_ERROR:初始化失敗。
3.1.2 GPIO輸入輸出操作
HAL_StatusTypeDef HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
  • 參數

    • GPIOx:GPIO端口。
    • GPIO_Pin:GPIO引腳,如GPIO_PIN_5。
    • PinState:引腳狀態,GPIO_PIN_SET表示高電平,GPIO_PIN_RESET表示低電平。
  • 返回值

    • HAL_OK:操作成功。
    • HAL_ERROR:操作失敗。

3.2 UART操作

3.2.1 UART初始化
HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart, UART_InitTypeDef *uInit)
  • 參數

    • huart:UART句柄,包含UART配置信息。
    • uInit:指向UART初始化結構體的指針,包含波特率、數據位、停止位、校驗位等信息。
  • 返回值

    • HAL_OK:初始化成功。
    • HAL_ERROR:初始化失敗。
3.2.2 UART數據發送
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
  • 參數

    • huart:UART句柄。
    • pData:指向發送數據緩沖區的指針。
    • Size:發送數據的長度。
    • Timeout:超時時間。
  • 返回值

    • HAL_OK:發送成功。
    • HAL_ERROR:發送失敗。

3.3 PWM操作

3.3.1 PWM初始化
HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim, TIM_InitTypeDef *pInitStruct)
  • 參數

    • htim:TIM句柄,包含PWM配置信息。
    • pInitStruct:指向TIM初始化結構體的指針,包含PWM模式、時鐘源、頻率等信息。
  • 返回值

    • HAL_OK:初始化成功。
    • HAL_ERROR:初始化失敗。
3.3.2 PWM輸出
HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
  • 參數

    • htim:TIM句柄。
    • Channel:PWM通道,如TIM_CHANNEL_1。
  • 返回值

    • HAL_OK:啟動成功。
    • HAL_ERROR:啟動失敗。

4. 配套例程

4.1 LED閃爍例程

4.1.1 代碼實現
#include "main.h"GPIO_InitTypeDef GPIO_InitStructure;void SystemClock_Config(void);
static void MX_GPIO_Init(void);int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();while (1){HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);HAL_Delay(500);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);HAL_Delay(500);}
}static void MX_GPIO_Init(void)
{GPIO_InitStructure.Pin = GPIO_PIN_5;GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStructure.Pull = GPIO_NOPULL;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
}void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 25;RCC_OscInitStruct.PLL.PLLN = 336;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;RCC_OscInitStruct.PLL.PLLQ = 7;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}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();}
}void Error_Handler(void)
{while (1){}
}
4.1.2 代碼說明
  • HAL_Init():初始化HAL庫。
  • SystemClock_Config():配置系統時鐘。
  • MX_GPIO_Init():配置GPIO引腳。
  • HAL_GPIO_WritePin():控制GPIO引腳輸出。
  • HAL_Delay():延時函數。

4.2 UART通信例程

4.2.1 代碼實現
#include "main.h"UART_HandleTypeDef huart2;void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_USART2_UART_Init();while (1){char data = 'A';HAL_UART_Transmit(&huart2, (uint8_t *)&data, 1, 100);HAL_Delay(1000);}
}static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.Pin = GPIO_PIN_2;GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;GPIO_InitStructure.Pull = GPIO_NOPULL;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
}static void MX_USART2_UART_Init(void)
{huart2.Instance = USART2;huart2.Init.BaudRate = 115200;huart2.Init.WordLength = UART_WORDLENGTH_8B;huart2.Init.StopBits = UART_STOPBITS_1;huart2.Init.Parity = UART_PARITY_NONE;huart2.Init.Mode = UART_MODE_TX_RX;huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart2.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart2) != HAL_OK){Error_Handler();}
}void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 25;RCC_OscInitStruct.PLL.PLLN = 336;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;RCC_OscInitStruct.PLL.PLLQ = 7;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}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();}
}void Error_Handler(void)
{while (1){}
}
4.2.2 代碼注釋
  • UART_HandleTypeDef huart2:UART句柄。
  • MX_USART2_UART_Init():配置UART2。
  • HAL_UART_Transmit():發送數據。
  • HAL_Delay():延時函數。

4.3 PWM生成例程

4.3.1 代碼實現
#include "main.h"TIM_HandleTypeDef htim2;void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_TIM2_Init();HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);while (1){HAL_Delay(1000);}
}static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.Pin = GPIO_PIN_0;GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;GPIO_InitStructure.Pull = GPIO_NOPULL;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
}static void MX_TIM2_Init(void)
{TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};htim2.Instance = TIM2;htim2.Init.Prescaler = 8399;htim2.Init.CounterMode = TIM_COUNTERMODE_UP;htim2.Init.Period = 999;htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;if (HAL_TIM_Init(&htim2) != HAL_OK){Error_Handler();}sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK){Error_Handler();}
}void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCClkInitStruct = {0};RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 25;RCC_OscInitStruct.PLL.PLLN = 336;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;RCC_OscInitStruct.PLL.PLLQ = 7;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}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();}
}void Error_Handler(void)
{while (1){}
}
4.3.2 代碼說明
  • TIM_HandleTypeDef htim2:TIM句柄。
  • MX_TIM2_Init():配置TIM2。
  • HAL_TIM_PWM_Start():啟動PWM輸出。
  • HAL_Delay():延時函數。

5. 總結

通過本文的學習,讀者應該能夠掌握STM32F407的基本知識、HAL庫的配置步驟、HAL庫函數的使用方法,并能夠通過配套的例程和代碼注釋加深理解。HAL庫的使用大大簡化了硬件操作,使得開發者能夠更專注于應用邏輯的實現。希望本文能夠幫助讀者快速上手STM32F407的開發。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/72273.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/72273.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/72273.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

跟著官方文檔學習UE C++ TArray容器系列 迭代 和 排序

一.首先測試下&#xff0c;官方案例 迭代器的方法&#xff0c;有點不常見。有點像個指針&#xff0c;迭代完還自帶break. oid AWXTArrayActor::WXLoopArray() {FString JoinedStr1;FString JoinedStr2;TArray<FString> StrArr { "Hello","Baby",&q…

C++中的“結界”機制:作用域與變量可見性探秘

一、編程世界的“結界”概念 源自佛學的結界概念&#xff0c;在C中體現為作用域機制。程序中的每個函數都會形成獨立的作用域屏障&#xff0c;如同魔法結界般保護內部變量&#xff0c;使其與外界的同名變量互不干擾。這種機制保證了代碼模塊的獨立性和安全性&#xff0c;但當存…

3-6 WPS JS宏 工作表移動復制實例-1(工作表的拆分操作)學習筆記

************************************************************************************************************** 點擊進入 -我要自學網-國內領先的專業視頻教程學習網站 *******************************************************************************************…

Qt 對象樹詳解:從原理到運用

1. 什么是對象樹&#xff1f; 對象樹是一種基于父子關系的對象管理機制。在 Qt 中&#xff0c;所有繼承自 QObject 的類都可以參與到對象樹中。 當一個對象被設置為另一個對象的父對象時&#xff0c;子對象會被添加到父對象的內部列表中&#xff0c;形成一種樹狀結構。 Qt 提…

使用hutool將json集合對象轉化為對象

集合之間相互轉化 //List轉Json&#xff0c;maps是List類型的參數 String json JSONUtil.toJsonStr(maps); System.out.println("這是json字符串: "json);//Json轉List JSONArray objects JSONUtil.parseArray(json); List<Map> maps1 JSONUtil.toList(objec…

Qt關于平滑滾動的使用QScroller及QScrollerProperties類說明

一、觸控時代的滾動工具&#xff1a;QScroller類設計介紹 1.1 從機械滾輪到數字慣性 在觸控設備普及前&#xff0c;滾動操作如同老式打字機的滾軸&#xff0c;只能通過鼠標滾輪或滾動條進行離散式控制。QScroller的出現如同給數字界面裝上了"慣性飛輪"&#xff0c;…

JavaAPI(網絡編程)

網絡通信協議 通信協議 ?所謂通信協議&#xff0c;是指通信雙方在進行數據交換時必須遵守的規則和約定。?這些規則確保了雙方能夠有效地進行通信&#xff0c;實現信息的交換和資源共享。通信協議定義了傳輸時的數據格式、控制信息以及傳輸順序和速度等&#xff0c;確保雙方…

Java---入門基礎篇(下)---方法與數組

前言 本篇文章主要講解有關方法與數組的知識點 ,是基礎篇的一部分 , 而在下一篇文章我會講解類和對象的知識點 入門基礎篇上的鏈接給大家放在下面啦 ! Java---入門基礎篇(上)-CSDN博客 感謝大家點贊&#x1f44d;&#x1f3fb;收藏?評論?&#x1f3fb; 歡迎各位大佬指點…

Python 爬蟲 – BeautifulSoup

Python 爬蟲&#xff08;Web Scraping&#xff09;是指通過編寫 Python 程序從互聯網上自動提取信息的過程。 爬蟲的基本流程通常包括發送 HTTP 請求獲取網頁內容、解析網頁并提取數據&#xff0c;然后存儲數據。 Python 的豐富生態使其成為開發爬蟲的熱門語言&#xff0c;特…

圖像分類項目1:基于卷積神經網絡的動物圖像分類

一、選題背景及動機 在現代社會中&#xff0c;圖像分類是計算機視覺領域的一個重要任務。動物圖像分類具有廣泛的應用&#xff0c;例如生態學研究、動物保護、農業監測等。通過對動物圖像進行自動分類&#xff0c;可以幫助人們更好地了解動物種類、數量和分布情況&#xff0c;…

物聯網 智慧園區井蓋管理辦法和功能介紹

在園區內實現 智慧井蓋 的定位、內部氣體檢測和紅外監測等頂級功能&#xff0c;可以顯著提升園區的安全管理水平和運維效率。以下是智慧井蓋系統的詳細設計方案和功能實現&#xff1a; 一、系統架構 智慧井蓋系統可以分為以下層次&#xff1a; 1. 感知層 定位模塊&#xff1…

零基礎deep seek+剪映,如何制作高品質的視頻短片

以下是專為零基礎學習者設計的 剪映專業版詳細教程&#xff0b;Deep seek配合制 &#xff0c;包含從入門到精通的系統化教學&#xff0c;配合具體操作步驟與實用技巧&#xff1a; 基于DeepSeek與剪映協同制作高品質視頻短片的專業流程指南&#xff08;2025年最新實踐版&#x…

PHP:IDEA開發工具配置XDebug,斷點調試

文章目錄 一、php.ini配置二、IDEA配置 一、php.ini配置 [xdebug] zend_extension"F:\wamp64\bin\php\php7.4.0\ext\php_xdebug-2.8.0-7.4-vc15-x86_64.dll" xdebug.remote_enable on xdebug.remote_host 127.0.0.1 xdebug.remote_port 9001 xdebug.idekey"…

改進YOLOv8模型的空間注意力機制研究:RFAConv的貢獻與實現

文章目錄 1. 背景介紹2. 什么是RFAConv?3. YOLOv8中的RFAConv實現3.1 RFAConv模塊設計3.2 在YOLOv8中集成RFAConv4. 性能對比與實驗結果4.1 實驗設置4.2 實驗結果5. 模型優化與調優5.1 調整RFAConv模塊的超參數5.2 數據增強策略5.3 更深層的注意力機制5.4 混合卷積與優化計算圖…

【Java】使用jdk自帶的zip壓縮實現任意文件壓縮打包下載功能(復制即用)

前言 在實際項目中&#xff0c;我們可能會接到將文件或者資料打包壓縮導出的需求&#xff0c;例如將系統中某些生成的文件一起打包壓縮下載提供給客戶使用&#xff0c;今天提供一個jdk自帶的工具類快速實現打包壓縮的功能&#xff0c;方法我已經封裝好&#xff0c;大家如果在項…

騰訊云擴容記錄

騰訊云擴容&#xff1a; sudo yum install -y cloud-utils-growpart 安裝擴容工具 sudo file -s /dev/vda1 有數據 sudo LC_ALLen_US.UTF-8 growpart /dev/vda 1 sudo resize2fs /dev/vda1 df -Th 完畢 以下是對執行的命令的詳細解釋以及背后的原理&#xff1a; 1. 安裝 cloud…

服務流程設計和服務或端口重定向及其websocket等應用示例

服務流程設計和服務或端口重定向及其websocket等應用示例 目錄 服務或端口重定向的服務設計和websocket等應用示例 一、通用請求控制流程 1.1、入口 1.2、所有GET請求首先預檢控制單元 1.3、http請求會分別自動307重定向 1.4、所有請求首先執行跨源控制單元 1.5、然后…

PHP面試題--后端部分

本文章持續更新內容 之前沒來得及整理時間問題導致每次都得找和重新背 這次整理下也方便各位小伙伴一起更輕松的一起踏入編程之路 歡迎各位關注博主不定期更新各種高質量內容適合小白及其初級水平同學一起學習 一起成為大佬 數組函數有那些 ps&#xff1a;本題挑難的背因為…

深入了解 MySQL 中的 JSON_CONTAINS

深入了解 MySQL 中的 JSON_CONTAINS MySQL 5.7 及更高版本引入了對 JSON 數據類型的支持&#xff0c;使得在數據庫中存儲和查詢 JSON 數據成為可能。在這些新功能中&#xff0c;JSON_CONTAINS 函數是一個非常有用的工具&#xff0c;允許我們檢查一個 JSON 文檔是否包含特定的值…

git命令學習記錄

1. git reset 參數說明 git reset 是用來回退版本的&#xff0c;它可以添加三個參數&#xff0c;常用的使用格式是這樣的&#xff1a;git reset [--hard | --soft | --mixed] 版本號 一般使用git修改文件并提交需要三步&#xff0c;第一步在文本編輯器中編輯文件&#xff0c;也…