stm32之GPIO库函数点灯分析

        stm32官方为了方便开发者,利用CubeMX 生成HAL库有关的C代码。HAL库就是硬件抽象层(hardware abstraction layer),生成一系列的函数帮助我们快速生成工程,脱离复杂的寄存器配置。stm32相对于51来功能强大,但是寄存器的数量也不是一个量级,单靠配置寄存器来做项目的话,进度会非常缓慢。但是在学习阶段还是有必要研究一个寄存器配置或者说研究HAL是如何操作寄存器的。

一、利用CubeMX 生成代码

具体怎么操作的这里就不讲解了,网上一大堆。实验用的开发板用的led,一端接到vcc,一端接到PB9(GPIO_B的第9个引脚),当PB9输出低电平时,led就会亮,反之则灭。

生成的工程中,main函数内调用了MX_GPIO_Init函数,这个是GPIO_B_9引脚的初始化。

函数示例如下:

void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOD_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET);/*Configure GPIO pin : PB9 */GPIO_InitStruct.Pin = GPIO_PIN_9;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);}

整个过程就是

  1. 配置__HAL_RCC_GPIOB_CLK_ENABLE时钟,
  2. 配置GPIO_InitTypeDef变量,
  3. GPIO_PIN_9进行reset操作,也是给引脚设置成0
  4. HAL_GPIO_Init进行初始化。

1.1、 GPIO_InitTypeDef类型定义

typedef struct
{uint32_t Pin;       /*!< Specifies the GPIO pins to be configured.This parameter can be any value of @ref GPIO_pins_define */uint32_t Mode;      /*!< Specifies the operating mode for the selected pins.This parameter can be a value of @ref GPIO_mode_define */uint32_t Pull;      /*!< Specifies the Pull-up or Pull-Down activation for the selected pins.This parameter can be a value of @ref GPIO_pull_define */uint32_t Speed;     /*!< Specifies the speed for the selected pins.This parameter can be a value of @ref GPIO_speed_define */
} GPIO_InitTypeDef;

 结构体内部有四个成员变量

  • Pin: 要配置的引脚
  • Mode: 要配置的模式,输入或输出
  • Pull: 配置上拉、下拉或者两者都不
  • Speed:这里的speed暂时有三种模式,low(2MHZ), medium(10MHZ), high(50MHZ),后续会有说明

引脚有两种状态,0或1,定义如下

typedef enum
{GPIO_PIN_RESET = 0u,GPIO_PIN_SET
} GPIO_PinState;

1.2、给GPIOB开启时钟

在stm32中每个片上外设都有对应的时钟,所以在使用时都需要开启。GPIOB时钟开启的代码如下所示

#define __HAL_RCC_GPIOB_CLK_ENABLE()   do { \__IO uint32_t tmpreg; \SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPBEN);\/* Delay after an RCC peripheral clock enabling */\tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPBEN);\UNUSED(tmpreg); \} while(0U)

代码里面就是搞了一个宏进行设置的。其中__IO 也是一个宏,它的类型是volatile,意为“直接存取原始内存地址”。

1.2.1、 SET_BIT是一个宏,作用就是将寄存器的某一个设置成1。
#define SET_BIT(REG, BIT)     ((REG) |= (BIT))

另外所有GPIO是挂载到APB2总线上的,

SET_BIT的第一个参数是APB2ENR,这里就涉及到RCC_APB2ENR寄存器。

 所有外设都需要时钟驱动,这里用到的是GPIO_B, 所以要把RCC_APB2ENR中的第3位置1。

SET_BIT的第二个参数是一个宏

#define RCC_APB2ENR_IOPBEN_Pos               (3U)                              
#define RCC_APB2ENR_IOPBEN_Msk               (0x1UL << RCC_APB2ENR_IOPBEN_Pos)  /*!< 0x00000008 */
#define RCC_APB2ENR_IOPBEN                   RCC_APB2ENR_IOPBEN_Msk            /*!< I/O port B clock enable */

它代表的意思是通过移位将第3位(从0开始数)变成1,其它位都是0。

这样一来 SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPBEN) 代表的意思就是将RCC_APB2ENR寄存器中的第三位置1,也即使能GPIOB。

另外一点是RCC_APB2ENR_IOPBEN寄存器的获取是通过RCC->APB2ENR这种形式。这里又涉及到RCC的问题。

1.2.2、RCC相关寄存器

RCC内部包括一系列和时钟相关的寄存器,当然也包括APB2ENR。RCC是一个宏,我把相关代码集中到一块如下所示

// 所有外设的基址
#define PERIPH_BASE           0x40000000UL /*!< Peripheral base address in the alias region */// 这里AHB的基址
#define AHBPERIPH_BASE        (PERIPH_BASE + 0x00020000UL)// RCC 是挂载到AHB上的
define RCC_BASE              (AHBPERIPH_BASE + 0x00001000UL)// RCC 包括众多寄存器,这里通过C语言的结构体和指针进行操作,将RCC的地址绑定到RCC_BASE
#define RCC                 ((RCC_TypeDef *)RCC_BASE)typedef struct
{__IO uint32_t CR;__IO uint32_t CFGR;__IO uint32_t CIR;__IO uint32_t APB2RSTR;__IO uint32_t APB1RSTR;__IO uint32_t AHBENR;__IO uint32_t APB2ENR;__IO uint32_t APB1ENR;__IO uint32_t BDCR;__IO uint32_t CSR;} RCC_TypeDef

通过上面的操作,就可以利用RCC这个指针来操作各个寄存器,RCC内的变量都是按照寄存器的顺序排列的。这里再强制一点,RCC是挂载到AHB总线上的,所以它的地址是相对AHB总线进行偏移的。

1.2.3、READ_BIT

知道了SET_BIT, 那么READ_BIT也清楚了,采取的操作都差不多,作用就是取出指定的位。

将要取出的位置1,其它位全部是0,这样就取出了指定位。

#define READ_BIT(REG, BIT)    ((REG) & (BIT))

1.3、HAL_GPIO_WritePin 

这个函数的定义如下:

void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
{/* Check the parameters */assert_param(IS_GPIO_PIN(GPIO_Pin));assert_param(IS_GPIO_PIN_ACTION(PinState));if (PinState != GPIO_PIN_RESET){GPIOx->BSRR = GPIO_Pin;}else{GPIOx->BSRR = (uint32_t)GPIO_Pin << 16u;}
}

这里可以看到主要是设置寄存器BSRR。这个函数传入的第一个参数是GPIOB,GPIOB的配置和上面说的RCC采用相似的策略

// 所有外设的基址
#define PERIPH_BASE           0x40000000UL /*!< Peripheral base address in the alias region */// APB2总线基址
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x00010000UL)
// GPIOB总线基址,GPIO是挂载到APB2上的
#define GPIOB_BASE            (APB2PERIPH_BASE + 0x00000C00UL)
// GPIOB 包括众多寄存器,这里通过C语言的结构体和指针进行操作,将GPIOB的地址绑定到GPIOB_BASE
#define GPIOB               ((GPIO_TypeDef *)GPIOB_BASE)typedef struct
{__IO uint32_t CRL;__IO uint32_t CRH;__IO uint32_t IDR;__IO uint32_t ODR;__IO uint32_t BSRR;__IO uint32_t BRR;__IO uint32_t LCKR;
} GPIO_TypeDef;

 BSRR寄存器定义如下:

ODR(端口输出数据寄存器)定义如下:

上面简单来讲

  • 给BSy设置1,ODR对应的位会输出1
  • 给BRy设置1,ODR对应的位会输出0

所以设置将引脚设置成0时需要在BSRR高16位进行操作,输出1 时在BSRR低16位进行操作。

1.4、HAL_GPIO_Init

这里涉及主要的初始化配置,是重中之重。涉及的函数比较多,已经在里面添加了注释。

void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
{//通过这个变量遍历所有的引脚uint32_t position = 0x00u;uint32_t ioposition;uint32_t iocurrent;uint32_t temp;uint32_t config = 0x00u;// __IO uint32_t *configregister; /* Store the address of CRL or CRH register based on pin number */// 引脚的偏移量(每个引脚由CNF和MODE总共4位组成)uint32_t registeroffset;       /* offset used during computation of CNF and MODE bits placement inside CRL or CRH register *//* Check the parameters */assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));assert_param(IS_GPIO_PIN(GPIO_Init->Pin));assert_param(IS_GPIO_MODE(GPIO_Init->Mode));// 判断后续是否还有引脚设置了1while (((GPIO_Init->Pin) >> position) != 0x00u){/* 获取引脚的位置 */ioposition = (0x01uL << position);/* 再次能过Pin获取当前要设置的引脚 */iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition;// 两种方式求得的引脚比较如果相同才进行处理if (iocurrent == ioposition){/* Check the Alternate function parameters */assert_param(IS_GPIO_AF_INSTANCE(GPIOx));/* Based on the required mode, filling config variable with MODEy[1:0] and CNFy[3:2] corresponding bits */// 根据模式来配置configswitch (GPIO_Init->Mode){/* 推挽输出模式 */case GPIO_MODE_OUTPUT_PP:/* Check the GPIO speed parameter */assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));config = GPIO_Init->Speed + GPIO_CR_CNF_GP_OUTPUT_PP;break;/* 开漏输出模式 */case GPIO_MODE_OUTPUT_OD:/* Check the GPIO speed parameter */assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));config = GPIO_Init->Speed + GPIO_CR_CNF_GP_OUTPUT_OD;break;/* 复用推挽模式 */case GPIO_MODE_AF_PP:/* Check the GPIO speed parameter */assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));config = GPIO_Init->Speed + GPIO_CR_CNF_AF_OUTPUT_PP;break;/* 复用开漏输出模式  */case GPIO_MODE_AF_OD:/* Check the GPIO speed parameter */assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));config = GPIO_Init->Speed + GPIO_CR_CNF_AF_OUTPUT_OD;break;/* 下面是输入,要么事件输入要么中断输入 */// 输入悬空case GPIO_MODE_INPUT:// 中断上升沿case GPIO_MODE_IT_RISING:// 中断下降沿case GPIO_MODE_IT_FALLING:// 中断上长或下降沿case GPIO_MODE_IT_RISING_FALLING:// 事件上长沿case GPIO_MODE_EVT_RISING:// 事件下降沿case GPIO_MODE_EVT_FALLING:// 事件上长或下降沿case GPIO_MODE_EVT_RISING_FALLING:/* Check the GPIO pull parameter */assert_param(IS_GPIO_PULL(GPIO_Init->Pull));if (GPIO_Init->Pull == GPIO_NOPULL){config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_FLOATING;}else if (GPIO_Init->Pull == GPIO_PULLUP){config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD;/* Set the corresponding ODR bit */GPIOx->BSRR = ioposition;}else /* GPIO_PULLDOWN */{config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD;/* Reset the corresponding ODR bit */GPIOx->BRR = ioposition;}break;/* 模拟输入 */case GPIO_MODE_ANALOG:config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_ANALOG;break;/* Parameters are checked with assert_param */default:break;}/* Check if the current bit belongs to first half or last half of the pin count numberin order to address CRH or CRL register*//*点灯目前没有用到输入模式,只用到输出模式1、如果当前的引脚是低8位,那就是么对CRL的操作,否则就是对CRH的操作2、如果当前的引脚是低8位,将Postion向左偏移四位,操作的就是当前引脚的MODE和CNF.如果是高8位,将(position - 8u)向左偏移四位,操作的就是当前引脚的MODE和CNF.*/configregister = (iocurrent < GPIO_PIN_8) ? &GPIOx->CRL     : &GPIOx->CRH;registeroffset = (iocurrent < GPIO_PIN_8) ? (position << 2u) : ((position - 8u) << 2u);/* 清除当前引脚的配置,并设置新配置 */MODIFY_REG((*configregister), ((GPIO_CRL_MODE0 | GPIO_CRL_CNF0) << registeroffset), (config << registeroffset));//  由于没有中断这里的操作是可以删除的/*--------------------- EXTI Mode Configuration ------------------------*//* Configure the External Interrupt or event for the current IO */if ((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE){/* Enable AFIO Clock */__HAL_RCC_AFIO_CLK_ENABLE();temp = AFIO->EXTICR[position >> 2u];CLEAR_BIT(temp, (0x0Fu) << (4u * (position & 0x03u)));SET_BIT(temp, (GPIO_GET_INDEX(GPIOx)) << (4u * (position & 0x03u)));AFIO->EXTICR[position >> 2u] = temp;/* Enable or disable the rising trigger */if ((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE){SET_BIT(EXTI->RTSR, iocurrent);}else{CLEAR_BIT(EXTI->RTSR, iocurrent);}/* Enable or disable the falling trigger */if ((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE){SET_BIT(EXTI->FTSR, iocurrent);}else{CLEAR_BIT(EXTI->FTSR, iocurrent);}/* Configure the event mask */if ((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT){SET_BIT(EXTI->EMR, iocurrent);}else{CLEAR_BIT(EXTI->EMR, iocurrent);}/* Configure the interrupt mask */if ((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT){SET_BIT(EXTI->IMR, iocurrent);}else{CLEAR_BIT(EXTI->IMR, iocurrent);}}}position++;}
}

代码相关的解释已经写到注释里了,这里有一个比较有意思的点。

开始是GPIO_Init->Speed设置的是GPIO_SPEED_FREQ_LOW,它其实是一个有关MODE的宏,就是和CNY对应的MODE的宏。

#define GPIO_CRL_MODE0_Pos                   (0U)   // 这个就是50MHZ的输出模式
#define GPIO_CRL_MODE0_Msk                   (0x3UL << GPIO_CRL_MODE0_Pos)      /*!< 0x00000003 */
// 这个就是50MHZ的输出模式
#define GPIO_CRL_MODE0                       GPIO_CRL_MODE0_Msk                /*!< MODE0[1:0] bits (Port x mode bits, pin 0) */
// 这个就是1的输出模式
#define GPIO_CRL_MODE0_0                     (0x1UL << GPIO_CRL_MODE0_Pos)      /*!< 0x00000001 */
// 这个就是2MHZ的输出模式
#define GPIO_CRL_MODE0_1                     (0x2UL << GPIO_CRL_MODE0_Pos)      /*!< 0x00000002 */#define  GPIO_SPEED_FREQ_LOW              (GPIO_CRL_MODE0_1) /*!< Low speed */
#define  GPIO_SPEED_FREQ_MEDIUM           (GPIO_CRL_MODE0_0) /*!< Medium speed */
#define  GPIO_SPEED_FREQ_HIGH             (GPIO_CRL_MODE0)   /*!< High speed */

所以初始化的Speed其实就是设置了MODE。而对于每个输出模式,在HAL_GPIO_Init函数里都用到这样的操作

// 低二位都是0,为了配合Mode
#define  GPIO_CR_CNF_GP_OUTPUT_PP   0x00000000u /*!< 00: General purpose output push-pull  */
// 低二位都是0,为了配合Mode
#define  GPIO_CR_CNF_GP_OUTPUT_OD   0x00000004u /*!< 01: General purpose output Open-drain  */
// 低二位都是0,为了配合Mode
#define  GPIO_CR_CNF_AF_OUTPUT_PP   0x00000008u /*!< 10: Alternate function output Push-pull  */
// 低二位都是0,为了配合Mode
#define  GPIO_CR_CNF_AF_OUTPUT_OD   0x0000000Cu /*!< 11: Alternate function output Open-drain  */// 这里就是配置CNF+Mode
config = GPIO_Init->Speed + GPIO_CR_CNF_GP_OUTPUT_PP;

其实就是将MODE和CNF结合到一块共同控制一个引脚。

二、在main()自定义操作

知道了库函数的操作,其实我们自己也可以将Led灯进行点亮或者熄灭,比如

// 熄灭
GPIOB->BSRR = GPIO_PIN_9;
// 点亮
GPIOB->BSRR = GPIO_PIN_9 << 16;

其实最终就是操作的寄存器(不研究也知道操作的寄存器,哈哈哈)。

点灯对寄存器的操作如下:

  1. 配置APB2ENR开启GPIOB时钟
  2. 配置CRLCRH,来操作引脚的CNFMODE,让其作为输入或输出
  3. 配置BSRR使ODR对应的位输出1或0

通过对stm32内存映射和GPIO寄存器的分析,大致了解了HAL的一些细节,确实单独操作寄存器难度比较大,但是通过对HAL函数的研究,加深了自己对HAL操作的了解以及寄存器细节的了解。

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

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

相关文章

MySQL备份及恢复

目录 MySQL备份 MySQL备份方法 备份策略 mysql的完全备份 mysql的增量备份 MySQL恢复 mysql完全恢复 mysql增量备份的恢复 MySQL备份 MySQL备份是基于对MySQL的日志进行备份&#xff0c;且恢复也是通过日志进行数据恢复。 MySQL备份方法 物理备份&#xff1a;直接对…

北京智和信通亮相2023IT运维大会,共话数智浪潮下自动化运维新生态

2023年9月21日&#xff0c;由IT运维网、《网络安全和信息化》杂志社联合主办的“2023&#xff08;第十四届&#xff09;IT运维大会”在北京成功举办。大会以“以数为基 智引未来”为主题&#xff0c;北京智和信通技术有限公司&#xff08;下文简称&#xff1a;北京智和信通&…

爱看小说手机网源码全站带数据带自动采集程序/ThinkPHP内核小说网站源码+书库数据库带自动采集

爱看小说手机网源码全站带数据带自动采集程序&#xff0c;爱看小说程序源码2W条数据全站打包,自动采集程序网站源码,后台已经更新5个采集规则可以采集小说30万本大概约10G。 分享的这一款自带2w数据爱看小说网源码全站带数据打包,ThinkPHP内核小说网站源码带听书等全部插件&am…

TouchGFX之画布控件

TouchGFX的画布控件&#xff0c;在使用相对较小的存储空间的同时保持高性能&#xff0c;可提供平滑、抗锯齿效果良好的几何图形绘制。 TouchGFX 设计器中可用的画布控件&#xff1a; LineCircleShapeLine Progress圆形进度条 存储空间分配和使用​ 为了生成反锯齿效果良好的…

矩阵论—凯莱-哈密顿定理

凯莱-哈密顿定理内容 凯莱-哈密顿定理典型例题 典型例题 我们先来观察这个题目&#xff0c;题目要求&#xff0c;若直接将矩阵A 代入计算&#xff0c;则会非常复杂&#xff0c;因此&#xff0c;这条路是走不通的。 我们试着引入我们今天介绍的凯莱-哈密顿定理来解这个…

Linux,计算机网络,数据库

Linux&#xff0c;计算机网络&#xff0c;数据库&#xff0c;操作系统 一、Linux1、linux查看进程2、linux基本命令3、top命令、查看磁盘 二、计算机网络1、HTTP的报文段请求 Repuest响应 Response 2、HTTP用的什么连接3、TCP的三次握手与四次挥手三次握手四次挥手 4、在浏览器…

【MATLAB第76期】基于MATLAB的代表性样本筛选方法合集(针对多输入单输出数据)

【MATLAB第76期】基于MATLAB的代表性样本筛选方法合集&#xff08;针对多输入单输出数据&#xff09; 前有筛选变量方法&#xff0c;如局部敏感性分析和全局敏感性分析方法介绍 。 今天提出另外一种思路&#xff0c;去对样本进行筛选。 使用场景&#xff1a; 场景1&#xff1a…

Python 实现 PDF 文件转换为图片 / PaddleOCR

文章用于学习记录 文章目录 前言一、PDF 文件转换为图片二、OCR 图片文字识别提取三、服务器端下载运行 PaddleOCR四、下载权重文件总结 前言 文字识别&#xff08;Optical Character Recognition&#xff0c;简称OCR&#xff09;是指将图片、扫描件或PDF、OFD文档中的打印字符…

Mybatis工作流程及原理详解

一、概述 1.何为mybatis&#xff1f; MyBatis 是一款优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息&#xff0c;将接口和 J…

数据仓库数据库

在当今的数字化时代&#xff0c;数据存储和管理是非常重要的领域。数据仓库和数据库是两个重要的数据存储和管理工具&#xff0c;它们有着不同的特点和用途。 一、数据仓库与数据库的定义 1. 数据仓库 数据仓库&#xff0c;是为企业所有级别的决策制定过程&#xff0c;提供所…

报错处理:Error: Redis server is running but Redis CLI cannot connect

嗨&#xff0c;读者朋友们&#xff01;今天我来跟大家分享一个我在运维过程中遇到的一个关于Linux上运行Redis服务时的报错及解决方法。 报错信息如下&#xff1a; Error: Redis server is running but Redis CLI cannot connect 这个报错信息表明Redis服务器已经运行&#xff…

达梦数据库-DW-国产化--九五小庞

武汉达梦数据库股份有限公司成立于2000年&#xff0c;是国内领先的数据库产品开发服务商&#xff0c;国内数据库基础软件产业发展的关键推动者。公司为客户提供各类数据库软件及集群软件、云计算与大数据等一系列数据库产品及相关技术服务&#xff0c;致力于成为国际顶尖的全栈…

【笔记】ubuntu 20.04 + mongodb 4.4.14定时增量备份脚本

环境 ubuntu 20.04mongodb 4.4.14还没实际使用&#xff08;20230922&#xff09;后续到10月底如果有问题会修改 原理 只会在有新增数据时生成新的备份日期目录备份恢复时&#xff0c;如果恢复的数据库未删除&#xff0c;则会覆盖数据 准备 准备一个文件夹&#xff0c;用于…

thinkphp8路由

thinkphp8已出来有好一段时间了。这些天闲来无事&#xff0c;研究了下tp8的路由。默认情况下&#xff0c;tp8的路由是在route\app.php的文件里。但在实际工作中&#xff0c;我们并不会这样子去写路由。因为这样不好管理。更多的&#xff0c;是通过应用级别去管理路由。假如项目…

网络初识

一 IP 地址 概念: IP 地址主要用于表示网络主机、其他网络设备&#xff08;如路由器&#xff09;的网络地址。简单说&#xff0c;IP地址用于定位主机的网络地址 格式 IP 地址是一个32为的二进制数&#xff0c;通常被分割为4个“8位二进制数“&#xff08;也就是4个字节&…

23. 图论 - 图的由来和构成

文章目录 图的由来图的构成Hi, 你好。我是茶桁。 从第一节课上到现在,我基本上把和人工智能相关的一些数学知识都教给大家了,终于来到我们人工智能数学的最后一个部分了,让我们从今天开始进入「图论」。 图论其实是一个比较有趣的领域,因为微积分其实更多的是对应连续型的…

[Linux入门]---Linux项目自动化构建工具-make/Makefile

目录 1.背景2.make指令输入make默认为Makefile文件第一条指令执行Makefile文件对gcc指令特殊处理及原理特殊符号 3.总结 1.背景 会不会写makefile&#xff0c;从一个侧面说明了一个人是否具备完成大型工程的能力一个工程中的源文件不计数&#xff0c;其按类型、功能、模块分别放…

Lua学习笔记:词法分析

前言 本篇在讲什么 Lua的词法分析 本篇需要什么 对Lua语法有简单认知 对C语法有简单认知 依赖Visual Studio工具 本篇的特色 具有全流程的图文教学 重实践&#xff0c;轻理论&#xff0c;快速上手 提供全流程的源码内容 ★提高阅读体验★ &#x1f449; ♠ 一级标题…

207.Flink(二):架构及核心概念,flink从各种数据源读取数据,各种算子转化数据,将数据推送到各数据源

一、Flink架构及核心概念 1.系统架构 JobMaster是JobManager中最核心的组件,负责处理单独的作业(Job)。一个job对应一个jobManager 2.并行度 (1)并行度(Parallelism)概念 一个特定算子的子任务(subtask)的个数被称之为其并行度(parallelism)。这样,包含并行子任…

【方案】浅析AI视频分析与视频监控技术的工厂车间智能化监管方案

一、方案背景 工厂生产车间一般是从原材料到成品的流水作业&#xff0c;有大量器械和物料。为保障车间财产安全并提高生产效率&#xff0c;需要进行全面的监管。在生产制造流水线的关键工序中&#xff0c;不仅有作业过程监管需求&#xff0c;同时&#xff0c;也存在生产发生异…