HAL库USART中断接收的相关问题

文章目录

  • 一、使用中断的步骤
  • 二、相关函数分析
    • 1、HAL_UART_IRQHandler
    • 2、UART_Receive_IT
    • 3、HAL_UART_Receive_IT
    • 4、UART_Start_Receive_IT
    • 5、总结
  • 三、HAL库使用心得

一、使用中断的步骤

1、配置GPIO
2、配置USART1
3、设置UART1中断优先级(不开启手动中断,中断由HAL库给好的函数开启)
4、设置USART1中断服务函数(调用HAL给好的中断服务函数)
5、设置回调函数(HAL定义了一个弱函数,需要用户自己重定义)
6、开启USART1接收中断

二、相关函数分析

1、HAL_UART_IRQHandler

在中断服务函数USART1_IRQHandler中调用,进行USART中断的处理。

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

查看函数源码

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
  uint32_t isrflags   = READ_REG(huart->Instance->SR); //#define READ_REG(REG)         ((REG))
  uint32_t cr1its     = READ_REG(huart->Instance->CR1);
  uint32_t cr3its     = READ_REG(huart->Instance->CR3);
  uint32_t errorflags = 0x00U;
  uint32_t dmarequest = 0x00U;

  /* If no error occurs */
  errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
  //USART_SR_PE 32位,PE位为1,其余为0,是一个掩码  #define USART_SR_PE   USART_SR_PE_Msk  
  //  isrflags 时SR的值,与这几位的掩码与,若这些位无置位则结果位0.表示错误位都没有置为,无错误发生
  if (errorflags == RESET)// == 0 无错误
  {
    /* UART in mode Receiver -------------------------------------------------*/
    if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
    {//接收数据寄存器非空 且 接收中断使能
      UART_Receive_IT(huart);//中断接收函数
      return;
    }
  }
//错误发生时
  /* If some errors occur */
  if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET)
                                || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
  {
    /* UART parity error interrupt occurred ----------------------------------*/
    if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
    {
      huart->ErrorCode |= HAL_UART_ERROR_PE;
    }

    /* UART noise error interrupt occurred -----------------------------------*/
    if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
    {
      huart->ErrorCode |= HAL_UART_ERROR_NE;
    }

    /* UART frame error interrupt occurred -----------------------------------*/
    if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
    {
      huart->ErrorCode |= HAL_UART_ERROR_FE;
    }

    /* UART Over-Run interrupt occurred --------------------------------------*/
    if (((isrflags & USART_SR_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET)
                                                 || ((cr3its & USART_CR3_EIE) != RESET)))
    {
      huart->ErrorCode |= HAL_UART_ERROR_ORE;
    }

    /* Call UART Error Call back function if need be --------------------------*/
    if (huart->ErrorCode != HAL_UART_ERROR_NONE)
    {
      /* UART in mode Receiver -----------------------------------------------*/
      if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
      {
        UART_Receive_IT(huart);
      }

      /* If Overrun error occurs, or if any error occurs in DMA mode reception,
         consider error as blocking */
      dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
      if (((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || dmarequest)
      {
        /* Blocking error : transfer is aborted
           Set the UART state ready to be able to start again the process,
           Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
        UART_EndRxTransfer(huart);

        /* Disable the UART DMA Rx request if enabled */
        if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
        {
          ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);

          /* Abort the UART DMA Rx channel */
          if (huart->hdmarx != NULL)
          {
            /* Set the UART DMA Abort callback :
               will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */
            huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError;
            if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
            {
              /* Call Directly XferAbortCallback function in case of error */
              huart->hdmarx->XferAbortCallback(huart->hdmarx);
            }
          }
          else
          {
            /* Call user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
            /*Call registered error callback*/
            huart->ErrorCallback(huart);
#else
            /*Call legacy weak error callback*/
            HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
          }
        }
        else
        {
          /* Call user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
          /*Call registered error callback*/
          huart->ErrorCallback(huart);
#else
          /*Call legacy weak error callback*/
          HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
        }
      }
      else
      {
        /* Non Blocking error : transfer could go on.
           Error is notified to user through user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /*Call registered error callback*/
        huart->ErrorCallback(huart);
#else
        /*Call legacy weak error callback*/
        HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */

        huart->ErrorCode = HAL_UART_ERROR_NONE;
      }
    }
    return;
  } /* End if some error occurs */

  /* Check current reception Mode :
     If Reception till IDLE event has been selected : */
  if ((huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
      && ((isrflags & USART_SR_IDLE) != 0U)
      && ((cr1its & USART_SR_IDLE) != 0U))
  {
    __HAL_UART_CLEAR_IDLEFLAG(huart);

    /* Check if DMA mode is enabled in UART */
    if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
    {
      /* DMA mode enabled */
      /* Check received length : If all expected data are received, do nothing,
         (DMA cplt callback will be called).
         Otherwise, if at least one data has already been received, IDLE event is to be notified to user */
      uint16_t nb_remaining_rx_data = (uint16_t) __HAL_DMA_GET_COUNTER(huart->hdmarx);
      if ((nb_remaining_rx_data > 0U)
          && (nb_remaining_rx_data < huart->RxXferSize))
      {
        /* Reception is not complete */
        huart->RxXferCount = nb_remaining_rx_data;

        /* In Normal mode, end DMA xfer and HAL UART Rx process*/
        if (huart->hdmarx->Init.Mode != DMA_CIRCULAR)
        {
          /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */
          ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE);
          ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);

          /* Disable the DMA transfer for the receiver request by resetting the DMAR bit
             in the UART CR3 register */
          ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);

          /* At end of Rx process, restore huart->RxState to Ready */
          huart->RxState = HAL_UART_STATE_READY;
          huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;

          ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);

          /* Last bytes received, so no need as the abort is immediate */
          (void)HAL_DMA_Abort(huart->hdmarx);
        }

        /* Initialize type of RxEvent that correspond to RxEvent callback execution;
        In this case, Rx Event type is Idle Event */
        huart->RxEventType = HAL_UART_RXEVENT_IDLE;

#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /*Call registered Rx Event callback*/
        huart->RxEventCallback(huart, (huart->RxXferSize - huart->RxXferCount));
#else
        /*Call legacy weak Rx Event callback*/
        HAL_UARTEx_RxEventCallback(huart, (huart->RxXferSize - huart->RxXferCount));
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
      }
      return;
    }
    else
    {
      /* DMA mode not enabled */
      /* Check received length : If all expected data are received, do nothing.
         Otherwise, if at least one data has already been received, IDLE event is to be notified to user */
      uint16_t nb_rx_data = huart->RxXferSize - huart->RxXferCount;
      if ((huart->RxXferCount > 0U)
          && (nb_rx_data > 0U))
      {
        /* Disable the UART Parity Error Interrupt and RXNE interrupts */
        ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));

        /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
        ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);

        /* Rx process is completed, restore huart->RxState to Ready */
        huart->RxState = HAL_UART_STATE_READY;
        huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;

        ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);

        /* Initialize type of RxEvent that correspond to RxEvent callback execution;
           In this case, Rx Event type is Idle Event */
        huart->RxEventType = HAL_UART_RXEVENT_IDLE;

#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /*Call registered Rx complete callback*/
        huart->RxEventCallback(huart, nb_rx_data);
#else
        /*Call legacy weak Rx Event callback*/
        HAL_UARTEx_RxEventCallback(huart, nb_rx_data);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
      }
      return;
    }
  }

  /* UART in mode Transmitter ------------------------------------------------*/
  if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
  {
    UART_Transmit_IT(huart);
    return;
  }

  /* UART in mode Transmitter end --------------------------------------------*/
  if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
  {
    UART_EndTransmit_IT(huart);
    return;
  }
}

2、UART_Receive_IT

中断接收函数,被HAL_UART_IRQHandler 调用

static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
  uint8_t  *pdata8bits;
  uint16_t *pdata16bits;

  /* Check that a Rx process is ongoing */
  if (huart->RxState == HAL_UART_STATE_BUSY_RX)//判断接收过程是否任然在进行
  {
    if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
    {//设置为9位数据而且无校验时的处理
      pdata8bits  = NULL;
      pdata16bits = (uint16_t *) huart->pRxBuffPtr;
      *pdata16bits = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF);
      huart->pRxBuffPtr += 2U;
    }
    else
    {
      pdata8bits = (uint8_t *) huart->pRxBuffPtr;//
      pdata16bits  = NULL;

      if ((huart->Init.WordLength == UART_WORDLENGTH_9B) || ((huart->Init.WordLength == UART_WORDLENGTH_8B) && (huart->Init.Parity == UART_PARITY_NONE)))
      {//设置为8位数据时无校验或9位数据位时的处理
        *pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);//从数据寄存器接收8位数据
      }
      else
      {
        *pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);//从数据寄存器接收7位数据
      }
      huart->pRxBuffPtr += 1U;//buff指针加一
    }

    if (--huart->RxXferCount == 0U)//此时已经接收了最后一位数据 huart->RxXferCount = 1;
    {//关闭所有中断,设置usart1 的句柄的各个标志位
      /* Disable the UART Data Register not empty Interrupt */
      __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);

      /* Disable the UART Parity Error Interrupt */
      __HAL_UART_DISABLE_IT(huart, UART_IT_PE);

      /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
      __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);

      /* Rx process is completed, restore huart->RxState to Ready */
      huart->RxState = HAL_UART_STATE_READY;

      /* Initialize type of RxEvent to Transfer Complete */
      huart->RxEventType = HAL_UART_RXEVENT_TC;

      /* Check current reception Mode :
         If Reception till IDLE event has been selected : */
      if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
      {//开启了空闲中断,关闭空闲中断
        /* Set reception type to Standard */
        huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;

        /* Disable IDLE interrupt */
        ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);

        /* Check if IDLE flag is set */
        if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
        {
          /* Clear IDLE flag in ISR */
          __HAL_UART_CLEAR_IDLEFLAG(huart);
        }
//接收完成,且开启了空闲中断时调用此函数
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /*Call registered Rx Event callback*/
        huart->RxEventCallback(huart, huart->RxXferSize);
#else
        /*Call legacy weak Rx Event callback*/
        HAL_UARTEx_RxEventCallback(huart, huart->RxXferSize);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
      }
      else
      {
        /* Standard reception API called */

//接收完成,没有开启空闲中断时选择处理的回调函数
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        /*Call registered Rx complete callback*/
        huart->RxCpltCallback(huart);
#else
        /*Call legacy weak Rx complete callback*/
        HAL_UART_RxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
      }

      return HAL_OK;
    }
    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}

3、HAL_UART_Receive_IT

判断USART句柄的接收状态,调用UART_Start_Receive_IT 开启中断。

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  /* Check that a Rx process is not already ongoing */
  if (huart->RxState == HAL_UART_STATE_READY)//判断usart状态
  {
    if ((pData == NULL) || (Size == 0U))//判断参数是否有效
    {
      return HAL_ERROR;
    }

    /* Set Reception type to Standard reception */
    huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;//设置接收状态

    return (UART_Start_Receive_IT(huart, pData, Size));//调用接收中断开启函数
  }
  else
  {
    return HAL_BUSY;
  }
}

4、UART_Start_Receive_IT

HAL_StatusTypeDef UART_Start_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  huart->pRxBuffPtr = pData;//缓冲区指针初始化
  huart->RxXferSize = Size;//缓冲区大小初始化
  huart->RxXferCount = Size;//接收数据总大小初始化  会在接收时减小

  huart->ErrorCode = HAL_UART_ERROR_NONE;//错误码设置
  huart->RxState = HAL_UART_STATE_BUSY_RX;//接收状态设置

  if (huart->Init.Parity != UART_PARITY_NONE)
  {
    /* Enable the UART Parity Error Interrupt */
    __HAL_UART_ENABLE_IT(huart, UART_IT_PE);
  }
  //开启错误中断和接收中断
  /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
  __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);

  /* Enable the UART Data Register not empty Interrupt */
  __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);

  return HAL_OK;
}

5、总结

在使用标准库时需要我们先初始化GPIO再初始化USART,然后设置中断优先级并开启中断。在HAL库中,只需要我们初始化GPIO和USART并设置中断优先级,中断的开启和数据的接收都在HAL中封装好了函数,并使用回调函数的方式在接收完成后对数据进行处理。需要注意的是,USART的中断在HAL_UART_Receive_IT中调用UART_Start_Receive_IT开启相关中断,在ISR函数中只需调用HAL_UART_IRQHander函数。每次接收完成后相关的中断都会关闭,需要再次调用HAL_UART_Receive_IT函数开启中断,这也是刚开始用HAL库时常常疑惑的地方,为什么要在初始化时调用一次HAL_UART_Receive_IT函数,在接收完成后的处理函数中要调用HAL_UART_Receive_IT?
当然我们也可以自己调用相关的宏开启中断在ISR中写自己的处理函数,但是这样就不能够调用HAL库提供的函数接收数据了,因为在HAL库中,将外设抽象为句柄,在其中有许多的标志位,我们一旦自己自己调用中断操作后面又使用HAL库的API就会因为外设句柄中的标志位与实际不符而返回错误状态,导致程序卡死。

三、HAL库使用心得

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯(B组)-每日一题

题目&#xff1a; 思路&#xff1a; 首先将所有牛分类 1.a第一头母牛-每年年初生一头小母牛 2.不能生小牛的牛&#xff1a; b1-一岁小母牛 b2-二岁小母牛 b3-三岁小母牛 超过4岁就会再生一头小牛 因此计算每年生的小牛是第一头生的a再加上4岁后的生的 代码实现&#xff1…

deepseek+ollama+anythingLLM搭建本地知识库AI的笔记

所有内容都安装在docker里&#xff0c;安装完ollama后&#xff0c;在其bash里&#xff1a; ollama run deepseek-r1:1.5b 于是就安装好了deepseek, 再安装anythingLLM有点坑&#xff1a; export STORAGE_LOCATION$HOME/anythingllm && \ mkdir -p $STORAGE_LOCATIO…

Python中的json文件操作

1.1 基础知识 什么是JSON&#xff1a;&#xff08;JavaScript Object Notation&#xff09;是一种简洁、易读的数据语言&#xff0c;广泛用于数据交换、文档储存和web开发&#xff1b;适合数据量大&#xff0c;不要求保留原有的数据类型。导入&#xff1a;import json&#xf…

使用JavaScript设计一款简单的数字时钟

本文目录 使用 JavaScript 设计一款带日期显示的数字时钟效果预览1. 项目概述2. HTML 结构代码说明 3. CSS 样式代码说明 4. JavaScript 逻辑代码说明 5. 运行效果 使用 JavaScript 设计一款带日期显示的数字时钟 本文将详细介绍如何使用 HTML、CSS 和 JavaScript 设计一款带日…

PPDock:复旦大学团队研发的蛋白质-配体“盲对接“技术

PPDock: Pocket Prediction-Based Protein−Ligand Blind Docking 发表于Journal of Chemical Information and Modeling&#xff0c;第一作者为 Jie Du&#xff0c;通讯作者为 Manning Wang&#xff0c;研究团队来自复旦大学。该研究提出一种新的基于口袋预测的蛋白质 - 配体盲…

VSCode C/C++ 开发环境完整配置及常见问题(自用)

这里主要记录了一些与配置相关的内容。由于网上教程众多&#xff0c;部分解决方法并不能完全契合我遇到的问题&#xff0c;因此我选择以自己偏好的方式&#xff0c;对 VSCode 进行完整的配置&#xff0c;并记录在使用过程中遇到的问题及解决方案。后续内容也会持续更新和完善。…

系统漏洞扫描服务:安全风险识别与防护指南

系统安全的关键在于漏洞扫描服务&#xff0c;此服务能迅速发现潜在的安全风险。借助专业的扫描工具和技术&#xff0c;它确保系统稳定运作。以下将简要介绍这一服务的主要特点。 扫描原理 系统漏洞扫描服务依赖两种主要手段&#xff1a;一是通过漏洞数据库进行匹配&#xff0…

MVC(Model-View-Controller)framework using Python ,Tkinter and SQLite

1.项目结构 sql: CREATE TABLE IF NOT EXISTS School (SchoolId TEXT not null, SchoolName TEXT NOT NULL,SchoolTelNo TEXT NOT NULL) 整体思路 Model&#xff1a;负责与 SQLite 数据库进行交互&#xff0c;包括创建表、插入、删除、更新和查询数据等操作。View&#xff1…

Xcode证书密钥导入

证书干嘛用 渠道定期会给xcode证书&#xff0c;用来给ios打包用&#xff0c;证书里面有记录哪些设备可以打包进去。 怎么换证书 先更新密钥 在钥匙串访问中&#xff0c;选择系统。(选登录也行&#xff0c;反正两个都要导入就是了)。 mac中双击所有 .p12 后缀的密钥&#xff…

【学习笔记】计算机网络(三)

第3章 数据链路层 文章目录 第3章 数据链路层3.1数据链路层的几个共同问题3.1.1 数据链路和帧3.1.2 三个基本功能3.1.3 其他功能 - 滑动窗口机制 3.2 点对点协议PPP(Point-to-Point Protocol)3.2.1 PPP 协议的特点3.2.2 PPP协议的帧格式3.2.3 PPP 协议的工作状态 3.3 使用广播信…

最新版Edge浏览器集成ActiveX控件之金山WpsDocFrame控件

背景 WpsDocFrame控件‌是由金山公司开发的ActiveX控件&#xff0c;主要用于OA系统中&#xff0c;支持在浏览器中嵌入WPS文档的查看和编辑功能。 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品&#xff0c;致力于将浏览器插件重新应用到所有…

计算机网络结课设计:通过思科Cisco进行中小型校园网搭建

上学期计算机网络课程的结课设计是使用思科模拟器搭建一个中小型校园网&#xff0c;当时花了几天时间查阅相关博客总算是做出来了&#xff0c;在验收后一直没管&#xff0c;在寒假想起来了简单分享一下&#xff0c;希望可以给有需求的小伙伴一些帮助 目录 一、设计要求 二、…

mars3d接入到uniapp的时候ios上所有地图的瓦片都无法加载解决方案

用的是【Mars3d】官网的uniapp的仓库&#xff0c;安卓没有问题&#xff0c;但是ios的不行 相关链接 mars3d-uni-app: uni-app技术栈下的Mars3D项目模板 解决方案&#xff1a;感觉所有图片请求全被拦截了 uniapp的ios内核不允许跨域&#xff0c;需要先把瓦片下载后转base64&…

springboot019高校心理教育辅导

版权声明 所有作品均为本人原创&#xff0c;提供参考学习使用&#xff0c;如需要源码数据库配套文档请移步 www.taobysj.com 搜索获取 技术实现 开发语言&#xff1a;Javavue。 框架&#xff1a;后端spingboot前端vue。 模式&#xff1a;B/S。 数据库&#xff1a;mysql。 开…

基于java手机销售网站设计和实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

基于 GEE 计算研究区年均地表温度数据

目录 1 代码解析 2 完整代码 3 运行结果 1 代码解析 &#xff08;1&#xff09;定义研究区&#xff1a; // 研究区的范围需要自己提前上传 var dataset table;// 将研究区显示在中心&#xff0c;后面的数字为缩放等级&#xff0c;范围从1 - 24 Map.centerObject(dataset,…

VMware Windows_10_x64 安装 VM Tools 后无法将本机文件复制到虚拟机

有一种情况&#xff0c;安装VM Tools死活安装不上去。这时不要急不要慌&#xff0c;重启本机就好了&#xff08;本人情况就是如此&#xff09;。 windows键 R 输入 service.msc 打开服务管理器 找到Virtual Disk服务&#xff0c;选择属性设置为自动&#xff0c;应用后启用服…

python知识和项目经验

一些功能的实现 从.py文件中获取函数对象和参数 的字典 在给定的Python脚本中&#xff0c;通过模块导入和反射机制&#xff0c;如何动态获取包含模型函数的模块中的函数及其默认参数&#xff0c;并构建一个字典以便后续使用&#xff1f; 解决方案 test.py # test.py impor…

Unity下ML-Agents第一个示例

本文写于2025年2月12日&#xff0c;需要提前安装好Anaconda。按文中步骤测试了两次都可正常运行。 一、准备Python端 1.下载并解压 ML-Agents Release 22&#xff08;使用git clone大概率会失败&#xff09; 解压路径为 C:\Users\Administrator&#xff08;Administrator为电…

FastExcel + Java:打造高效灵活的Excel数据导入导出解决方案

作者&#xff1a;后端小肥肠 &#x1f347; 我写过的文章中的相关代码放到了gitee&#xff0c;地址&#xff1a;xfc-fdw-cloud: 公共解决方案 &#x1f34a; 有疑问可私信或评论区联系我。 &#x1f951; 创作不易未经允许严禁转载。 姊妹篇&#xff1a; 基于AOP的数据字典实现…