STM32H7定时器TIM1-TIM17中断、PWM实现

news2025/4/11 22:39:40

STM32H7定时器TIM1-TIM17中断、PWM实现

  • 高级定时器硬件框图
  • 定时器模式
    • 时基
    • 输出PWM
    • 定时器输入捕获
  • TIM1-TIM17的中断配置
  • TIM1-TIM17的PWM输出

STM32H7 支持的定时器有点多,要简单的区分下。STM32H7 支持 TIM1-TIM8,TIM12-TIM17 共14 个定时器,而中间的 TIM9,TIM10,TIM11 是不存在的,这点要注意。

在这里插入图片描述

高级定时器硬件框图

我们直接看最复杂的高级定时器 TIM1&TIM8 框图:
在这里插入图片描述
通过这个框图,我们可以得到如下信息:
TIMx_ETR 接口
外部触发输入接口。ETR 支持多种输入源:输入引脚(默认配置)、比较器输出和模拟看门狗。
截图左侧的 TIMx_CH1,TIMx_CH2,TIMx_CH3 和 TIMx_CH4 接口
这四个通道主要用于输入捕获,可以计算波形频率和脉宽。
TIMx_BKIN 和 TIMx_BKIN2 接口
断路功能,主要用于保护由 TIM1 和 TIM8 定时器产生的 PWM 信号所驱动的功率开关
TRGO 内部输出通道
主要用于定时器级联,ADC 和 DAC 的定时器触发。
6 组输出比较单元 OC1 到 OC6
OC1 到 OC4 有对应的输出引脚,而 OC5 和 OC6 没有对应的输出引脚,主要用于内部控制。
截图右侧的输出比较通道 TIMx_CH1,TIMx_CH1N,TIMx_CH2
TIMx_CH2N,TIMx_CH3,
TIMx_CH3N 和 TIMx_CH4
主要用于 PWM 输出,注意 CH1 到 CH3 有互补输出,而 CH4 没有互补输出。

定时器模式

时基

定时器要工作就需要一个基本时基单元,而基本的时基单元是由下面几个寄存器组成的:
预分频器寄存器 (TIMx_PSC)
用于设置定时器的分频,比如定时器的主频是 200MHz,通过此寄存器可以将其设置为 100MHz,
50MHz,25MHz 等分频值。
注:预分频器有个缓冲功能,可以让用户实时更改,新的预分频值将在下一个更新事件发生时被采用
(以递增计数模式为例,就是 CNT 计数值达到 ARR 自动重装寄存器的数值时会产生更新事件)。
计数器寄存器 (TIMx_CNT)
计数器是最基本的计数单元,计数值是建立在分频的基础上面,比如通过 TIMx_PSC 设置分频后的频
率为 100MHz,那么计数寄存器计一次数就是 10ns。
自动重载寄存器 (TIMx_ARR)
自动重装寄存器是 CNT 计数寄存器能达到的最大计数值,以递增计数模式为例,就是 CNT 计数器达
到 ARR 寄存器数值时,重新从 0 开始计数。
注,自动重载寄存器是预装载的。对自动重载寄存器执行写入或读取操作时会访问预装载寄存器。预
装载寄存器的内容既可以立即传送到影子寄存器(让设置立即起到效果的寄存器),也可以在每次发
生更新事件时传送到影子寄存器。简单的说就是让 ARR 寄存器的数值立即更新还是更新事件发送的
时候更新。
重复计数器寄存器 (TIMx_RCR)
以递增计数模式为例,当 CNT 计数器数值达到 ARR 自动重载数值时,重复计数器的数值加 1,重复
次数达到 TIMx_RCR+ 1 后就,将生成更新事件。
注,只有 TIM1,TIM8,TIM15,TIM16,TIM17 有此寄存器。
比如我们要配置定时器实现周期性的中断,主要使用这几个寄存器即可。

输出PWM

使用定时器时基单元的那几个寄存器仅仅能设置周期,还不能设置占空比。针对这个问题,还需要比
较捕获寄存 CCR 的参与,这样就可以设置占空比了。
为了方便大家理解,以 PWM 边沿对齐模式,递增计数配置为例:
当计数器 TIMx_CNT < 比较捕获寄存器 TIMx_CCRx 期间,PWM 参考信号 OCxREF 输出高电平。
当计数器 TIMx_CNT >= 比较捕获寄存器 TIMx_CCRx 期间,PWM 参考信号 OCxREF 输出低电平。
当比较捕获寄存器 TIMx_CCRx > 自动重载寄存器 TIMx_ARR,OCxREF 保持为 1。
当比较捕获寄存器 TIMx_CCRx = 0,则 OCxRef 保持为 0。

定时器输入捕获

与 PWM 一样,使用定时器实现输入捕获,仅靠时基单元的那几个寄存器是不行的,我们需要一个寄
存器来记录发生捕获时的具体时间,这个寄存器依然由比较捕获寄存器 TIMx_CCRx 来实现。
比如我们要测量一路方波的周期:
配置定时器为输入捕获模式,上升沿触发,设置分频,自动重装等寄存器,比如设置的 CNT 计数器计数 1 次是 1 微秒。
当有上升沿触发的时候,TIMx_CCRx 寄存器就会自动记录当前的 CNT 数值,然后用户就可以通过CC 中断,在中断复位程序里面保存当前的 TIMx_CCRx 寄存器数值。等下次再检测到上升沿触发,两次时间求差就可以得到方波的周期。
不过这里要特别注意一点,如果 CNT 发生溢出(比如 16 位定时器,计数到 65535 就溢出了)
就需要特别处理下,将 CNT 计数溢出考虑进来。

TIM1-TIM17的中断配置

/*	
TIM¶¨Ê±ÖжϷþÎñ³ÌÐò·¶Àý£¬±ØÐëÇåÖжϱêÖ¾
void TIM6_DAC_IRQHandler(void)
{
	if((TIM6->SR & TIM_FLAG_UPDATE) != RESET)
	{
		TIM6->SR = ~ TIM_FLAG_UPDATE;
		//Ìí¼ÓÓû§´úÂë
	}
}
*/
void bsp_SetTIMforInt(TIM_TypeDef* TIMx, uint32_t _ulFreq, uint8_t _PreemptionPriority, uint8_t _SubPriority)
{
	TIM_HandleTypeDef   TimHandle = {0};
	uint16_t usPeriod;
	uint16_t usPrescaler;
	uint32_t uiTIMxCLK;
	
	/* ʹÄÜTIMʱÖÓ */
	bsp_RCC_TIM_Enable(TIMx);
	
    /*-----------------------------------------------------------------------
		bsp.c ÎļþÖÐ void SystemClock_Config(void) º¯Êý¶ÔʱÖÓµÄÅäÖÃÈçÏÂ: 

        System Clock source       = PLL (HSE)
        SYSCLK(Hz)                = 400000000 (CPU Clock)
        HCLK(Hz)                  = 200000000 (AXI and AHBs Clock)
        AHB Prescaler             = 2
 D1 APB3 Prescaler = 2 (APB3 Clock 100MHz)
 D2 APB1 Prescaler = 2 (APB1 Clock 100MHz)
D2 APB2 Prescaler = 2 (APB2 Clock 100MHz)
D3 APB4 Prescaler = 2 (APB4 Clock 100MHz)

 因为 APB1 prescaler != 1, 所以 APB1 上的 TIMxCLK = APB1 x 2 = 200MHz;
因为 APB2 prescaler != 1, 所以 APB2 上的 TIMxCLK = APB2 x 2 = 200MHz;
 APB4 上面的 TIMxCLK 没有分频,所以就是 100MHz;

APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14,LPTIM1
 APB2 定时器有 TIM1, TIM8 , TIM15, TIM16,TIM17

APB4 定时器有 LPTIM2,LPTIM3,LPTIM4,LPTIM5
 ----------------------------------------------------------------------- */
	if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM15) || (TIMx == TIM16) || (TIMx == TIM17))
	{
		/* APB2 定时器时钟 = 200M */
		uiTIMxCLK = SystemCoreClock / 2;
	}
	else	
	{
		/* APB1 定时器 = 200M */
		uiTIMxCLK = SystemCoreClock / 2;
	}

	if (_ulFreq < 100)
	{
		usPrescaler = 10000 - 1;					/* 分频比 = 10000 */
		usPeriod =  (uiTIMxCLK / 10000) / _ulFreq  - 1;		/* 自动重装的值 */
	}
	else if (_ulFreq < 3000)
	{
		usPrescaler = 100 - 1;					/* 分频比 = 100 */
		usPeriod =  (uiTIMxCLK / 100) / _ulFreq  - 1;		/* 自动重装的值 */
98. }
	}
	else	/* APB1 定时器 = 200M */
	{
		usPrescaler = 0;					/* 分频比 = 1 */
		usPeriod = uiTIMxCLK / _ulFreq - 1;	/* 自动重装的值 */
	}

	/* 
       定时器中断更新周期
	*/
	TimHandle.Instance = TIMx;
	TimHandle.Init.Prescaler         = usPrescaler;
	TimHandle.Init.Period            = usPeriod;	
	TimHandle.Init.ClockDivision     = 0;
	TimHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;
	TimHandle.Init.RepetitionCounter = 0;
	TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}

	/* 使能定时器中断 */
	__HAL_TIM_ENABLE_IT(&TimHandle, TIM_IT_UPDATE);
	

	/* 配置 TIM 定时更新中断 (Update) */
	{
        uint8_t irq = 0;/* 中断号, 定义在 stm32h7xx.h */

        if (TIMx == TIM1) irq = TIM1_UP_IRQn;
        else if (TIMx == TIM2) irq = TIM2_IRQn;
        else if (TIMx == TIM3) irq = TIM3_IRQn;
        else if (TIMx == TIM4) irq = TIM4_IRQn;
        else if (TIMx == TIM5) irq = TIM5_IRQn;
        else if (TIMx == TIM6) irq = TIM6_DAC_IRQn;
        else if (TIMx == TIM7) irq = TIM7_IRQn;
        else if (TIMx == TIM8) irq = TIM8_UP_TIM13_IRQn;
        else if (TIMx == TIM12) irq = TIM8_BRK_TIM12_IRQn;
        else if (TIMx == TIM13) irq = TIM8_UP_TIM13_IRQn;
        else if (TIMx == TIM14) irq = TIM8_TRG_COM_TIM14_IRQn;
        else if (TIMx == TIM15) irq = TIM15_IRQn;
        else if (TIMx == TIM16) irq = TIM16_IRQn;
        else if (TIMx == TIM17) irq = TIM17_IRQn;
        else
        {
            Error_Handler(__FILE__, __LINE__);
        }	
        HAL_NVIC_SetPriority((IRQn_Type)irq, _PreemptionPriority, _SubPriority);
        HAL_NVIC_EnableIRQ((IRQn_Type)irq);		
	}
	
	HAL_TIM_Base_Start(&TimHandle);
}

TIM1-TIM17的PWM输出

/*
2. ******************************************************************************************************
3. * 函 数 名: bsp_ConfigTimGpio
4. * 功能说明: 配置 GPIO 和 TIM 时钟, GPIO 连接到 TIM 输出通道
5. * 形 参: GPIOx : GPIOA - GPIOK
6. * GPIO_PinX : GPIO_PIN_0 - GPIO__PIN_15
7. * TIMx : TIM1 - TIM17
8. * 返 回 值: 无
9. ******************************************************************************************************
10. */
void bsp_ConfigTimGpio(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinX, TIM_TypeDef* TIMx)
{
	GPIO_InitTypeDef   GPIO_InitStruct;

	bsp_RCC_GPIO_Enable(GPIOx);

	bsp_RCC_TIM_Enable(TIMx);

	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	GPIO_InitStruct.Alternate = bsp_GetAFofTIM(TIMx);
	GPIO_InitStruct.Pin = GPIO_PinX;
	HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
}
/*
2. ******************************************************************************************************
3. * 函 数 名: bsp_ConfigGpioOut
4. * 功能说明: 配置 GPIO 为推挽输出。主要用于 PWM 输出,占空比为 0 和 100 的情况。
5. * 形 参: GPIOx : GPIOA - GPIOK
6. * GPIO_PinX : GPIO_PIN_0 - GPIO__PIN_15
7. * 返 回 值: 无
8. ******************************************************************************************************
9. */
void bsp_ConfigGpioOut(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinX)
{
	GPIO_InitTypeDef   GPIO_InitStruct;

	bsp_RCC_GPIO_Enable(GPIOx);		/* ʹÄÜGPIOʱÖÓ */

	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	GPIO_InitStruct.Pin = GPIO_PinX;
	HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
}
/*
24. * 函 数 名: bsp_SetTIMOutPWM
25. * 功能说明: 设置引脚输出的 PWM 信号的频率和占空比. 当频率为 0,并且占空为 0 时,关闭定时器,GPIO 输出 0;
26. * 当频率为 0,占空比为 100%时,GPIO 输出 1.
27. * 形 参: GPIOx : GPIOA - GPIOK
28. * GPIO_Pin : GPIO_PIN_0 - GPIO__PIN_15
29. * TIMx : TIM1 - TIM17
30. * _ucChannel:使用的定时器通道,范围 1 - 4
31. * _ulFreq : PWM 信号频率,单位 Hz (实际测试,可以输出 100MHz). 0 表示禁止输出
32. * _ulDutyCycle : PWM 信号占空比,单位: 万分之一。如 5000,表示 50.00%的占空比
33. * 返 回 值: 无
34. ******************************************************************************************************
35. */
void bsp_SetTIMOutPWM(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, TIM_TypeDef* TIMx, uint8_t _ucChannel,
	 uint32_t _ulFreq, uint32_t _ulDutyCycle)
{
	TIM_HandleTypeDef  TimHandle = {0};
	TIM_OC_InitTypeDef sConfig = {0};	
	uint16_t usPeriod;
	uint16_t usPrescaler;
	uint32_t pulse;
	uint32_t uiTIMxCLK;
	const uint16_t TimChannel[6+1] = {0, TIM_CHANNEL_1, TIM_CHANNEL_2, TIM_CHANNEL_3, TIM_CHANNEL_4, TIM_CHANNEL_5, TIM_CHANNEL_6};

	if (_ucChannel > 6)
	{
		Error_Handler(__FILE__, __LINE__);
	}
	
	if (_ulDutyCycle == 0)
	{		
		
		bsp_ConfigGpioOut(GPIOx, GPIO_Pin);			
		GPIOx->BSRRH = GPIO_Pin;		/* PWM = 0 */		
		return;
	}
	else if (_ulDutyCycle == 10000)
	{
		bsp_ConfigGpioOut(GPIOx, GPIO_Pin);		
		GPIOx->BSRRL = GPIO_Pin;		
		return;
	}
	
	
	bsp_ConfigTimGpio(GPIOx, GPIO_Pin, TIMx);	
	if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM15) || (TIMx == TIM16) || (TIMx == TIM17))
	{
		uiTIMxCLK = SystemCoreClock / 2;
	}
	else	
	{
		uiTIMxCLK = SystemCoreClock / 2;
	}

	if (_ulFreq < 100)
	{
		usPrescaler = 10000 - 1;					
		usPeriod =  (uiTIMxCLK / 10000) / _ulFreq  - 1;		
	}
	else if (_ulFreq < 3000)
	{
		usPrescaler = 100 - 1;				
		usPeriod =  (uiTIMxCLK / 100) / _ulFreq  - 1;		
	}
	else	
	{
		usPrescaler = 0;					
		usPeriod = uiTIMxCLK / _ulFreq - 1;	
	}
	pulse = (_ulDutyCycle * usPeriod) / 10000;

	
	HAL_TIM_PWM_DeInit(&TimHandle);
    
	TimHandle.Instance = TIMx;
	TimHandle.Init.Prescaler         = usPrescaler;
	TimHandle.Init.Period            = usPeriod;
	TimHandle.Init.ClockDivision     = 0;
	TimHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;
	TimHandle.Init.RepetitionCounter = 0;
	TimHandle.Init.AutoReloadPreload = 0;
	if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}

	sConfig.OCMode       = TIM_OCMODE_PWM1;
	sConfig.OCPolarity   = TIM_OCPOLARITY_HIGH;
	sConfig.OCFastMode   = TIM_OCFAST_DISABLE;
	sConfig.OCNPolarity  = TIM_OCNPOLARITY_HIGH;
	sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
	sConfig.OCIdleState  = TIM_OCIDLESTATE_RESET;

	sConfig.Pulse = pulse;
	if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TimChannel[_ucChannel]) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
	
	if (HAL_TIM_PWM_Start(&TimHandle, TimChannel[_ucChannel]) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
}

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

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

相关文章

Java | Leetcode Java题解之第36题有效的数独

题目&#xff1a; 题解&#xff1a; class Solution {public boolean isValidSudoku(char[][] board) {int[][] rows new int[9][9];int[][] columns new int[9][9];int[][][] subboxes new int[3][3][9];for (int i 0; i < 9; i) {for (int j 0; j < 9; j) {char …

ThreadLocal 原理及源码详解

什么是ThreadLocal&#xff1f; ThreadLocal 是一种提供线程本地变量&#xff08;也称为线程局部变量&#xff09;的类&#xff0c;这种变量确保了在不同的线程中访问同一个 ThreadLocal 变量时&#xff0c;每个线程会有一个该变量的私有副本&#xff0c;即使多个线程修改了相…

MATLAB环境下基于同步压缩变换重分配算子的瞬时频率估计

瞬时频率是表征非平稳信号特征的重要物理量&#xff0c;已经被广泛应用于桥梁振动检测、地震勘测、机械、电力系统、雷达、通信、医学等各个方面。瞬时频率的概念最早由Carson提出&#xff0c;后来&#xff0c;Gabor提出解析信号的定义&#xff0c;为瞬时频率的研究提供了新的方…

「不羁联盟/XDefiant」4月20号开启服务器测试,游戏预下载安装教程

XDefiant》开启Alpha测试&#xff0c;这是一款免费游玩的快节奏 FPS 竞技游戏&#xff0c;可选择特色阵营&#xff0c;搭配个性化的装备&#xff0c;体验 6v6 对抗或是线性游戏模式。高品质射击竞技端游XDefiant以6v6双边对抗为核心&#xff0c;对局模式分为区域与线性两大类&a…

【Spring】-编程式事务和声明式事务

spring中控制事务的方式有两种&#xff1a;编程式事务和声明式事务&#xff0c;今天我以两种事务出发&#xff0c;对spring中实现事务的EnableTransactionManagement和Transaction两个注解的底层原理进行讨论。 一、编程式事务 什么是编程式事务&#xff1f; 硬编码的方式实现…

数据结构-栈和队列刷题集(长期更新)

文章目录 万能计算器的实现以及源码分析1. leetcode 150 逆波兰表达式求值 万能计算器的实现以及源码分析 /*** 我们尝试写一个完整版的计算器,由于计算机不能很好的识别括号,所以一般要转换为逆波兰表达式求解* 思路解析 :* 1. 输入一个 中缀表达式* 2. 中缀表达式转化为list…

鸡汤笔记-致自己

《你只是看起来很努力》李尚龙 我们看起来每天熬夜&#xff0c;却只是拿着手机点了无数个赞&#xff1b;看起来在图书馆坐了一天&#xff0c;却真的只是坐了一天&#xff1b;看起来买了很多书&#xff0c;只不过晒了个朋友圈&#xff1b;看起来每天很晚地离开办公室&am…

聊聊go语言中的内存填充

写在文章开头 我们都知道数据加载到CPU缓存中可以提升执行性能&#xff0c;所以为了保证每一个结构体中的成员能够完整的被单个CPU核心加载以避免缓存一致性问题而提出内存对齐&#xff0c;这篇文章笔者会从go语言的角度来讨论这个优化机制。 Hi&#xff0c;我是 sharkChili &…

基于Springboot+Vue的Java项目-网上点餐系统开发实战(附演示视频+源码+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &am…

杀鸡焉用牛刀,用unity3D开发数字孪生是大材小用吗?

"杀鸡焉用牛刀"这句话的意思是指使用过于强大或不适合的工具来完成一个简单的任务。而用Unity3D开发数字孪生并不一定是大材小用。 Unity3D是一款功能强大的游戏开发引擎&#xff0c;它可以用于开发各种类型的游戏和交互应用程序。数字孪生是一种基于现实世界对象的虚…

网络靶场实战-PE 自注入

默认的 Windows API 函数&#xff08;LoadLibrary、LoadLibraryEx&#xff09;只能加载文件系统中的外部库&#xff0c;无法直接从内存中加载 DLL&#xff0c;并且无法正确地加载 EXE。有时候&#xff0c;确实需要这种功能&#xff08;例如&#xff0c;不想分发大量文件或者想增…

Redis入门到通关之解决Redis缓存一致性问题

文章目录 ☃️概述☃️数据库和缓存不一致采用什么方案☃️代码实现☃️其他 ☃️概述 由于我们的 缓存的数据源来自于数据库, 而数据库的 数据是会发生变化的, 因此,如果当数据库中 数据发生变化,而缓存却没有同步, 此时就会有 一致性问题存在, 其后果是: 用户使用缓存中的过…

Python 数据结构和算法实用指南(二)

原文&#xff1a;zh.annas-archive.org/md5/66ae3d5970b9b38c5ad770b42fec806d 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第四章&#xff1a;列表和指针结构 我们已经在 Python 中讨论了列表&#xff0c;它们方便而强大。通常情况下&#xff0c;我们使用 Python…

【C语言__基础概念__复习篇8】

目录 前言 一、C语言是什么 二、C语言的发展历史 三、编译器的选择 3.1 编译和链接 3.2 编译器的对比 3.3 VS如何使用 四、main函数 五、关键字 六、字符和ASCII编码 七、字符串和\0 八、转义字符 九、注释 十、数据类型 10.1 数据类型的介绍 10.2 数据类型大小的计…

有哪些网站设计教程

网站设计教程是帮助人们学习如何设计和开发网站的资源&#xff0c;它们提供了从基础知识到高级技巧的全方位指导。无论您是初学者还是经验丰富的开发者&#xff0c;都可以从这些教程中获益。下面是一些广受欢迎的网站设计教程&#xff0c;它们涵盖了各种技术和工具&#xff1a;…

Linux之进程控制进程终止进程等待进程的程序替换替换函数实现简易shell

文章目录 一、进程创建1.1 fork的使用 二、进程终止2.1 终止是在做什么&#xff1f;2.2 终止的3种情况&&退出码的理解2.3 进程常见退出方法 三、进程等待3.1 为什么要进行进程等待&#xff1f;3.2 取子进程退出信息status3.3 宏WIFEXITED和WEXITSTATUS&#xff08;获取…

【C++题解】1345. 玫瑰花圃

问题&#xff1a;1345. 玫瑰花圃 类型&#xff1a;基本运算、小数运算 题目描述&#xff1a; 有一块nn&#xff08;n≥5&#xff0c;且 n 是奇数&#xff09;的红玫瑰花圃&#xff0c;由 nn 个小正方形花圃组成&#xff0c;现要求在花圃中最中间的一行、最中间的一列以及 4 个…

SpringBoot多数据源基于mybatis插件(三)

SpringBoot多数据源基于mybatis插件&#xff08;三&#xff09; 1.主要思路2.具体实现 1.主要思路 MyBatis的插件机制允许你在MyBatis的四大对象&#xff08;Executor、StatementHandler、ParameterHandler和ResultSetHandler&#xff09;的方法执行前后进行拦截&#xff0c;并…

考察自动化立体库应注意的几点

导语 大家好&#xff0c;我是智能仓储物流技术研习社的社长&#xff0c;老K。专注分享智能仓储物流技术、智能制造等内容。 整版PPT和更多学习资料&#xff0c;请球友到知识星球 【智能仓储物流技术研习社】自行下载 考察自动化立体仓库的关键因素&#xff1a; 仓库容量&#x…

linux 中ifconfig 无法使用

1、先看问题 2、搜索 ifconfig 命令&#xff0c;看下该命令在哪 yum search ifconfig 可以看到ifconfig命令在 net-tools.x86_64这个包里。 3、下面开始安装&#xff0c;执行下面的命令 yum install net-tools.x86_64 4、查看是否安装成功 ifconfig 看到上面的ip就说明可以用了…