stm32之GPIO库函数点灯分析

news2024/12/26 23:21:44

        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));

	// 判断后续是否还有引脚设置了1
  while (((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 */
			// 根据模式来配置config
      switch (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 number
       in 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.coloradmin.cn/o/1033236.html

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

相关文章

动手吧,vue数字动画

数字动画&#xff0c;有数字的地方都能用上&#xff0c;拿去吧&#xff01; 效果&#xff1a; 1、template部分 <template><div class"v-count-up">{{ dispVlaue }}</div> </template> 2、js部分 export default {data() {return {timer…

版本动态 | SolidUI 0.3.0 版本发布

文章目录 背景发版清单功能部署 示例html生成模型选择数据源 详细指引贡献者如何成为贡献者 背景 随着文本生成图像的语言模型兴起&#xff0c;SolidUI想帮人们快速构建可视化工具&#xff0c;可视化内容包括2D,3D,3D场景&#xff0c;从而快速构三维数据演示场景。SolidUI 是一…

摄像头工程师说 Camera - 数据格式 RAW、RGB(1)

Camera - 数据格式 RAW、RGB Camera 数据格式-RAW、RGB从摄像头工作的基本原理说起回归本质-图像色彩的几种表示方法RGB 三原色RAW RGB 格式诞生RAW8 VS RAW10真彩色-RGB888、BGR888 格式的引入数据量小点的 RGB 格式-RGB565、RGB555用位数表示的 RGB 格式RGB24&#xff1a;RGB…

iOS17.0.2更新修复iPhone 15系列机型数据迁移问题,附新机快速数据迁移办法!

iPhone 15 系列机型已于今日正式发售&#xff0c;为解决iPhone15这些机型出现的数据迁移问题&#xff0c;苹果紧急发布了 iOS 17.0.2 更新&#xff0c;内部版本号为 21A350。 需要注意的是&#xff0c; iOS 17.0.2 更新仅适用于 iPhone 15、iPhone 15 Plus、iPhone 15 Pro 和 …

HTML5福利篇--使用Canvas画图

目录 一.Canvas元素 1.Canvas元素定义 2.使用JavaScript获取页面中的Canvas对象 二.绘制图形 1.绘制直线 2.绘制矩形 &#xff08;1&#xff09;rect() &#xff08;2&#xff09;strokeRect() &#xff08;3&#xff09;fillRect()和clearRect()函数 3.绘制圆弧 4.…

华为云云耀云服务器L实例评测 | 基于minikube搭建单节点kubernetes集群

目录 1 安装Docker2 conntrack-tools3 安装minikube4 下载二进制&#xff1a;kubeadm、kubectl、kubelet5 准备镜像6 启动minikube7 简单测试 ​ Minikube 是一个使用golang开发的单节点kubernetes集群环境&#xff0c;在资源紧张的情况下&#xff0c;可以用于快速搭建kubernet…

项目进展(一)-晶振正常输出、焊接驱动芯片、查找芯片手册并学习

今天的主要工作集中在博士师兄的项目上&#xff0c;效率偏低&#xff0c;主要是一中午的时间都卡在晶振上。在焊接完芯片和晶振之后&#xff0c;测试晶振输出引脚无输出&#xff0c;所以就开始找各种博客&#xff0c;寻找晶振不起振的原因&#xff0c;在下面两篇文章中找到了答…

基于骨架的动作识别:SkeleTR: Towrads Skeleton-based Action Recognition in the Wild

论文作者&#xff1a;Haodong Duan,Mingze Xu,Bing Shuai,Davide Modolo,Zhuowen Tu,Joseph Tighe,Alessandro Bergamo 作者单位&#xff1a;The Chinese University of Hong Kong; AWS AI Labs. 论文链接&#xff1a;http://arxiv.org/abs/2309.11445v1 内容简介&#xff1…

JavaScript+canvas实现粒子动画效果

1.HTML部分 <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>粒子效果</title><style&g…

OpenAI官方吴达恩《ChatGPT Prompt Engineering 提示词工程师》(7)聊天机器人 / ChatBot

聊天机器人 / ChatBot 使用大型语言模型来构建你的自定义聊天机器人 在本视频中&#xff0c;你将学习使用OpenAI ChatCompletions格式的组件构建一个机器人。 环境准备 首先&#xff0c;我们将像往常一样设置OpenAI Python包。 import os import openai from dotenv import…

图像练习-答题卡opencv(02)

原图 结果 代码 // Load source imagecv::Mat src cv::imread("answer_card.jpg", cv::IMREAD_COLOR);if (src.empty()){return;}cv::Mat gray;cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);cv::Mat binary;double value cv::threshold(gray, binary, 0, 255, …

用PHP实现极验验证功能

极验验证是一种防机器人的验证机制&#xff0c;可以通过图像识别等方式来判断用户是否为真实用户。在实现极验验证功能时&#xff0c;您需要进行以下步骤&#xff1a; 1 注册极验账号&#xff1a; 首先&#xff0c;您需要在极验官网注册账号并创建一个应用&#xff0c;获取相应…

x_ctf_b0verfl0w

x_ctf_b0verfl0w Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) RWX: Has RWX segments32位&#xff0c;保护全关&#xff0c;写shellcode int vul() {char s[32]; // [esp18h] [eb…

mac安装 scala 详细教程(包含在 idea 上使用,以及scala插件安装)

目录 一 下载解压 二 配置环境变量 三 测试 scala 四 idea 编写 scala 文件 1. 安装插件 scala 插件 2. 使用 idea 创建 scala 工程 3. 使用idea 创建 maven 工程开发 scala 一 下载解压 去官网选择合适的版本下载 官网地址https://www.scala-lang.org/download/all.…

RocketMQ高性能核心原理与源码架构剖析

文章目录 1、源码环境搭建1.1、主要功能模块1.2、源码启动服务1.2.1、 启动nameServer1.2.2、 启动Broker1.2.3、 发送消息1.2.4、 消费消息 2、源码剖析2.1、NameServer的启动过程2.2、Broker服务启动过程2.3、Netty服务注册框架2.3.1、关注重点2.3.2、源码重点 1、源码环境搭…

进化的京东云DaaS:向大模型要解

通过新的DaaS大模型模式&#xff0c;京东云想要为企业提供的增长路径&#xff0c;恰是从最原始的“要数据”真正进阶到最终的“出效果”&#xff0c;将大模型和京东对增长的理解封装到整个产品矩阵中&#xff0c;帮助企业构建最适合AI时代的增长底盘。 作者|皮爷 出品|产业…

如何保障汽车嵌入式软件的质量与安全?您需要了解ASPICE标准

汽车软件开发流程改进与能力确定&#xff08;Automotive SPICE或ASPICE&#xff09;是一个流程评估模型&#xff0c;它帮助汽车原始设备制造商&#xff08;OEM&#xff09;和供应商评估当前企业软件开发流程的性能和成熟度水平。 遵守这一标准&#xff0c;有助于汽车供应商确保…

Apache Flume

Flume 1.9.0 Developer Guide【Flume 1.9.0开发人员指南】 Introduction【介绍】 摘自&#xff1a;Flume 1.9.0 Developer Guide — Apache Flume Overview【概述】 Apache Flume is a distributed, reliable, and available system for efficiently collecting, aggregati…

迁移 MySQL 数据到 OceanBase 集群

使用 mysqldump 将 mysql的表结构和数据同步到 OceanBase 的MySQL 租户中 Mysql数据库导出 mysqldump -h127.0.0.1 -P3306 -uroot –p --single-transaction --hex-blob --routines --events --triggers --set-gtid-purgedOFF --databases teller >teller.sql mysql> …

sentinel环境搭建以及微服务接入

• sentinel部署 • sentinel-镜像制造 • sentinel-镜像推送 • sentinel-部署配置文件 • 访问控制台 • 外网访问控制台 • 集群内访问 • 配置规则 • 限流效果 • 微服务接入 • pom文件引入依赖 • pod部署文件添加配置 Sentinel 控制台是流量控制、熔断降级规则统一配置…