【LM401】USART串口配置过程

  • 1. 板载资源说明
  • 2.uart.c 串口配置文件修改
    • 2.1接口文件 uart_if.c
    • 2.2整体配置流程
      • 2.2.1初始化串口,分配DMA
      • 2.2.2配置串口和DMA中断
  • 3.调试过程分析
  • 4.给出代码
    • 4.1 uart.c
    • 4.2 uart_if.c
    • 4.3 dma.c
  • 5. 串口中断配置
  • 6. 实现接收到回车换行,打印接受完成
  • 7. 实现串口空闲中断+DMA接收不定字长数据
    • 7.1 串口空闲中断+DMA接收不定字长测试

本文主要记录基于 LM401模组的3路串口调试过程,MCU 是 STM32WLE5,主要包括串口IO配置以及DMA中断配置

1. 板载资源说明

LM401 模组是基于 STM32WLE5 系列芯片,模组支持3路串口,其中一路可以配置为低功耗串口。另外还有2路7通道DMA

【普通串口和低功耗串口区别】

USART 可以工作在 Stop 0 1 模式,LPUART1 可以工作在 Stop 0 1 2模式,LPUART1 在匹配 start address 或者 received frame event 时会 产生唤醒中断

板载总线示意图如下:

demo 例程中是用的 usart2,我想用 UASRT1PB6PB7引脚,开始串口的配置过程

2.uart.c 串口配置文件修改

2.1接口文件 uart_if.c

可以用 STM32Cube IDE 开发环境对MCU进行可视化配置,然后生成代码接口,给码农减小了工作量。从下图中可以看出,串口的的接口是 vcom

uart_if.c文件中,找到接口,是一个结构体,结构体成员是函数指针,以下4个函数功能为:

const UTIL_ADV_TRACE_Driver_s UTIL_TraceDriver =
{vcom_Init,         // 初始化串口,并分配相应的 DMA channelvcom_DeInit,          // 串口和DMA的去使能vcom_ReceiveInit,      // 串口接收数据初始化vcom_Trace_DMA,     // 使用 DMA 将databuffer 发送至串口
};

2.2整体配置流程

  • 初始化 uart.c uart_if.c

  • 中断处理函数配置 stm32wlxx_it.c

    • DMA1_Channel1_IRQHandler

    • USART1_IRQHandler

2.2.1初始化串口,分配DMA

【vcom_Init】

其中,EXTI表示(external interrupt/event controller)外部中断控制,请参考博文:【stm32中的外部中断】

UTIL_ADV_TRACE_Status_t vcom_Init(void (*cb)(void *))
{TxCpltCallback = cb;  MX_USART1_UART_Init();  //串口1 参数初始化 MX_DMA_Init();        // 分配 DMALL_EXTI_EnableIT_0_31(LL_EXTI_LINE_27);  // Enable ExtiLine Interrupt request for Lines in range 0 to 31.return UTIL_ADV_TRACE_OK;
}

下面重点分析以下,串口1初始化和分配DMA函数的功能,该功能主要涉及2个函数,在 uart.c 文件中

  • 【MX_USART1_UART_Init()】 【HAL_UART_MspInit()】【HAL_UART_MspDeInit()】 代码在文末

注意:串口DMA选择了 DMA1_Channel1

2.2.2配置串口和DMA中断

dma.c 文件中,配置DMA通道中断,因为选择了 DMA1_Channel1,因此设置中断 DMA1_Channel1_IRQn

void MX_DMA_Init(void)
{/* DMA controller clock enable */__HAL_RCC_DMAMUX1_CLK_ENABLE();__HAL_RCC_DMA1_CLK_ENABLE();/* DMA interrupt init *//* DMA1_Channel5_IRQn interrupt configuration */HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 2, 0);HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}

stm32wlxx_it.c 文件中,设置中断处理函数,设置为: DMA处理来自于串口1的中断请求

// DMA 通道中断
void DMA1_Channel1_IRQHandler(void)
{/* USER CODE BEGIN DMA1_Channel1_IRQn 0 *//* USER CODE END DMA1_Channel1_IRQn 0 */HAL_DMA_IRQHandler(&hdma_usart1_tx);   // DMA处理来自于串口1的中断请求/* USER CODE BEGIN DMA1_Channel1_IRQn 1 *//* USER CODE END DMA1_Channel1_IRQn 1 */
}// 串口中断
void USART1_IRQHandler(void)
{/* USER CODE BEGIN USART1_IRQn 0 *//* USER CODE END USART1_IRQn 0 */HAL_UART_IRQHandler(&huart1);/* USER CODE BEGIN USART1_IRQn 1 *//* USER CODE END USART1_IRQn 1 */
}

3.调试过程分析

以下是调试成功之后的打印信息,但是在调试过程中遇到过以下问题, ****************************是初始化时打印的第一条信息

【问题1:只打印第一条信息,以后的消息不打印了】

解决: DMA 通道配置错误,造成无法正确执行

4.给出代码

4.1 uart.c


/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"/* USER CODE BEGIN 0 *//* USER CODE END 0 */UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_tx;/* USART1 init function */void MX_USART1_UART_Init(void)
{huart1.Instance = USART1;huart1.Init.BaudRate = 115200;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK){Error_Handler();}if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK){Error_Handler();}if (HAL_UARTEx_EnableFifoMode(&huart1) != HAL_OK){Error_Handler();}
}void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};if(uartHandle->Instance==USART1){/** Initializes the peripherals clocks*/PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART1;PeriphClkInitStruct.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK){Error_Handler();}/* USART1 clock enable */__HAL_RCC_USART1_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/**USART1 GPIO ConfigurationPB7     ------> USART1_RXPB6     ------> USART1_TX*/GPIO_InitStruct.Pin = USARTx_RX_Pin|USARTx_TX_Pin;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF7_USART1;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);/* USART1 DMA Init *//* USART1_TX Init */hdma_usart1_tx.Instance = DMA1_Channel1;hdma_usart1_tx.Init.Request = DMA_REQUEST_USART1_TX;hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;hdma_usart1_tx.Init.Mode = DMA_NORMAL;hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK){Error_Handler();}__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);/* USART1 interrupt Init */HAL_NVIC_SetPriority(USART1_IRQn, 2, 0);HAL_NVIC_EnableIRQ(USART1_IRQn);}
}void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspDeInit 0 *//* USER CODE END USART1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_USART1_CLK_DISABLE();/**USART1 GPIO ConfigurationPB7     ------> USART1_RXPB6     ------> USART1_TX*/HAL_GPIO_DeInit(GPIOB, USARTx_RX_Pin|USARTx_TX_Pin);/* USART1 DMA DeInit */HAL_DMA_DeInit(uartHandle->hdmatx);/* USART1 interrupt Deinit */HAL_NVIC_DisableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspDeInit 1 *//* USER CODE END USART1_MspDeInit 1 */}
}/* USER CODE BEGIN 1 *//* USER CODE END 1 */

4.2 uart_if.c

/* Includes ------------------------------------------------------------------*/
#include "usart_if.h"/* USER CODE BEGIN Includes *//* USER CODE END Includes *//* External variables ---------------------------------------------------------*/
/*** @brief DMA handle*/
extern DMA_HandleTypeDef hdma_usart1_tx;/*** @brief UART handle*/
extern UART_HandleTypeDef huart1;/*** @brief buffer to receive 1 character*/
uint8_t charRx;/* USER CODE BEGIN EV *//* USER CODE END EV *//* Private typedef -----------------------------------------------------------*/
/*** @brief Trace driver callbacks handler*/
const UTIL_ADV_TRACE_Driver_s UTIL_TraceDriver =
{vcom_Init,vcom_DeInit,vcom_ReceiveInit,vcom_Trace_DMA,
};/* 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 ---------------------------------------------------------*/
/*** @brief  TX complete callback* @return none*/
static void (*TxCpltCallback)(void *);
/*** @brief  RX complete callback* @param  rxChar ptr of chars buffer sent by user* @param  size buffer size* @param  error errorcode* @return none*/
static void (*RxCpltCallback)(uint8_t *rxChar, uint16_t size, uint8_t error);/* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*//* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Exported functions --------------------------------------------------------*/UTIL_ADV_TRACE_Status_t vcom_Init(void (*cb)(void *))
{TxCpltCallback = cb; MX_USART1_UART_Init();MX_DMA_Init();LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_26);return UTIL_ADV_TRACE_OK;
}UTIL_ADV_TRACE_Status_t vcom_DeInit(void)
{/* USER CODE BEGIN vcom_DeInit_1 *//* USER CODE END vcom_DeInit_1 *//* ##-1- Reset peripherals ################################################## */__HAL_RCC_USART1_FORCE_RESET();__HAL_RCC_USART1_RELEASE_RESET();/* ##-2- MspDeInit ################################################## */HAL_UART_MspDeInit(&huart1);/* ##-3- Disable the NVIC for DMA ########################################### *//* USER CODE BEGIN 1 */HAL_NVIC_DisableIRQ(DMA1_Channel5_IRQn);return UTIL_ADV_TRACE_OK;/* USER CODE END 1 *//* USER CODE BEGIN vcom_DeInit_2 *//* USER CODE END vcom_DeInit_2 */
}void vcom_Trace(uint8_t *p_data, uint16_t size)
{/* USER CODE BEGIN vcom_Trace_1 *//* USER CODE END vcom_Trace_1 */HAL_UART_Transmit(&huart1, p_data, size, 1000);/* USER CODE BEGIN vcom_Trace_2 *//* USER CODE END vcom_Trace_2 */
}UTIL_ADV_TRACE_Status_t vcom_Trace_DMA(uint8_t *p_data, uint16_t size)
{/* USER CODE BEGIN vcom_Trace_DMA_1 *//* USER CODE END vcom_Trace_DMA_1 */HAL_UART_Transmit_DMA(&huart1, p_data, size);return UTIL_ADV_TRACE_OK;/* USER CODE BEGIN vcom_Trace_DMA_2 *//* USER CODE END vcom_Trace_DMA_2 */
}UTIL_ADV_TRACE_Status_t vcom_ReceiveInit(void (*RxCb)(uint8_t *rxChar, uint16_t size, uint8_t error))
{/* USER CODE BEGIN vcom_ReceiveInit_1 *//* USER CODE END vcom_ReceiveInit_1 */UART_WakeUpTypeDef WakeUpSelection;/*record call back*/RxCpltCallback = RxCb;/*Set wakeUp event on start bit*/WakeUpSelection.WakeUpEvent = UART_WAKEUP_ON_STARTBIT;HAL_UARTEx_StopModeWakeUpSourceConfig(&huart1, WakeUpSelection);/* Make sure that no UART transfer is on-going */while (__HAL_UART_GET_FLAG(&huart1, USART_ISR_BUSY) == SET);/* Make sure that UART is ready to receive)   */while (__HAL_UART_GET_FLAG(&huart1, USART_ISR_REACK) == RESET);/* Enable USART interrupt */__HAL_UART_ENABLE_IT(&huart1, UART_IT_WUF);/*Enable wakeup from stop mode*/HAL_UARTEx_EnableStopMode(&huart1);/*Start LPUART receive on IT*/HAL_UART_Receive_IT(&huart1, &charRx, 1);return UTIL_ADV_TRACE_OK;/* USER CODE BEGIN vcom_ReceiveInit_2 *//* USER CODE END vcom_ReceiveInit_2 */
}void vcom_Resume(void)
{/* USER CODE BEGIN vcom_Resume_1 *//* USER CODE END vcom_Resume_1 *//*to re-enable lost UART settings*/if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}/*to re-enable lost DMA settings*/if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK){Error_Handler();}/* USER CODE BEGIN vcom_Resume_2 *//* USER CODE END vcom_Resume_2 */
}void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{/* USER CODE BEGIN HAL_UART_TxCpltCallback_1 *//* USER CODE END HAL_UART_TxCpltCallback_1 *//* buffer transmission complete*/if (huart->Instance == USART1){TxCpltCallback(NULL);}/* USER CODE BEGIN HAL_UART_TxCpltCallback_2 *//* USER CODE END HAL_UART_TxCpltCallback_2 */
}void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{/* USER CODE BEGIN HAL_UART_RxCpltCallback_1 *//* USER CODE END HAL_UART_RxCpltCallback_1 */if (huart->Instance == USART1){if ((NULL != RxCpltCallback) && (HAL_UART_ERROR_NONE == huart->ErrorCode)){RxCpltCallback(&charRx, 1, 0);}HAL_UART_Receive_IT(huart, &charRx, 1);}/* USER CODE BEGIN HAL_UART_RxCpltCallback_2 *//* USER CODE END HAL_UART_RxCpltCallback_2 */
}

4.3 dma.c

#include "dma.h"void MX_DMA_Init(void)
{/* DMA controller clock enable */__HAL_RCC_DMAMUX1_CLK_ENABLE();__HAL_RCC_DMA1_CLK_ENABLE();/* DMA interrupt init *//* DMA1_Channel5_IRQn interrupt configuration */HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 2, 0);HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);}

5. 串口中断配置

STM32CubeMX实现串口DMA中断通信

HAL_UART_MspInit使能中断,设置

HAL_UART_MspInit(){xxxxxxx;HAL_NVIC_SetPriority(USART1_IRQn, 1, 0);HAL_NVIC_EnableIRQ(USART1_IRQn);
}

MX_USART1_UART_Init串口初始化函数中,设置使能接收中断

void MX_USART1_UART_Init(void){/* USER CODE BEGIN USART1_Init 2 */__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);HAL_UART_Receive_IT(&huart1, (uint8_t *)&g_rev_uart3_buffer, 1);/* USER CODE END USART1_Init 2 */
}

USART1_IRQHandler 中断服务函数:

void USART2_IRQHandler(void)
{HAL_UART_IRQHandler(&huart2);HAL_UART_Transmit(&huart1, (uint8_t *)&g_rev_uart3_buffer, 1,1000);HAL_UART_Receive_IT(&huart1, (uint8_t *)&g_rev_uart3_buffer, 1);
}

6. 实现接收到回车换行,打印接受完成

使用串口1 pb6 pb7

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{/* USER CODE BEGIN HAL_UART_RxCpltCallback_1 */static uint8_t Uart1_Rx_Cnt = 0;static uint8_t Uart1_RxBuff[255];/* USER CODE END HAL_UART_RxCpltCallback_1 */if (huart->Instance == USART2){if ((NULL != RxCpltCallback) && (HAL_UART_ERROR_NONE == huart->ErrorCode)){RxCpltCallback(&charRx, 1, 0);}HAL_UART_Receive_IT(huart, &charRx, 1);}/* USER CODE BEGIN HAL_UART_RxCpltCallback_2 */if (huart->Instance == USART1){if(Uart1_Rx_Cnt >= 255){Uart1_Rx_Cnt = 0;memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff));}else{Uart1_RxBuff[Uart1_Rx_Cnt] = g_rev_uart1_buffer[0];Uart1_Rx_Cnt++;if((Uart1_RxBuff[Uart1_Rx_Cnt-1] == 0x0A)&&(Uart1_RxBuff[Uart1_Rx_Cnt-2] == 0x0D))  // 收到回车换行{HAL_UART_Transmit(&huart1,Uart1_RxBuff,Uart1_Rx_Cnt,1000);Uart1_Rx_Cnt= 0;//bRx1_complete = 0;APP_PRINTF("recive success \r\n");}}HAL_UART_Receive_IT(huart, (uint8_t *)&g_rev_uart1_buffer, 1);}/* USER CODE END HAL_UART_RxCpltCallback_2 */
}

7. 实现串口空闲中断+DMA接收不定字长数据

  1. 在 MX_USART1_UART_Init 函数中开启 DMA 接收中断。

  2. 在 uart.c 中定义 接收缓冲区的长度

  3. 在 stm32wlxx_it.c 中写中断服务函数

int joinIsrCNT= 0;
/*** @brief This function handles USART1 Interrupt.*/
void USART1_IRQHandler(void)
{/* USER CODE BEGIN USART1_IRQn 0 */uint8_t datalen = DMA_DataLength;volatile uint32_t dmaNotransCnt = 0;uint32_t temp = 0;if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) != RESET){ __HAL_UART_CLEAR_IDLEFLAG(&huart1);////temp = huart1.Instance->ISR;//temp = huart1.Instance->RDR;HAL_UART_DMAStop(&huart1); dmaNotransCnt =__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 获取DMA中未传输的数据个数rx_len =  datalen - dmaNotransCnt; // 总计数减去未传输的数据个数,得到/此次接收到的数据个数//rx_len = hdma_usart1_rx.Instance->CNDTR;  // 测试zyhrecv_end_flag = 1;joinIsrCNT++;}/* USER CODE END USART1_IRQn 0 */HAL_UART_IRQHandler(&huart1);/* USER CODE BEGIN USART1_IRQn 1 */if(recv_end_flag ==1){HAL_UART_Transmit(&huart1,uart1_Dma_reciveData, rx_len,0xffff);rx_len=0;recv_end_flag=0;}HAL_UART_Receive_DMA(&huart1, uart1_Dma_reciveData,DMA_DataLength);//再次开启DMA接收/* USER CODE END USART1_IRQn 1 */
}

7.1 串口空闲中断+DMA接收不定字长测试

设置缓冲区大小为200,发送30个字节数据
下图变量,datalen表示缓冲区大小200
dmaNotransCnt 表示DMA缓冲区还有多少字节的空间(200-30 =170)
rx_len 表示本次接收到的字节长度30


100ms 一次接收中断数据

参考大佬博客:
STM32 UART 串口中断配置—基于 STM32CubeMX

STM32 HAL CubeMX 串口IDLE接收空闲中断+DMA

STM32串口接收中断——基于HAL库

【LM401】USART串口配置过程 uart.c 代码解析相关推荐

  1. cubemx stm32 配置两个串口_STM32CubeMX的串口配置,以及驱动代码

    1.STM32CubeMX的配置没啥子好说的,使能然后改一下波特率和字长,然后在将中断勾选,把中断等级调到1(一定要比systick的优先级垃圾!!!) 2.驱动代码 在生成的it.c文件中,例如用的 ...

  2. mysql的优化器执行过程(附代码解析,手动注释等)

    一.前言 这篇文章的诞生很偶然,优化器大家基本都听过,感觉就是只要自己不能理解的东西,都归于mysql优化器就完事了,哈哈.但是优化器到底是什么呢,执行过程是什么样子的呢?博主是在看一篇博文的时候,看 ...

  3. STM32CubeMX实现USART串口通信

    文章目录 一.实验环境 二.STM32CubeMX的安装 三.使用STM32CubeMX完成串口通信 1. 安装固件库 2.工程设置 四.USART串口通信 1. UART函数库介绍 2.代码编写 3 ...

  4. PIC单片机学习—USART串口

    PIC单片机学习-USART串口 最近做了几个项目都用到了PIC单片机,在这几个项目之前我只用到了51单片机和STM32来做控制类的项目,用PIC单片机的时候发现使用的时候和51单片机还是有所区别,有 ...

  5. DBNet++(TPAMI) 原理与代码解析

    paper:Real-Time Scene Text Detection with Differentiable Binarization and Adaptive Scale Fusion code ...

  6. 串口接收中断配置过程---STM32F4--HAL

    串口接收中断程序配置过程(HAL) 初始化相关参数,使能串口: HAL_UART_Init(); 该函数的参数是串口的基址,在stm32f429xx.h文件中,定义了8个UART_HandleType ...

  7. php什么设置前端代码,代码编辑器与PHPSTUDY的安装与配置过程(前端第一课)

    前端第一课:编辑器与PHPSTUDY的安装与配置过程 编辑器安装过程 1.Visual Studio Code 官网下载软件,解压下载文件,打开安装程序安装至你的计算机. 2.安装"Chin ...

  8. 浅谈STM32 USART串口中断配置函数USART_ITConfig()的编程思路

    void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState) 函数参数列表中,USAR ...

  9. 树莓派4B ubuntu20.04 UART 多串口配置通信

    相比树莓派0.1.2 以及 3 的双串口 UART0(PL011)和 UART1(mini UART),树莓派 4 中新增了 4 个 PL011 串口共计有 6 个 UART,整理此笔记用作记录和配置 ...

最新文章

  1. [CVPR 2016] Weakly Supervised Deep Detection Networks论文笔记
  2. js类数组转数组的方法(ArrayLike)
  3. 人工智能伦理体系:基础架构与关键问题
  4. 同一接口有多个实现类,怎么来注入一个指定的实现?@Resource、@Autowired、@Qualifier
  5. socket 请求Web服务器过程
  6. 随记:我们需要怎样的数学教育?
  7. 中美共建大数据创新研究中心
  8. 《linux核心应用命令速查》连载二:lastcomm:显示以前使用过的命令的信息
  9. 用批量重命名技巧把文件夹下多个文件快速重命名
  10. 天正双击墙体不能编辑_【盘点】CAD、天正、Ps 快捷键最全汇总!
  11. 100条历史典故,读懂半个中国
  12. 阳历和阴历的互转函数
  13. 针对不同场景的Python合并多个Excel方法
  14. 交叉验证stratified k-fold cv与shuffle等常用cv方法
  15. PCIe传输速率和有效带宽计算方式
  16. Bugku-CTF (web 持续更新) ——新手ctf记录
  17. Viper的使用方法
  18. 微信程序开发之微信接入
  19. QGC 地面站中获取电压完整教程(QGC中无法获取APM电压)
  20. linux中如何压缩目录文件,在Linux中,如何压缩文件和目录

热门文章

  1. 数据结构 - 决策树(分类)
  2. 文明6怎么修改计算机用户名,文明6领袖特性修改教程 文明6怎么修改领袖特性...
  3. mysql日志满如何清理_mysql 日志爆满,删除日志文件,定时清理日志
  4. 栅格化布局的简单示例
  5. 如何刻录能够自动播放的DVD光盘
  6. internet时间同步服务器地址
  7. 跟着骆大神了解进程线程
  8. 如何用社交电商来解决企业痛点
  9. (附源码)ssm基于角色访问控制的文件共享系统 毕业设计161821
  10. Java对象的序列化和反序列化