• STM32F103C8T6第二天:按键点灯轮询法和中断法、RCC、电动车报警器(振动传感器、继电器、喇叭、433M无线接收发射模块)


    1. 点亮LED灯详解(307.11)

    • 标号一样的导线在物理上是连接在一起的。
      在这里插入图片描述
      在这里插入图片描述
    • 将 PB8 或 PB9 拉低,就可以实现将对应的 LED 灯点亮。
    • 常用的GPIO HAL库函数:
    void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);//I/O口的初始化配置
    void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState
    PinState);//对I/O口写高写低
    void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);//翻转I/O口的状态
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();//时钟:使GPIOB能工作,节约能耗,资源最大化的利用
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 结构体 GPIO_InitTypeDef 定义:
    typedef struct
    {
    uint32_t Pin;//引脚编号
    uint32_t Mode;//输入|推挽输出|开漏输出
    uint32_t Pull;//上拉|下拉|不拉
    uint32_t Speed;//低速|中速|高速
    } GPIO_InitTypeDef;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2. 按键点亮LED灯(轮询法)(308.12)

    • 输入(按键):
      • KEY1:PA0
      • KEY2:PA1
    • 输出(LED灯):
      • LED1:PB8
      • LED2:PB9
        在这里插入图片描述
    • 代码(key_test/MDK-ARM)
    //main.c
    /* Private macro -------------------------------------------------------------*/
    /* USER CODE BEGIN PM */
    #define KEY_ON  0
    #define KEY_OFF 1
    /* USER CODE END PM */
    uint8_t Key_Scan(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
    {//检测按键的状态
    	if(HAL_GPIO_ReadPin(GPIOx, GPIO_Pin) == GPIO_PIN_RESET)
    	{	/* 按键按下 */
    		while(HAL_GPIO_ReadPin(GPIOx, GPIO_Pin) == GPIO_PIN_RESET);//消除按键抖动(防抖操作)
    		return KEY_ON;
    	}else
    	{	/* 按键松开 */
    		return KEY_OFF;
    	}
    }
    int main(void)
    {
    	HAL_Init();
    	SystemClock_Config();
    	MX_GPIO_Init();
    	while (1)
      {//按下key时,翻转led的状态
        	/* USER CODE END WHILE */
    		//HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8|GPIO_PIN_9, GPIO_PIN_RESET);
        	/* USER CODE BEGIN 3 */
    		if(Key_Scan(GPIOA, GPIO_PIN_0) == KEY_ON)
    			HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_8);
    		if(Key_Scan(GPIOA, GPIO_PIN_1) == KEY_ON)
    			HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_9);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    3. 复位和时钟控制(RCC)(309.13)

    • reset and clock control

    复位

    • 系统复位
      当发生以下任一事件时,产生一个系统复位:
        1. NRST引脚上的低电平(外部复位)
        2. 窗口看门狗计数终止(WWDG复位)
        3. 独立看门狗计数终止(IWDG复位)
        4. 软件复位(SW复位)
        5. 低功耗管理复位
    • 电源复位
      当以下事件中之一发生时,产生电源复位:
        1. 上电/掉电复位(POR/PDR复位)
        2. 从待机模式中返回
    • 备份区复位
      备份区域拥有两个专门的复位,它们只影响备份区域。
      当以下事件中之一发生时,产生备份区域复位。
        1. 软件复位,备份区域复位可由设置备份域控制寄存器 (RCC_BDCR)(见6.3.9节)中的BDRST位产生。
        2. 在VDD和VBAT两者掉电的前提下,VDD或VBAT上电将引发备份区域复位。

    时钟控制

    • 什么是时钟?
      时钟打开,对应的设备才会工作。
    • 时钟来源
      • 三种不同的时钟源可被用来驱动系统时钟(SYSCLK)
        • HSI振荡器时钟(高速内部时钟)
        • HSE振荡器时钟(高速外部时钟)
        • PLL时钟(锁相环倍频时钟)
      • 二级时钟源:
        • 40kHz低速内部RC(LSIRC)振荡器
        • 32.768kHz低速外部晶体(LSE晶体)
    • 如何使用CubeMX配置时钟
      在这里插入图片描述
      在这里插入图片描述

    在这里插入图片描述

    4. 中断相关概念(310.14)

    什么是中断?

    • 中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。

    什么是 EXTI?

    • 外部中断/事件控制器 (EXTI) 管理了控制器的 23 个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。 EXTI 可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。
      在这里插入图片描述
    • EXTI 可分为两大部分功能,一个是产生中断,另一个是产生事件,这两个功能从硬件上就有所不同。
      产生中断线路目的是把输入信号输入到 NVIC,进一步会运行中断服务函数,实现功能,这样是软件级的。而产生事件线路目的就是传输一个脉冲信号给其他外设使用,并且是电路级别的信号传输,属于硬件级的。
    • EXTI初始化结构体:
    typedef struct
    {
     //中断/事件线
     uint32_t EXTI_Line;        /*!< Specifies the EXTI lines to be enabled or
    disabled.
                        This parameter can be any combination value
    of @ref EXTI_Lines */
     //EXTI 模式
     EXTIMode_TypeDef EXTI_Mode;    /*!< Specifies the mode for the EXTI lines.
                        This parameter can be a value of @ref
    EXTIMode_TypeDef */
     //触发类型
     EXTITrigger_TypeDef EXTI_Trigger; /*!< Specifies the trigger signal active edge
    for the EXTI lines.
                        This parameter can be a value of @ref
    EXTITrigger_TypeDef */
     //EXTI 控制
     FunctionalState EXTI_LineCmd;   /*!< Specifies the new state of the selected
    EXTI lines.
                        This parameter can be set either to ENABLE
    or DISABLE */
    }EXTI_InitTypeDef;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 中断/事件线:
    #define EXTI_Line0    ((uint32_t)0x00001)   /*!< External interrupt line 0 */
    #define EXTI_Line1    ((uint32_t)0x00002)   /*!< External interrupt line 1 */
    #define EXTI_Line2    ((uint32_t)0x00004)   /*!< External interrupt line 2 */
    #define EXTI_Line3    ((uint32_t)0x00008)   /*!< External interrupt line 3 */
    #define EXTI_Line4    ((uint32_t)0x00010)   /*!< External interrupt line 4 */
    #define EXTI_Line5    ((uint32_t)0x00020)   /*!< External interrupt line 5 */
    #define EXTI_Line6    ((uint32_t)0x00040)   /*!< External interrupt line 6 */
    #define EXTI_Line7    ((uint32_t)0x00080)   /*!< External interrupt line 7 */
    #define EXTI_Line8    ((uint32_t)0x00100)   /*!< External interrupt line 8 */
    #define EXTI_Line9    ((uint32_t)0x00200)   /*!< External interrupt line 9 */
    #define EXTI_Line10   ((uint32_t)0x00400)   /*!< External interrupt line 10 */
    #define EXTI_Line11   ((uint32_t)0x00800)   /*!< External interrupt line 11 */
    #define EXTI_Line12   ((uint32_t)0x01000)   /*!< External interrupt line 12 */
    #define EXTI_Line13   ((uint32_t)0x02000)   /*!< External interrupt line 13 */
    #define EXTI_Line14   ((uint32_t)0x04000)   /*!< External interrupt line 14 */
    #define EXTI_Line15   ((uint32_t)0x08000)   /*!< External interrupt line 15 */
    #define EXTI_Line16   ((uint32_t)0x10000)   /*!< External interrupt line 16
    Connected to the PVD Output */
    #define EXTI_Line17   ((uint32_t)0x20000)   /*!< External interrupt line 17
    Connected to the RTC Alarm event */
    #define EXTI_Line18   ((uint32_t)0x40000)   /*!< External interrupt line 18
    Connected to the USB OTG FS Wakeup from suspend event */              
    #define EXTI_Line19   ((uint32_t)0x80000)   /*!< External interrupt line 19
    Connected to the Ethernet Wakeup event */
    #define EXTI_Line20   ((uint32_t)0x00100000)  /*!< External interrupt line 20
    Connected to the USB OTG HS (configured in FS) Wakeup event */
    #define EXTI_Line21   ((uint32_t)0x00200000)  /*!< External interrupt line 21
    Connected to the RTC Tamper and Time Stamp events */                
    #define EXTI_Line22   ((uint32_t)0x00400000)  /*!< External interrupt line 22
    Connected to the RTC Wakeup event */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • EXTI 模式:
    typedef enum
    {
     EXTI_Mode_Interrupt = 0x00,  //产生中断
     EXTI_Mode_Event = 0x04    //产生事件
    }EXTIMode_TypeDef;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 触发类型:
    typedef enum
    {
     EXTI_Trigger_Rising = 0x08,     //上升沿
     EXTI_Trigger_Falling = 0x0C,     //下降沿
     EXTI_Trigger_Rising_Falling = 0x10  //上升沿和下降沿都触发
    }EXTITrigger_TypeDef;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • EXTI 控制:
      使能 EXTI ,一般都是使能, ENABLE

    什么是优先级?

    抢占优先级和响应优先级的区别:

    • 高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。
    • 抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。
    • 抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。
    • 如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行

    什么是优先级分组?

    Cortex-M3 允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此 STM32 把指定中断优先级的寄存器位减少到 4 位,这 4 个寄存器位的分组方式如下:

    • 第0组:所有4位用于指定响应优先级
    • 第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级
    • 第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级
    • 第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级
    • 第4组:所有4位用于指定抢占式优先级

    什么是NVIC?

    STM32 通过中断控制器 NVIC(Nested Vectored Interrupt Controller)进行中断的管理 。NVIC 是属于 Cortex 内核的器件,不可屏蔽中断(NMI)和外部中断都由它来处理,但是 SYSTICK 不是由 NVIC 控制的。

    typedef struct
    {
     uint8_t NVIC_IRQChannel;
     uint8_t NVIC_IRQChannelPreemptionPriority;  //抢断优先级
     uint8_t NVIC_IRQChannelSubPriority;  //响应优先级   
     FunctionalState NVIC_IRQChannelCmd;   
    } NVIC_InitTypeDef;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    什么是中断向量表?

    • 每个中断源都有对应的处理程序,这个处理程序称为中断服务程序,其入口地址称为中断向量。所有中断的中断服务程序入口地址构成一个表,称为中断向量表;也有的机器把中断服务程序入口的跳转指令构成一张表,称为中断向量跳转表。

    5. 按键点亮LED灯(中断法)(311.15)

    1. 配置时钟
      在这里插入图片描述
      在这里插入图片描述
    2. 配置GPIO口
      在这里插入图片描述
    3. 使能中断
      在这里插入图片描述
    • 代码(4.exti_test/MDK-ARM)
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)//中断服务函数
    {
    	switch(GPIO_Pin)
    	{
    		HAL_Delay(50);//为了消抖
    		case GPIO_PIN_0:
    			if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)//消抖:如果下降沿之后的50ms还是低(消除意外抖动带来的低电平情况)
    				HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_8);//翻转LED灯状态
    		break;
    		case GPIO_PIN_1:
    			if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET)
    				HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_9);
    		break;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    6. 电动车报警器项目概述(312.16)

    项目需求

    • 点击遥控器 A 按键,系统进入警戒模式,一旦检测到震动(小偷偷车),则喇叭发出声响报警,吓退小偷。
    • 点击遥控器 B 按键,系统退出警戒模式,再怎么摇晃系统都不会报警,否则系统一直发出尖叫,让车主尴
      尬。

    项目框图

    在这里插入图片描述

    硬件清单

    • 振动传感器
    • 继电器
    • 高功率喇叭
    • 433M无线接收发射模块
    • 杜邦线

    7. 振动传感器介绍及实战(313.17)

    振动传感器介绍

    • 单片机供电VCC GND接单片机
    • 产品不震动,输出高电平,模块上的DO口
    • 产品震动,输出低电平,绿色指示灯亮
    • AO口不用
      在这里插入图片描述

    编程实现

    • 需求:当振动传感器接收到振动信号时,使用中断方式点亮LED1。
    • CubeMX 的必要配置
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
    • 代码(5.alert_project/MDK-ARM)
    //重写中断服务函数,如果检测到EXTI中断请求,则进入此函数
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    {
    	//一根中断线上接有多个中断源,判断中断源是否来自PA4
    	if(GPIO_Pin == GPIO_PIN_4)
    	{
    		//如果检测到PA4被拉低
    		if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == GPIO_PIN_RESET)
    		{
    			//则点亮LED1
    			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
    			HAL_Delay(1000);
    			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
    		}
    		else
    		{
    		//如果未检测到PA4被拉低,则关闭LED1
    			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 如果直接在中断服务函数里调用 HAL_Delay 函数,则会造成系统卡死。
      • 原因:程序初始化时默认把滴答定时器的中断优先级设为最低,其它中断源很容易打断它导致卡死。
      • 解决:在 main 函数里使用以下函数提高滴答定时器的中断优先级(提升至0):
        HAL_NVIC_SetPriority(SysTick_IRQn,0,0);
      • 并且将 EXTI4 的中断优先级设置比滴答定时器的中断优先级高,比如 2 。
        在这里插入图片描述

    8. 继电器介绍及实战(314.18)

    继电器工作原理

    • 单片机供电VCC GND接单片机,VCC需要接3.3V,5V不行!
    • 最大负载电路交流250V/10A,直流30V/10A
    • 引脚 IN 接收到低电平时开关闭合。(PB8,同时led1亮)
    • 电源的负极—负载的负极(黑线)
    • 电源的正极、负载的正极分别接到继电器的 com 和 NO 口(可反)(红线)
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

    9. 433M无线发射接收模块介绍及实战(315.19)

    433M无线发射接收模块介绍

    • 单片机供电VCC GND接单片机
    • 接收到信号,接收模块对应针脚输出高电平
    • 有D0 D1 D2 D3,对应遥控器的ABCD在这里插入图片描述

    编程实现

    • 需求:按下遥控器A按键,LED1亮1秒;按下遥控器B按键,LED2亮1秒。
      • D0 – PA5
      • D1 – PA6
    • 修改 cubemx 工程配置:
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
    • 代码(5.alert_project/MDK-ARM)
    //重写中断服务函数,如果检测到EXTI中断请求,则进入此函数
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    {
    	switch(GPIO_Pin)
    	{	
    		case GPIO_PIN_5:
    			if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) ==  GPIO_PIN_SET)
    			{// 如果检测到PA5被拉高(即按键A被按下)
    				// 则将PB8拉低,LED1亮1秒
    				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
    				HAL_Delay(1000);
    				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
    			}
    			else
    			{// 未检测到PA5被拉高,则LED1灭
    				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
    			}
    		break;
    		case GPIO_PIN_6:
    			if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6) ==  GPIO_PIN_SET)
    			{// 如果检测到PA6被拉高(按键B被按下)
    				// 则将PB9拉低,LED2亮1秒
    				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET);
    				HAL_Delay(1000);
    				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET);
    			}
    			else
    			{// 未检测到PA5被拉高,则LED1灭
    				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET);
    			}
    		break;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    10. 电动车报警器项目设计及(316.20)

    项目设计

    //如果检测到PA4被拉低(小偷偷车),并且警报模式打开
        //则将PB7拉低,继电器通电,喇叭一直响
    // 如果检测到PA5被拉高(按键A按下),设定为开启警报模式
        // 则将PB7拉低(喇叭响),2秒后恢复电平(喇叭不响),表示进入警报模式
        // 同时将标志位设置为ON
    // 如果检测到PA6被拉高(按键B按下),设定为关闭警报模式
        // 则将PB7拉低(喇叭响),1秒后恢复电平(喇叭不响),表示关闭警报模式
        // 同时将标志位设置为OFF
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    编程实现

    • cubemx工程修改
      在这里插入图片描述
    • 代码(5.alert_project/MDK-ARM)
    /* Private macro -------------------------------------------------------------*/
    /* USER CODE BEGIN PM */
    #define J_ON  1
    #define J_OFF 2
    /* USER CODE END PM */
    //重写中断服务函数,如果检测到EXTI中断请求,则进入此函数
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    {
    	static int mark = J_OFF;//只在首次初始化时分配内存,且在函数调用之间保留其值
    	switch(GPIO_Pin)
    	{
    		// 如果检测到PA4被拉低(发生振动 即小偷偷车),并且警报模式打开
    		case GPIO_PIN_4:
    			if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) ==  GPIO_PIN_RESET && mark == J_ON)
    			{
    				// 则将PB7拉低,继电器通电,喇叭一直响
    				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
    			}
    		break;
    		
    		// 如果检测到PA5被拉高(按键A被按下),设定为开启警报模式
    		case GPIO_PIN_5:
    		if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) ==  GPIO_PIN_SET)
    		{
    			// 则将PB7拉低(喇叭响),2秒,表示进入到警报模式
    			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
    			HAL_Delay(2000);
    			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
    			// 同时将标示位设置为ON
    			mark = J_ON;
    		}
    		break;
    		
    		// 如果检测到PA6被拉高(按键B被按下),设定为关闭警报模式
    		case GPIO_PIN_6:
    		if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6) ==  GPIO_PIN_SET)
    		{
    			// 则将PB7拉低(喇叭响),1秒,表示关闭警报模式
    			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
    			HAL_Delay(1000);
    			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
    			// 同时将标示位设置为OFF
    			mark = J_OFF;
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    [山东科技大学OJ]1487 Problem B: 编写函数:字符串的查找字符 之二 (Append Code)
    数据结构 --- JAVA版链表
    在Ubuntu/Linux中修改MySQL的数据目录
    Java自定义注解解析
    喜迎国庆,居家五黑,自己写个组队匹配叭
    小白高效自学-网络安全(黑客技术)
    Qt的窗口的设置
    MatrixOne Logtail 设计解析
    电子行业MES管理系统的主要功能与用途
    Kubernetes Scheduler全解析
  • 原文地址:https://blog.csdn.net/Jaci133/article/details/134189357