Clion开发STM32之串口封装(HAL库)

news2024/12/23 15:49:38

前提

  1. 在开发STM32过程中,芯片提供的串口引脚一般是不会发生变化的,所以为了方便移植,借助HAL提供的注册回调函数自定义,这边重新进行简要的封装
  2. 此工程开发是以Clion为开发的IDE,用keil只需将对应的文件进行移植即可.
  3. 文章末尾附带gitee工程地址

工程创建(以STM32F103C8T6为例)

  1. 参考Stm32开发环境从0搭建(Clion作为开发软件)
  2. 开启自定义注册串口硬件注册回调(方便后面工程移植,也可以使用HAL默认的硬件回调)
    在这里插入图片描述3. 打开工程并测试
    在这里插入图片描述

添加自定义的项目路径(方便后期移植)

  1. 创建目录框架
    在这里插入图片描述2. 编写CMakeLists文件t和CMakeLists模板文件(此步骤是将自定义目录框架包含到项目中)
    在这里插入图片描述在这里插入图片描述3. 创建同一的头文件去管理

在这里插入图片描述

统一串口宏定义

头文件 (bsp_serial_define.h)

#ifndef STM32_VET6_BSP_SERIAL_DEFINE_H
#define STM32_VET6_BSP_SERIAL_DEFINE_H

#include "sys_driver_include.h"
// 串口只支持异步
/***********************************************************串口1相关宏定义*******************************************************/
#define USE_COM1_ENABLE (1)
#define USE_COM1_IRQ_ENABLE (0) // 串口1中断使能
#define USE_COM1_DMA_RX_ENABLE (0) // 串口1 DMA RX 使能
#define COM1_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define COM1_TX_PORT GPIOA
#define COM1_TX_PIN GPIO_PIN_9
#define COM1_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define COM1_RX_PORT GPIOA
#define COM1_RX_PIN GPIO_PIN_10
#define COM1_IRQ_Priority 5 // 抢占优先级
#define COM1_IRQ_SubPriority 0 // 响应优先级
#define COM1_DMA_RX_CHANNEL DMA1_Channel5
#define COM1_DMA_CLK_ENABLE() __HAL_RCC_DMA1_CLK_ENABLE()
#define COM1_DMA_IRQ DMA1_Channel5_IRQn
#define COM1_IRQ_HANDLE DMA1_Channel5_IRQHandler
extern UART_HandleTypeDef com1_handle;
/***********************************************************串口2相关宏定义*******************************************************/
#define USE_COM2_ENABLE (0)
#define USE_COM2_IRQ_ENABLE (0) // 串口2中断使能
#define USE_COM2_DMA_RX_ENABLE (0) // 串口1 DMA RX 使能

/**@details 引脚定义*/
#define COM2_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define COM2_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define COM2_TX_PIN GPIO_PIN_2
#define COM2_RX_PIN GPIO_PIN_3
#define COM2_TX_PORT GPIOA
#define COM2_RX_PORT GPIOA

#define COM2_IRQ_Priority 5 // 抢占优先级
#define COM2_IRQ_SubPriority 0 // 响应优先级
#define COM2_DMA_RX_CHANNEL DMA1_Channel6
#define COM2_DMA_CLK_ENABLE() __HAL_RCC_DMA1_CLK_ENABLE()
#define COM2_DMA_IRQ DMA1_Channel6_IRQn
#define COM2_IRQ_HANDLE DMA1_Channel6_IRQHandler
extern UART_HandleTypeDef com2_handle;
/***********************************************************串口3相关宏定义*******************************************************/
#define USE_COM3_ENABLE (0)
#define USE_COM3_IRQ_ENABLE (1) // 串口3中断使能
#define USE_COM3_DMA_RX_ENABLE (1) // 串口3 DMA RX 使能
#define COM3_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
#define COM3_TX_PORT GPIOD
#define COM3_TX_PIN GPIO_PIN_8
#define COM3_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
#define COM3_RX_PORT GPIOD
#define COM3_RX_PIN GPIO_PIN_9
#define COM3_IRQ_Priority 5 // 抢占优先级
#define COM3_IRQ_SubPriority 0 // 响应优先级
#define COM3_DMA_CLK_ENABLE() __HAL_RCC_DMA1_CLK_ENABLE()
#define COM3_DMA_RX_CHANNEL DMA1_Channel3
#define COM3_DMA_IRQ DMA1_Channel3_IRQn
#define COM3_IRQ_HANDLE DMA1_Channel3_IRQHandler
extern UART_HandleTypeDef com3_handle;
/***********************************************************串口4相关宏定义*******************************************************/
#define USE_COM4_ENABLE (0)
#define USE_COM4_IRQ_ENABLE (1) // 串口4中断使能
#define USE_COM4_DMA_RX_ENABLE (1) // 串口4 DMA RX 使能
#define COM4_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
#define COM4_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
#define COM4_TX_PORT GPIOC
#define COM4_RX_PORT GPIOC
#define COM4_TX_PIN GPIO_PIN_10
#define COM4_RX_PIN GPIO_PIN_11
#define COM4_IRQ_Priority 5 // 抢占优先级
#define COM4_IRQ_SubPriority 0 // 响应优先级
#define COM4_DMA_CLK_ENABLE() __HAL_RCC_DMA2_CLK_ENABLE()
#define COM4_DMA_RX_CHANNEL DMA2_Channel3
#define COM4_DMA_IRQ DMA2_Channel3_IRQn
#define COM4_DMA_IRQ_HANDLE DMA2_Channel3_IRQHandler
extern UART_HandleTypeDef com4_handle;
#endif //STM32_VET6_BSP_SERIAL_DEFINE_H

串口核心文件

头文件(bsp_serial.h)

#ifndef STM32_VET6_BSP_SERIAL_H
#define STM32_VET6_BSP_SERIAL_H

#include "bsp_serial_define.h"
#include "bsp_serial_com1.h"


void Com_Init_01(USART_TypeDef *uart, uint32_t baud);

void Com_Init(UART_HandleTypeDef *comHandle, UART_InitTypeDef *config);

void Com_RegisterCallback(UART_HandleTypeDef *comHandle);

void Com_Dma_Init(DMA_HandleTypeDef *dmaHandle, DMA_InitTypeDef *config);

void UART_MspInit(UART_HandleTypeDef *comHandle);

void UART_MspDeInit(UART_HandleTypeDef *comHandle);

void UART_RxEventCallback(UART_HandleTypeDef *com_handle, uint16_t Pos);

#endif //STM32_VET6_BSP_SERIAL_H

源文件(bsp_serial.c)

#include "bsp_serial.h"

static UART_InitTypeDef init_cnf = {
        .OverSampling = UART_OVERSAMPLING_16,
        .Mode = UART_MODE_TX_RX,
        .HwFlowCtl = UART_HWCONTROL_NONE,
        .Parity = UART_PARITY_NONE,
        .StopBits = UART_STOPBITS_1,
        .WordLength = UART_WORDLENGTH_8B,
        .BaudRate = 9600
};
static DMA_InitTypeDef default_dma_config = {
        .Direction = DMA_PERIPH_TO_MEMORY,
        .PeriphInc = DMA_PINC_DISABLE,
        .MemInc = DMA_MINC_ENABLE,
        .PeriphDataAlignment = DMA_PDATAALIGN_BYTE,
        .MemDataAlignment =DMA_MDATAALIGN_BYTE,
        .Mode = DMA_NORMAL,
        .Priority = DMA_PRIORITY_LOW
};

/**
 * 通用串口初始化
 * @param uart  串口
 * @param baud
 */
void Com_Init_01(USART_TypeDef *uart, uint32_t baud) {
    init_cnf.BaudRate = baud;
    if (uart == NULL) {

    }
#if USE_COM1_ENABLE
    else if (uart == USART1) {
        Com_Init(&com1_handle, &init_cnf);
    }
#endif
#if USE_COM2_ENABLE
    else if (uart == USART2) {
        Sw_Com_Init(&com2_handle, &init_cnf);

    }
#endif
#if USE_COM3_ENABLE
    else if (uart == USART3) {
            Sw_Com_Init(&com3_handle, &init_cnf);
        }
#endif
#if USE_COM4_ENABLE
    else if (uart == UART4) {
        Sw_Com_Init(&com4_handle, &init_cnf);
    }
#endif
}

/**
 * @brief 通用串口初始化
 * @param comHandle
 * @param config
 */
void Com_Init(UART_HandleTypeDef *comHandle, UART_InitTypeDef *config) {
#if USE_HAL_UART_REGISTER_CALLBACKS
    comHandle->MspDeInitCallback = UART_MspDeInit;
    comHandle->MspInitCallback = UART_MspInit;
#endif
    UART_InitTypeDef *ptr = NULL;
    if (config != NULL) {
        ptr = config;
    } else {
        ptr = &init_cnf;
    }
    memcpy(&comHandle->Init, ptr, sizeof(UART_InitTypeDef));
    if (HAL_UART_Init(comHandle) != HAL_OK) {
        common_error_handle(__FILE__, __LINE__);
    }
}

/**
 * @brief 注册接收事件回调
 * @param comHandle
 */
void Com_RegisterCallback(UART_HandleTypeDef *comHandle) {
#if USE_HAL_UART_REGISTER_CALLBACKS
    HAL_UART_RegisterRxEventCallback(comHandle, UART_RxEventCallback);
#endif
}

void UART_MspInit(UART_HandleTypeDef *comHandle) {
#if USE_COM1_ENABLE
    if (comHandle->Instance == USART1) {
        Com1_MspInit();
    }
#endif
#if USE_COM2_ENABLE
    if (comHandle->Instance == USART2) {
        Com2_MspInit();
    }
#endif
#if USE_COM3_ENABLE
    if (comHandle->Instance == USART3) {
        Com3_MspInit();
    }
#endif
#if USE_COM4_ENABLE
    if (comHandle->Instance == UART4) {
        Com4_MspInit();
    }
#endif
}

void UART_MspDeInit(UART_HandleTypeDef *comHandle) {
#if USE_COM1_ENABLE
    if (comHandle->Instance == USART1) {
        Com1_MspDeInit();
    }
#endif
#if USE_COM2_ENABLE
    if (comHandle->Instance == USART2) {
        Com2_MspDeInit();
    }
#endif
#if USE_COM3_ENABLE
    if (comHandle->Instance == USART3) {
        Com3_MspDeInit();
    }
#endif
#if USE_COM4_ENABLE
    if (comHandle->Instance == UART4) {
        Com4_MspDeInit();
    }
#endif
}

/**
 * @brief 串口接收事件
 * @param com_handle
 * @param Pos
 */
void UART_RxEventCallback(UART_HandleTypeDef *com_handle, uint16_t Pos) {
    if (com_handle == NULL) {
        common_error_handle(__FILE__, __LINE__);
    }
#if (USE_COM1_ENABLE == 1)
    else if (com_handle->Instance == USART1) {
        Com1_RxEvent(Pos);
    }
#endif
#if (USE_COM2_ENABLE == 1)
    else if (comHandle->Instance == USART2) {
        Com2_RxEvent(Pos);
    }
#endif
#if (USE_COM3_ENABLE == 1)
    else if (comHandle->Instance == USART3) {
        Com3_RxEvent(Pos);
    }
#endif
#if (USE_COM4_ENABLE == 1)
    else if (comHandle->Instance == UART4) {
        Com4_RxEvent(Pos);
    }
#endif
}

/**
 * 错误回调
 * @param comHandle 串口句柄
 */
void HAL_UART_ErrorCallback(UART_HandleTypeDef *comHandle) {
    switch (comHandle->ErrorCode) {
        case HAL_UART_ERROR_PE:
            __HAL_UART_CLEAR_FLAG(comHandle, UART_FLAG_PE);
            break;
        case HAL_UART_ERROR_NE:
            __HAL_UART_CLEAR_FLAG(comHandle, UART_FLAG_NE);
            break;
        case HAL_UART_ERROR_FE:
            __HAL_UART_CLEAR_FLAG(comHandle, UART_FLAG_FE);
            break;
        case HAL_UART_ERROR_ORE:
            __HAL_UART_CLEAR_FLAG(comHandle, UART_FLAG_ORE);
            break;
    }
    if (comHandle == NULL) {
        common_error_handle(__FILE__, __LINE__);
    }
#if (USE_COM1_ENABLE == 1)
    else if (comHandle->Instance == USART1) {
        Com1_ErrEvent();
    }
#endif
#if (USE_COM2_ENABLE == 1)
    else if (comHandle->Instance == USART2) {
        Com2_ErrEvent();
    }
#endif
#if (USE_COM3_ENABLE == 1)
    else if (comHandle->Instance == USART3) {
        Com3_ErrEvent();
    }
#endif
#if (USE_COM4_ENABLE == 1)
    else if (comHandle->Instance == UART4) {
        Com4_ErrEvent();
    }
#endif
}


/**
 * @brief 统一DMA接口初始化
 * @param dmaHandle
 * @param config
 */
void Com_Dma_Init(DMA_HandleTypeDef *dmaHandle, DMA_InitTypeDef *config) {
    DMA_InitTypeDef *ptr;

    if (config != NULL) {
        ptr = config;
    } else {
        ptr = &default_dma_config;
    }
    memcpy(&dmaHandle->Init, ptr, sizeof(DMA_InitTypeDef));
}

串口1

头文件(bsp_serial_com1.h)

#ifndef STM32_VET6_BSP_SERIAL_COM1_H
#define STM32_VET6_BSP_SERIAL_COM1_H

#include "bsp_serial_define.h"

#if USE_COM1_ENABLE

void Com1_DMA_Init(uint32_t PreemptPriority, uint32_t SubPriority, DMA_InitTypeDef *config);

void Com1_Init(UART_InitTypeDef *config);

void Com1_MspInit(void);

void Com1_MspDeInit(void);

void Com1_DMA_Rx_MspInit(void);

void Com1_DMA_Rx_MspDeInit(void);

void Com1_RxEvent(uint16_t pos);

void Com1_ErrEvent(void);

#endif

#endif //STM32_VET6_BSP_SERIAL_COM1_H

基础源文件(bsp_serial_com1.c)

#include "bsp_serial.h"

UART_HandleTypeDef com1_handle = {.Instance=USART1};


/**
 * @brief Com1初始化
 * @param config
 */
void Com1_Init(UART_InitTypeDef *config) {
    Com_Init(&com1_handle, config);
    // 使用自定义的中断回调
    Com_RegisterCallback(&com1_handle);
}

void Com1_MspInit(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();
    COM1_TX_GPIO_CLK_ENABLE();
    COM1_RX_GPIO_CLK_ENABLE();
    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    GPIO_InitStruct.Pin = COM1_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(COM1_TX_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = COM1_RX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(COM1_RX_PORT, &GPIO_InitStruct);
#if USE_COM1_DMA_RX_ENABLE
    Com1_DMA_Rx_MspInit();
#endif
}

void Com1_MspDeInit(void) {
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();
    HAL_GPIO_DeInit(COM1_TX_PORT, COM1_TX_PIN);
    HAL_GPIO_DeInit(COM1_RX_PORT, COM1_RX_PIN);
#if USE_COM1_DMA_RX_ENABLE
    Com1_DMA_Rx_MspDeInit();
#endif
}

void USART1_IRQHandler(void) {
    HAL_UART_IRQHandler(&com1_handle);
}

扩展串口接收dma(bsp_serial_dma_com1.c)

#include "bsp_serial.h"

DMA_HandleTypeDef com1_dma_rx_handle={
		.Instance=COM1_DMA_RX_CHANNEL,
};

void Com1_DMA_Init(uint32_t PreemptPriority, uint32_t SubPriority, DMA_InitTypeDef *config) {
/* DMA controller clock enable */
	COM1_DMA_CLK_ENABLE();
	/* DMA interrupt init */
	HAL_NVIC_SetPriority(COM1_DMA_IRQ, PreemptPriority, SubPriority);
	HAL_NVIC_EnableIRQ(COM1_DMA_IRQ);
	// com1初始化
    Com_Dma_Init(&com1_dma_rx_handle, config);
}

void Com1_DMA_Rx_MspInit(void) {
	if (HAL_DMA_Init(&com1_dma_rx_handle) != HAL_OK) {
        common_error_handle(__FILE__, __LINE__);
	}
	__HAL_LINKDMA(&com1_handle, hdmarx, com1_dma_rx_handle);
#if USE_COM1_IRQ_ENABLE
	HAL_NVIC_SetPriority(USART1_IRQn, COM1_IRQ_Priority, COM1_IRQ_SubPriority);
	HAL_NVIC_EnableIRQ(USART1_IRQn);
#endif
}

void Com1_DMA_Rx_MspDeInit(void) {
	/*  DMA DeInit */
	HAL_DMA_DeInit(&com1_dma_rx_handle);
	/*  interrupt Deinit */
	HAL_NVIC_DisableIRQ(COM1_DMA_IRQ);
}


void COM1_IRQ_HANDLE(void) {
	/* USER CODE BEGIN DMA1_Channel5_IRQn 0 */
	HAL_DMA_IRQHandler(&com1_dma_rx_handle);
}


/**
 * @brief 参考 @ref HAL_UARTEx_RxEventCallback
 * @param pos
 */
__weak void Com1_RxEvent(uint16_t pos) {
	UNUSED(pos);
}
/**
 * @brief 错误事件
 */
__weak void Com1_ErrEvent(void) {

}



示例

  1. 开启串口中断和DMA接收中断
    在这里插入图片描述
/* 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 <stdbool.h>
#include "main.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"
#include "bsp_serial.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* 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 */
static uint8_t buffer[256];
// 接收数据标志位
static volatile bool rec_data_flag = false;
// 接收数据长度
static volatile uint16_t rec_len = 0;

/**
 * @brief 错误事件
 */
void Com1_ErrEvent(void) {
    rec_len = 0;
    rec_data_flag = false;
    // 重新开启DMA接收
    HAL_UARTEx_ReceiveToIdle_DMA(&com1_handle, buffer, 256);
}

void Com1_RxEvent(uint16_t pos) {
    rec_len = pos;
    rec_data_flag = true;

}

static uint16_t com_rec(void *retBuf) {
    if (rec_data_flag) {
        rec_data_flag = false;
        memcpy(retBuf, buffer, rec_len);
        HAL_UARTEx_ReceiveToIdle_DMA(&com1_handle, buffer, 256);
        return rec_len;
    }
    return 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 */
#if 0
    /* USER CODE END SysInit */

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_USART1_UART_Init();
    /* USER CODE BEGIN 2 */
#endif

    Com1_DMA_Init(5, 0, NULL);
    Com_Init_01(USART1, 9600);
    // 开启串口屏接收数据
    HAL_UARTEx_ReceiveToIdle_DMA(&com1_handle, buffer, 256);
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    uint8_t read_buf[256];
    while (1) {
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
        uint16_t data_len = com_rec(read_buf);
        if (data_len > 0) {
            // todo 解析数据 read_buf
        }
    }
    /* USER CODE END 3 */
}

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

    /** Initializes the RCC Oscillators according to the specified parameters
    * in the RCC_OscInitTypeDef structure.
    */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
    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 */

项目gitee

https://gitee.com/scl_arm/serial_proj.git

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

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

相关文章

Photoshop如何使用选区之实例演示?

文章目录 0.引言1.利用快速选择工具抠图2.制作网店产品优惠券3.利用选区改变眼睛颜色4.抠取复杂的花束5.制作丁达尔光照效果6.利用选区调整图像局部颜色 0.引言 因科研等多场景需要进行绘图处理&#xff0c;笔者对PS进行了学习&#xff0c;本文通过《Photoshop2021入门教程》及…

STM32F103 系统架构

1、Cortex M3 内核 & 芯片 ARM公司提供内核&#xff08;如Cortex M3&#xff0c;简称CM3&#xff0c;下同&#xff09;授权&#xff0c;完整的MCU还需要很多其他 组件。芯片公司&#xff08;ST、NXP、TI、GD、华大等&#xff09;在得到CM3内核授权后&#xff0c;就可以把C…

Linux网络基础二

一.应用层 我们程序员写的一个个解决我们实际问题, 满足我们日常需求的网络程序, 都是在应用层。 二.再谈 "协议" 协议是一种 "约定". socket api的接口, 在读写数据时, 都是按 "字符串" 的方式来发送接收的. 如果我们要传输一些"结构化…

VBA替换中文文献引用出现的et al.和and

问题描述&#xff1a;Endnote是常用的文献管理工具&#xff0c;并提供国标模板Chinese Std GBT7714 (numeric).ens&#xff0c;但Endnote在中英文混排上略欠考虑。Chinese Std GBT7714使用序号的形式&#xff08;******1&#xff09;对文献进行引用&#xff0c;但有时我们需要以…

python毕业设计之django+vue医院医疗救助系统

&#xff08;1&#xff09; 信息发布 当有基金的申请审批通过时&#xff0c;慈善机构信息维护部门应与慈善机构进行对接&#xff0c;保证信息的真实性&#xff0c;信息发布之后患者可以进行相应的基金申请。 &#xff08;2&#xff09; 基金管理 此项功能是保证基金信息的动态刷…

HR员工管理的三重境界:管事、管人、管心

在一个公司里&#xff0c;员工来来往往是常态&#xff0c;虽说我们不能替他们决定&#xff0c;但是一定是与公司的管理者有一定的关系。马云曾经说过&#xff1a;“一个员工离职&#xff0c;不外乎两种原因&#xff0c;一是钱没给到位&#xff1b;二是心里委屈了”。一句话就是…

笔记:计算机网络体系结构(OSI七层模型、TCP/IP五层协议)

计算机网络体系结构 计算机网络是一个复杂的、具有综合性技术的系统&#xff0c;它由计算机系统、通信处理机、通信线路和通信设备、操作系统以及网络协议等组成。为了更好地描述计算机网络结构&#xff0c;使计算机网络系统有条不紊地处理工作&#xff0c;需要定义一种较好的…

2023.04.30 学习周报

文章目录 摘要文献阅读1.题目2.摘要3.介绍4.本文贡献5.数据处理6.模型6.1 look - up操作6.2 LSTM6.3 周期模拟及额外因素 7.实验7.1 数据集7.2 基线7.3 实验表现 8.结论 ISOMAP1.基本思想2.欧氏距离3.折线近似曲线4.计算折线长度5.Floyd-Warshall算法6.ISOMAP算法7.总结 数学建…

Educoder/头歌JAVA——Java Web:基于JSP的网上商城

目录 一、商品列表 本关任务 具体要求 结果输出 实现代码 二、商品详情 本关任务 JDBC查询方法封装 商品相关信息介绍 具体要求 结果输出 实现代码 三、商品搜索 编程要求 测试说明 实现代码 四、购物车列表 本关任务 JDBC查询方法封装 购物车相关信息介绍…

IPsec中IKE与ISAKMP过程分析(主模式-消息4)

IPsec中IKE与ISAKMP过程分析&#xff08;主模式-消息1&#xff09;_搞搞搞高傲的博客-CSDN博客 IPsec中IKE与ISAKMP过程分析&#xff08;主模式-消息2&#xff09;_搞搞搞高傲的博客-CSDN博客 IPsec中IKE与ISAKMP过程分析&#xff08;主模式-消息3&#xff09;_搞搞搞高傲的博客…

Jenkins+Docker+gitee 持续部署spring boot 应用教程

目录 参考安装jenkinsci拉取镜像创建目录安装maven启动镜像配置输入密码安装推荐的插件 创建用户密码配置环境变量安装gitee和dingtalk插件创建SpringBoot并创建Dockfile配置gitee的webhook配置构建shell脚本配置监听gitee webhook触发构建 配置dingtalk钉钉通知 参考 Jenkins…

归纳截图小结

文章目录 web服务器、缓存和PHP加速对比没有做软连接http状态码cookie是什么图形管理界面nginx的访问路径LANM架构redisd服务整体框架免密连接kubeletk8s架构图kubeadm、kubectl、kubelet作用k8s集群token失效时&#xff0c;重新创建tokenk8s网络通信OSI总结pod的理解k8s核心知…

springboot+vue高校实验室预约管理系统

开发环境 开发语言&#xff1a;Java 后端框架&#xff1a;springbootweb 前端框架&#xff1a;vue.js 服务器&#xff1a;tomcat 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 校实验…

K8S集群原理(IT枫斗者)

K8S集群原理&#xff08;IT枫斗者&#xff09; 看图说K8S 先从一张大图来观看一下K8S是如何运作的&#xff0c;再具体去细化K8S的概念、组件以及网络模型。从上图&#xff0c;我们可以看到K8S组件和逻辑及其复杂&#xff0c;但是这并不可怕&#xff0c;我们从宏观上先了解K8S…

【设计模式】责任链模式的设计与示例

前言 责任链模式是一种行为设计模式&#xff0c;执行上它允许请求沿着一条处理链路依次向下传递&#xff0c;每个处理节点都能对当前状态的请求进行处理&#xff0c;满足一定条件后传递给下一个处理节点&#xff0c;亦或者直接结束这一次处理流程。 在现实生产环境中&#xf…

工作流框架研究

工作流框架研究 主流开源框架介绍OsWorkFlowJBPMActivitiFlowableCamundaCamunda 和Flowable对比功能上对比性能上对比 总结 主流开源框架介绍 OsWorkFlow 对于比较简单的流程&#xff0c;OsWorkFlow会是一个比较好的选择&#xff0c;对于复杂的流程就不推荐了&#xff0c;Os…

小 C 的数学(math)

祝大家劳动节快乐&#xff01;&#xff01;小手动起来 言归正传┏ (゜ω゜)☞ 题目描述 小 C 想要成为一名 OIer&#xff0c;于是他提前学习数学&#xff0c;为 OI 做好铺垫。这一天&#xff0c;他的数学老师给了一道题&#xff1a;给定正整数 a&#xff0c;以及给定一个区间 …

Python基础之列表元组

1.列表 序列是Python中最基本的数据结构。序列中的每个元素都分配一个数字 去锁定它的位置&#xff0c;或索引&#xff0c;第一个索引是0&#xff0c;第二个索引是1&#xff0c;依此类推。Python有6个序列的内置类型&#xff0c;但最常见的是列表和元组。序列都可以进行的操作…

HTB-Forge

HTB-Forge 信息收集80端口 立足user -> root 信息收集 80端口 试试上传图片看看有什么限制。 jpg上传成功&#xff0c;并且会给一个随机的文件名存储图片&#xff0c;过了一阵子图片就会被清除。 上传phpinfo后访问界面出现报错。 看来没有执行上传的PHP代码&#xff0…

第43天-DP-第九章 ● 139.单词拆分 ● 关于多重背包,你该了解这些! ● 背包问题总结篇!

文章目录 1. 单词拆分2.多重背包3. 背包总结 1. 单词拆分 s class Solution { public:bool wordBreak(string s, vector<string>& wordDict) {unordered_set<string> wordSet(wordDict.begin(), wordDict.end());// 1. dp[i] 为true代表 可以拆分为一个或者多…