【STM32+HAL库+CubeMX】UART轮询收发、中断收发、DMA收发方法及空闲中断详解

news2024/10/7 10:17:39

(转载)原文链接:https://blog.csdn.net/qq_39344192/article/details/131470735

1. 什么是UART?

UART是一种异步串行通信接口,常用于通过串口与外部设备进行通信。它通过发送和接收数据帧来实现数据传输,使用起来相对简单。UART通常包含发送器(Transmitter)和接收器(Receiver),通过两根信号线(传输线)进行双向通信。

2. UART协议内容简介

image

UART协议将一长串数据切成很多固定长度的小段,分别发送。每小段数据前后会加上一些附加数据以保证通信的实时性和准确性,最后形成的每个小段叫做一个数据包——即1帧数据。

  • 起始位:发出1位低电平信号,表示开始传输字符。
  • 数据位:真正发送的数据,一般为8位(1个字节),常采用ASCII编码,从最低位开始发送。
  • 校验位:用于检验接收到的数据是否正确,分为奇校验和偶校验。
  • 停止位:一组数据的结束传输的标志。可以是1位、1.5位、2位的高电平。
  • 空闲位:空闲时数据线为高电平状态,代表无数据传输。
  • 波特率:衡量传输速率的指标。UART通信中波特率等于比特率。

UART通信的两个设备间,以上因素必须完全一致才能实现数据通信。

3. UART轮询收发

UART轮询收发时,CPU会不断检测串口的状态位来判断数据收发的情况。

3.1 UART轮询收发的优缺点

UART轮询收发是一种简单直接的UART通信方式,它具有以下优点和缺点:

优点

  • 简单易实现:相比于中断或DMA方式进行数据收发,UART轮询收发的实现相对简单,不需要额外配置中断或DMA控制器,减少了开发的复杂性。
  • 低延迟:由于没有中断处理程序的介入和数据传输的等待时间,UART轮询收发可以实现较低的延迟,对实时性要求较高的应用场景较为适用。占用CPU资源,效能低:UART轮询收发需要通过不断的轮询来检查发送和接收缓冲区的状态,这会占用CPU的资源,导致CPU无法充分利用来执行其他任务。

缺点

  • 占用CPU资源,效能低:UART轮询收发需要通过不断的轮询来检查发送和接收缓冲区的状态,这会占用CPU的资源,导致CPU无法充分利用来执行其他任务。

UART轮询收发适用于简单的、对实时性要求不高的低速通信场景。但在对实时性、效率和灵活性要求较高的应用中,中断或DMA方式可能更加适合。在选择UART通信方式时,需要根据具体应用需求进行权衡和选择。

3.2 UART轮询收发相关的函数

初始化UART参数:首先,需要对UART进行初始化,包括波特率(Baud rate)、数据位数、校验位、停止位等参数的设置。这些参数决定了数据的传输格式。

初始化函数HAL_UART_Init(UART_HandleTypeDef *huart);
功能根据串口句柄指定的参数进行串口初始化。
入口参数huart:串口句柄的地址指针。
返回值HAL状态值。
说明使用CubeMX配置工程时,初始化代码会自动生成,我们不需要再对串口进行初始化。

发送数据:要发送数据,首先将待发送的数据写入UART发送缓冲区,然后调用轮询发送函数。在轮询方式下,单片机会一直检查是否完成发送,直到超过设定时间或数据发送完成。

轮询发送函数HAL_UART_Transmit(UART_Handle TypeDef *huart, uint 8_t *pData, uint 16_t Size, uint 32_t Timeout);
功能在轮询方式下发送一定数量的数据。
入口参数huart:串口句柄的地址。
pData:待发送数据的首地址。
Size:发送的字节数。
Timeout:超时等待时间, 以毫秒为单位。
返回值HAL状态值。

接收数据:要接收数据,需要从UART接收缓冲区读取数据。同样,在轮询方式下,单片机会一直检查是否完成接收,直到超过设定时间或接收到所有数据。

轮询接收函数HAL_UART_Receive(UART_Handle TypeDef *huart, uint 8_t *pData, uint 16_t Size, uint 32_t Timeout);
功能在轮询方式下接收一定数量的数据。
入口参数huart:串口句柄的地址。
pData:存放数据的首地址。
Size:接收数据的字节数。
Timeout:超时等待时间, 以毫秒为单位。
返回值HAL状态值。

3.3 【实践】使用蓝牙模块发送数据

使用UART协议,向手机循环发送“Hello World”语句。

3.3.1 配置UART

image

  1. 左侧connectivity中点击USART1。
  2. 右侧Mode,选择为Asynchronous(异步通信)
  3. 配置参数:
  • Baud Rate(波特率):9600Bits/s
  • Word Length(字长):8 Bits
  • Parity(奇偶校验位):无校验位
  • Stop Bits(停止位):1位

USART包括UART与USRT。我们使用USART的UART模式,即Asynchronous。

3.3.2 连接单片机与蓝牙模块
单片机蓝牙模块
RXTX
TXRX
5VVCC
GNDGND
3.3.3 代码实现

在main.c中添加如下语句:

/* 添加至引用区 */
#include "string.h" // strlen函数依赖该头文件
/* 添加至变量定义区*/
char txBuffer[] = "Hello World"; // 需要发送的数据
/* 写在main()的while(1)循环内 */
while(1)
{
    HAL_UART_Transmit(&huart1, (uint8_t *)txBuffer, strlen(txBuffer), 1000);
    HAL_Delay(1000);
}

4. UART中断收发

4.1 UART中断收发的优缺点

优点

  • 提高系统效率:相比于UART轮询收发方式,UART中断收发可以提高系统的效率。当每完成发送或接收一帧数据时,中断会通知CPU进行相应的处理,而不需要CPU不断地轮询发送或接收缓冲区,释放了CPU资源,使CPU可以同时执行其他任务;
  • 系统响应更快:通过使用中断机制,UART中断收发可以提供更快的系统响应时间。一旦有数据可发送或可接收时,中断立即触发,通知CPU进行相应操作,减少了数据传输的延迟。
  • 灵活性:UART中断收发具有较高的灵活性。中断处理程序可以对数据进行灵活的处理和控制,可以根据实际需求进行相应的操作,如解析数据、执行特定任务等。复杂性增加:相对于UART轮询收发方式,UART中断收发的实现相对复杂一些。需要正确配置中断触发条件和中断优先级,同时编写中断处理程序进行数据的发送和接收操作。

缺点

  • 中断开销:中断处理程序的执行会占用一定的CPU时间和系统资源。频繁的中断触发可能会增加系统的开销。
  • 实时性限制:尽管UART中断收发可以提高系统的响应时间,但它仍然受限于中断处理程序的执行时间和优先级。在高实时性要求的应用中,中断处理程序的执行时间必须保持足够短,以确保数据的及时处理和传输。
  • 占用CPU资源:在传输数据量较大时,如果采用中断方式,每收发一帧的数据,CPU都会被打断,造成CPU无法处理其他事务。因此在批量数据传输,通信波特率较高时,建议采用DMA方式。

UART中断收发相较于UART轮询收发,提高了系统的效率,但是遇到大量、高速的数据传输时仍然会对CPU的性能产生影响。

4.2 UART中断收发时触发中断的流程

image

使能中断后,每收发1帧数据后,UART会触发UART全局中断。此时程序会进入到中断处理函数 USART1_IRQHandler()。在这个函数中,又调用了HAL库的中断处理函数HAL_UART_IRQHandler(&huart1),该函数会通过判断中断类型来决定调用哪个函数。

如果收发完成 -> 进入发送/接收回调函数;
如果产生错误 -> 进入错误回调函数;
如果未收发完 -> 继续发送/接收。

简而言之,每完成一帧数据的收发,都会调用一次中断处理函数,但只有当收发完成时才会调用发送/接收回调函数。在实际操作中,我们一般不需要对中断处理函数HAL_UART_IRQHandler()进行修改。我们将收发完成时的操作逻辑写在回调函数中即可。

4.3 UART中断收发相关的函数

4.3.1 发送相关函数
中断发送函数HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
功能在中断方式下发送一定数量的数据。
入口参数huart:串口句柄的地址。
pData:发送数据的首地址。
Size:发送数据的字节数。
返回值HAL状态值。
发送回调函数HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
功能本函数会在中断发送完成时被调用。
入口参数huart:串口句柄的地址。
返回值
4.3.2 接收相关函数
中断接收函数HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
功能在中断方式下接收一定数量的数据。
入口参数huart:串口句柄的地址。
pData:存放数据的首地址。
Size:接收数据的字节数。
返回值HAL状态值。
接收回调函数HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
功能本函数会在中断接收完成时被调用。
入口参数huart:串口句柄的地址。
返回值

4.4 回调函数的使用方式

stm32f1xx_hal_uart.c文件中,我们可以找到回调函数的声明方式(下以接收回调函数为例)。

image

关注到函数声明前带有__weak修饰,我们一般将这种函数称之为“弱函数”。含有__weak标识的函数,我们可以自行声明一个同名函数,最终编译器在编译的时候会选择我们自己定义的函数。如果我们没有声明该函数,则会调用有__weak修饰的函数。因此,我们只需要在合适的位置自己声明一个回调函数即可,不必在该文件中进行修改。

4.5 【实践】使用中断方式收发数据

通过蓝牙向单片机发送三个英文字母,单片机将大小写翻转后发回。

4.5.1 配置UART

在上一节配置的基础上,我们打开UART1的全局中断。

image

4.5.2 代码实现

我们在main.c中添加如下代码

/* 添加至宏定义区 */
#define rxDataLen 3 //接收三个字节的数据
/* 添加至变量定义区*/
char rxBuffer[rxDataLen]; // 存储接收到的数据的数组

int main()
{
    /* 添加至while(1)循环前*/
    HAL_UART_Receive_IT(&huart1, (uint8_t *)rxBuffer, rxDataLen); // 中断方式接收三个字节数据
    
    while(1) // 注意不要将中断接收写在while循环内
    {
        HAL_Delay(1);
    }
}

在完成一次接收后,我们需要将接收到的字母大小写翻转并输出。我们需要在接收回调函数中实现这一功能,定义接收回调函数如下。

// 接收回调函数(由于需要覆盖原先的弱函数,本函数名称不能更改)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 
{
    if(huart == &huart1) // 如果是串口1
    {
        for(int i = 0; i < rxDataLen; i++)
        {
            if(rxBuffer[i] >= 'a' && rxBuffer[i] <= 'z')
            {
                rxBuffer[i] += 'A' - 'a';
            }
            else if(rxBuffer[i] >= 'A' && rxBuffer[i] <= 'Z')
            {
                rxBuffer[i] -= 'A' - 'a';
            }
        }
        HAL_UART_Transmit_IT(&huart1, (uint8_t *)rxBuffer, rxDataLen);
    }

    // 使用HAL_UART_Receive_IT()时,只会进入一次中断。因此需要在回调函数内再次调用该函数
    HAL_UART_Receive_IT(&huart1, (uint8_t *)rxBuffer, rxDataLen);
}

5. UART使用DMA进行收发 & 空闲中断

5.1 啥是DMA?

DMA(Direct Memory Access,直接内存访问)是一种计算机系统中的数据传输技术,它允许外设直接访问寄存器,而无需通过CPU的干预。DMA技术可以提高数据传输的效率和系统性能,减轻CPU的负担。

简单点来说,DMA收发与轮询、中断都有所不同。在收发数据时,CPU只需告诉DMA数据的来源以及目的地址等信息即可,而无需参与中间的所有传输过程(例如中断收发时每收发一帧数据都会进入中断处理函数,而DMA只在接收完成等少数时刻触发中断,大大降低了CPU的压力)。

5.2 什么是空闲中断?

空闲中断(Idle Interrupt)是UART通信中的一种中断类型。当UART处于空闲状态(没有接收到数据)且持续时间超过一个帧的传输时间时,空闲中断会触发,调用上节提到的函数USART1_IRQHandler。空闲中断可以用于检测数据帧的结束或接收数据的完成。

5.3 相关函数

使能UART的特定中断(宏)__HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__);
参数__HANDLE__:指向UART句柄的指针;
__INTERRUPT__:要使能的中断标志位。
说明本节会使用到空闲中断,即UART_IT_IDLE
DMA发送函数HAL_UART_Transmit_DMA(UART_Handle TypeDef *huart, uint 8_t *pData, uint 16_t Size);
入口参数huart:串口句柄的地址。
pData:发送数据的首地址。
Size:发送数据的字节数。
DMA接收函数HAL_UART_Receive_DMA(UART_Handle TypeDef *huart, uint 8_t *pData, uint 16_t Size);
入口参数huart:串口句柄的地址。
pData:存放数据的首地址。
Size:接收数据的字节数。
禁用DMA传输(宏)__HAL_DMA_DISABLE(_HANDLE_);
参数__HANDLE__:指向UART句柄的指针
使能DMA传输(宏)__HAL_DMA_ENABLE(_HANDLE_);
参数__HANDLE__:指向UART句柄的指针
设置DMA传输计数器值(宏)__HAL_DMA_SET_COUNTER(__HANDLE__, __COUNTER__);
参数__HANDLE__:指向UART句柄的指针
__COUNTER__:要设置的计数器值。
获取DMA传输的计数器值(宏)__HAL_DMA_GET_COUNTER(__HANDLE__);
参数__HANDLE__:指向UART句柄的指针
宏定义#define __HAL_DMA_GET_COUNTER(__HANDLE__) ((__HANDLE__)->Instance->CNDTR)
说明这个宏需要我们自行定义。
我们可以利用这个宏定义来获取接收到的数据的长度。
接收到的数据长度 = 设置的长度 - 当前DMA计数器的值,即
rxLen = rxBufferLen - __HAL_DMA_GET_COUNTER(__HANDLE__);

5.4 【实践】使用DMA & 空闲中断实现不定长数据的接收

结合DMA以及空闲中断,实现接收不定长度的一段数据,发送这一数据的长度。

5.4.1 配置UART

参考前两节,配置好UART以及全局中断。我们还需要开启UART的DMA接收。

5.4.2 代码实现

在本节中,我们将代码按用途划分为不同函数,逐一实现。先定义如下全局变量以及宏变量。

#define rxBufferLen 40 // 接收数据的最大长度
#define __HAL_DMA_SET_COUNTER(__HANDLE__, __COUNTER__) ((__HANDLE__)->Instance->CNDTR = (uint16_t)(__COUNTER__))
char rxBuffer[rxBufferLen]; // 用于存放接收到的数据

程序运行之初,我们需要先对DMA接收进行初始化,该初始化函数应当在main()函数内调用一次。

void UART_InitDMAReceive() // 初始化函数
{
    __HAL_UART_CLEAR_IDLEFLAG(&huart1); // 清除空闲中断标志位
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); // 开启UART的空闲中断
    HAL_UART_Receive_DMA(&huart1, (uint8_t*)rxBuffer, rxBufferLen ); // 启动DMA接收
}

每当发生空闲中断或接收到的数据超过缓存区大小时,会产生一次中断。我们首先需要自行编写中断回调函数。

void UART_DMAIdleCallback(UART_HandleTypeDef *huart)
{
    if(huart == &huart1)
    {
        // 停止DMA接收
        __HAL_DMA_DISABLE(huart->hdmarx);
        // 计算接收到的数据长度
        uint8_t dataLen = rxBufferLen - __HAL_DMA_GET_COUNTER(huart->hdmarx) + '0'; 
        // 发送数据长度,使用轮询方法
        HAL_UART_Transmit(&huart1, &dataLen, 1, 10);

        // 重启DMA接收
        __HAL_DMA_SET_COUNTER(huart->hdmarx, rxBufferLen); // 重设DMA计数器
        __HAL_DMA_ENABLE(huart->hdmarx); // 使能DMA接收
    }
}

我们在中断处理函数内添加如下内容(该函数位于文件stm32g4xx_it.c内)。

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 */
    if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET) // 判断中断是否为空闲中断
    {
        __HAL_UART_CLEAR_IDLEFLAG(&huart1); // 清除空闲中断标志位
        UART_DMAIdleCallback(&huart1); // 空闲回调函数
    }
    /* USER CODE END USART1_IRQn 1 */
}

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

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

相关文章

ROS2 Humble学习笔记 (2)

本文发表于个人的github pages。因csdn本身显示插件和转载过程中导致显示不太友好。建议大家阅读原文。想查看完整内容&#xff0c;请移步到ROS2 Humble学习笔记2。 本文篇幅较长&#xff0c;可抽空按照章节阅读。本文只作为对入门教程的一种浮现和提升。 一、前言 在上一篇…

项目02《游戏-08-开发》Unity3D

基于 项目02《游戏-07-开发》Unity3D &#xff0c; 本次任务做物品相互与详情的功能&#xff0c; 首先要做 点击相应&#xff0c; 接下来用接口实现点击相应事件&#xff0c;具体到代码中&#xff0c;我们找到需要响应鼠标事件的对象&#xff0c; 双击PackageCell…

数据结构与算法:图论(邻接表板子+BFS宽搜、DFS深搜+拓扑排序板子+最小生成树MST的Prim算法、Kruskal算法、Dijkstra算法)

前言 图的难点主要在于图的表达形式非常多&#xff0c;即数据结构实现的形式很多。算法本身不是很难理解。所以建议精通一种数据结构后遇到相关题写个转换数据结构的接口&#xff0c;再套自己的板子。 邻接表板子&#xff08;图的定义和生成&#xff09; public class Graph…

c语言实现greedy snake(贪吃蛇)

##第一个小项目 大一学生寒假项目 最终实现效果如图 一.以C语言实现个人小项目 在我们快速学完了一个高级编程语言&#xff0c;就应该写一个小项目来加以巩固自己的学习成果。 所以今天&#xff0c;我们来尝试写一写greedy snake&#xff0c;对于大学生来说也是可以加强能…

超时引发的牛角尖二(hystrix中的超时)

至今我都清楚记得自己负责的系统请求云上关联系统时所报的异常信息。为了解决这个异常&#xff0c;我坚持让这个关联系统的负责人查看&#xff0c;并且毫不顾忌他的嘲讽和鄙视&#xff0c;甚至无视他烦躁的情绪。不过我还是高估了自己的脸皮&#xff0c;最终在其恶狠狠地抛下“…

每日一练:LeeCode-513、找树左下角的值【二叉树】

本文是力扣LeeCode-513、找树左下角的值 学习与理解过程&#xff0c;本文仅做学习之用&#xff0c;对本题感兴趣的小伙伴可以出门左拐LeeCode。 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: …

图数据库(neo4j)在工业控制中的应用

最近看到国外发表的一篇文章&#xff0c;提到将OPC UA 模型映射到neo4j图模型数据库中&#xff0c;通过GraphQL 访问效率很高&#xff0c;顿时感觉自己眼睛一亮&#xff0c;这是一个好主意。 图模型 事物的模型中&#xff0c;除了它自身的某些特征之外&#xff0c;还包括它与其…

第十二讲_JavaScript浏览器对象模型BOM

JavaScript浏览器对象模型BOM 1. 浏览器对象模型介绍2. location2.1 常用的属性2.2 常用的方法 3. navigator3.1 常用的属性 4. history4.1 常用的方法&#xff1a; 5. 本地存储 1. 浏览器对象模型介绍 BOM(Browser Object Model) 是指浏览器对象模型&#xff0c;浏览器对象模…

Unity3D实现坦克大战

一、效果图演示 二、逻辑剖析 从界面上&#xff1a; 需要一个Canvas满屏对着用户&#xff0c;该Canvas上展示用户的游戏数据&#xff0c;比如血条。需要一个Canvas放在蓝色坦克上方&#xff0c;也需要实时对着用户&#xff0c;显示敌人的血条信息两个坦克一个平面Plane放草地…

Nice Touch

Nice Touch是Unity最简单的多点触控输入解决方案,来自Corgi Engine和Infinite Runner Engine的制造商。所有功能完整文档论坛 功能列表: • 超级简单的设置 •兼容Unity的新旧输入系统 • 内置多点触控输入 •适用于所有移动设备 • 虚拟操纵杆 • 动态虚拟操纵杆 • 可重新定…

WebChat——一个开源的聊天应用

Web Chat 是开源的聊天系统&#xff0c;支持一键免费部署私人Chat网页的应用程序。 开源地址&#xff1a;https://github.com/loks666/webchat 目录树 TOC &#x1f44b;&#x1f3fb; 开始使用 & 交流&#x1f6f3; 开箱即用 A 使用 Docker 部署B 使用 Docker-compose…

web前端-------弹性盒子(2)

上一讲我们谈的是盒子的容器实行&#xff0c;今天我们来聊一聊弹性盒子的项目属性&#xff1b; *******************&#xff08;1&#xff09;顺序属性 order属性&#xff0c;用于定义容器中项目的出现顺序。 顺序属性值&#xff0c;为整数&#xff0c;可以为负数&#xff…

由亚马逊云科技 Graviton4 驱动的全新内存优化型实例 Amazon EC2 实例(R8g),现已开放预览

下一代 Amazon Elastic Compute CloudAmazon EC2) 实例的预览版现已公开 提供。全新的 R8g 实例 搭载新式 Graviton4 处理器&#xff0c;其性价比远超任何现有的内存优化实例。对于要求较高的内存密集型工作负载&#xff0c;R8g 实例是不二之选&#xff1a;大数据分析、高性能数…

SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式 基础(持续更新~)

具体操作&#xff1a; day2: 作用&#xff1a; 出现跨域问题 配相对应进行配置即可解决&#xff1a; IDEA连接的&#xff0c;在url最后加参数?useSSLfalse注意链接密码是123&#xff08;docker中mysql密码&#xff09; 注意&#xff0c;虚拟机中设置的密码和ip要和主机上…

代码随想录算法训练营第17天 | 110.平衡二叉树, 257. 二叉树的所有路径 ,404.左叶子之和

二叉树理论基础&#xff1a; https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE 110.平衡二叉树 题目链接&#xff1a;https://leetcode.cn/problems/balanced-binary-tree…

2024最新最详细【接口测试总结】

序章 ​ 说起接口测试&#xff0c;网上有很多例子&#xff0c;但是当初做为新手的我来说&#xff0c;看了不不知道他们说的什么&#xff0c;觉得接口测试&#xff0c;好高大上。认为学会了接口测试就能屌丝逆袭&#xff0c;走上人生巅峰&#xff0c;迎娶白富美。因此学了点开发…

林浩然与杨凌芸的Java奇缘:一场继承大戏

林浩然与杨凌芸的Java奇缘&#xff1a;一场继承大戏 Lin Haoran and Yang Lingyun’s Java Odyssey: A Tale of Inheritance 在一个充满代码香气的午后&#xff0c;我们故事的男主角——林浩然&#xff0c;一个热衷于Java编程的程序员&#xff0c;正在和他的“梦中女神”、同样…

【蓝桥杯选拔赛真题64】python数字塔 第十五届青少年组蓝桥杯python 选拔赛比赛真题解析

python数字塔 第十五届蓝桥杯青少年组python比赛选拔赛真题 一、题目要求 (注:input()输入函数的括号中不允许添加任何信息) 提示信息: 数字塔是由 N 行数堆积而成,最顶层只有一个数,次顶层两个数,以此类推。相邻层之间的数用线连接,下一层的每个数与它上一层左上…

JS第二天、原型、原型链、正则

☆☆☆☆ 什么是原型&#xff1f; 构造函数的prototype 就是原型 专门保存所有子对象共有属性和方法的对象一个对象的原型就是它的构造函数的prototype属性的值。prototype是哪来的&#xff1f;所有的函数都有一个prototype属性当函数被创建的时候&#xff0c;prototype属性…

机器学习超参数优化算法(贝叶斯优化)

文章目录 贝叶斯优化算法原理贝叶斯优化的实现&#xff08;三种方法均有代码实现&#xff09;基于Bayes_opt实现GP优化基于HyperOpt实现TPE优化基于Optuna实现多种贝叶斯优化 贝叶斯优化算法原理 在贝叶斯优化的数学过程当中&#xff0c;我们主要执行以下几个步骤&#xff1a; …