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

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             = 2D1 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,LPTIM1APB2 定时器有 TIM1, TIM8 , TIM15, TIM16,TIM17APB4 定时器有 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.mzph.cn/news/813138.shtml

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

相关文章

Traefik不同版本之间的差异?

Traefik 是一款流行的开源反向代理和负载均衡器&#x1f504;&#xff0c;它被广泛用于容器化&#x1f4e6;和微服务架构&#x1f310;中。从其首次发布以来&#xff0c;Traefik 经历了多个版本的更新&#xff0c;每个版本都带来了重要的新特性和改进&#x1f6e0;️。在本文中…

GitHub repository - Watch - Star - Fork - Follow

GitHub repository - Watch - Star - Fork - Follow References 眼睛图标旁边写着 Watch 字样。点击这个按钮就可以 Watch 该仓库&#xff0c;今后该仓库的更新信息会显示在用户的公开活动中。Star 旁边的数字表示给这个仓库添加 Star 的人数。这个数越高&#xff0c;代表该仓库…

【数据结构】习题之链表的回文结构和相交链表

&#x1f451;个人主页&#xff1a;啊Q闻 &#x1f387;收录专栏&#xff1a;《数据结构》 &#x1f389;前路漫漫亦灿灿 前言 今日的习题是关于链表的&#xff0c;分别是链表的回文结构和相交链表的判断。 链表的回文结构 题目为&#xff1a;链表的回文结…

sysbench MySQL性能测试

目录 1. QPS&&TPS 1.1 数据库启动到现在的运行时间(秒) 1.2 查询量 1.3 status命令直接显示出QPS 1.4 每秒输出数据库状态(累加) 2. sysbench 测试工具 3. OLTP MySQL测试 3.1 普通参数 3.2 支持的lua脚本 3.3 脚本参数 3.4 测试数据准备 3.5 进行测试 3.…

服务器数据恢复—不同型号服务器RAID5数据恢复策略有何不同?

RAID5作为应用最广泛的raid阵列级别之一&#xff0c;在不同型号服务器中的RAID5出现故障后&#xff0c;处理方法也不同。 RAID5阵列级别是无独立校验磁盘的奇偶校验磁盘阵列&#xff0c;采用数据分块和独立存取技术&#xff0c;能在同一磁盘上并行处理多个访问请求&#xff0c;…

大话设计模式——22.访问者模式(Visitor Pattern)

简介 表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作 UML图 应用场景 适用于数据结构相对稳定且算法易于变化的系统&#xff0c;该模式将数据结构和作用于结构上的操作之间的耦合解脱开&#xff0c;使得操作集合…

react 初学增删改查购物车案例

界面 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>react-购物车案例</title><…

WebService反向代理的配置和

WebService反向代理的配置和 家都知道&#xff0c;联网上有很多被墙了的网站&#xff0c;虽然这是让人很伤心的一件事情&#xff0c;但还好咱们有办法绕过这个限制&#xff0c;那就是使用IP代理。今天我就来给大家讲讲如何配置和使用WebService反向代理。 什么是WebService反向…

maven之pom中的build标签

1、build标签分类 1.1、全局配置&#xff08;project build&#xff09; 针对整个项目的所有情况都有效。 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"htt…

常见的垃圾回收器(上)

文章目录 Serial垃圾回收器 SerialOld垃圾回收器PS POParNewCMS 常见的垃圾回收器&#xff08;下&#xff09; Serial垃圾回收器 SerialOld垃圾回收器 Serial是一种单线程串行回收年轻代的垃圾回收器 回收年代和算法 年轻代&#xff1a;复制算法 老年代&#xff1a;标记-整…

Autosar初学习

前言&#xff1a; 已下面这张图为例&#xff0c;进行Autosar初学习中SWC设计。 简单解释一下这张图&#xff0c;S-R Interface中 Receive Port的话有两个 分别是输入SeatSwitch和PowerManagement; Sender Port有一个 DialLED&#xff0c; 有一个标定量Calibration 1、Simulink…

一些知识点小细节

当遇到的问题有关逆序输出&#xff0c;可以转换一下思想&#xff0c;就是使用for循环的时候&#xff0c;i的初始化是从数组或者是字符串的最后一个&#xff0c;然后注意设置循环结束的条件&#xff0c;最重要的是不要忘记i--;而不是I&#xff1b; 注意&#xff1a;当要逆序输出…

OpenHarmony实例:【资源管理器】

介绍 本工程使用[ohos.app.ability.common] 接口中的AbilityContext类&#xff0c;获取资源管理器resourceManager&#xff0c;使用[ohos.resourceManager.d.ts]中的接口&#xff0c;展示了格式化字符串查询、基于指定屏幕分辨率查询媒体资源、获取系统资源管理对象等基础功能…

Trinamic步进电机控制模块助力抗击疟疾

疟疾是世界上最致命的传染病之一。这种疾病在亚洲、非洲和南美洲的热带地区十分常见&#xff0c;越早诊断&#xff0c;越能有效治疗。标准疟疾检测需要由训练有素的技术人员在显微镜下检测血液样本&#xff0c;以确认是否存在疟原虫&#xff0c;以及疟原虫的数量和类型。仅在印…

弱口令入侵FE企业管理平台【附口令】

漏洞描述 飞企互联-FE企业运营管理平台 druid路径弱口令&#xff0c;攻击者可能通过尝试弱口令&#xff0c;非法进入系统&#xff0c;恶意操作或者收集信息进一步攻击利用。 漏洞复现 1、Fofa app"飞企互联-FE企业运营管理平台"2、零零信安 (html_banner360浏览…

【python】基于pyttsx3库的字符串转音频文件

一、源码 import pyttsx3 engine pyttsx3.init() engine.setProperty(volume, 0.8) engine.setProperty(rate, 150) engine.save_to_file("Hello, World!", "output.mp3") engine.runAndWait()二、介绍 使用pyttsx3库&#xff0c;设置声音与速率&#x…

聊一聊一些关于npm、pnpm、yarn的事

前言 整理了最近的闲聊&#xff0c;话题是前端各个包管理器&#xff0c;如果分享的不对或者有异议的地方&#xff0c;麻烦请及时告诉我~ 耐心看完&#xff0c;也许你会有所收获~ 概述 本文阅读时间&#xff1a;10-15分钟左右&#xff1b; 难度&#xff1a;初级&#xff0c…

【回溯】Leetcode 51. N 皇后【困难】

N 皇后 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回所有不同的 n 皇后问题 的解决方案。…

C# Web应用调用EXE文件的一些实践

目录 需求 范例运行环境 可执行文件的设计 调用可执行文件方法 RunExecuteFile RunShellExecuteFile 方法的区别 WEB调用举例 小结 需求 最近同事使用Python开发了一款智能文字转语音的程序&#xff0c;经讨论部署在WINDOWS环境服务器下&#xff0c;因此需要生成目标…

Pytest实践:Python测试技术基础知识!

一、简介 在软件开发领域&#xff0c;确保代码的正确性和稳健性至关重要。这就是软件测试发挥作用的地方。Python 是一种通用且广泛使用的编程语言&#xff0c;提供了大量的工具和库来帮助测试过程。 其中&#xff0c;Pytest就是一个很好用的测试框架&#xff0c;可以在 Pyth…