【STM32Cube HAL】输入捕获(六)——PWM测量

2023-05-16

对于PWM的捕获,我这里一共使用两种方法实现:第一种是PWM输入模式,采用一个定时器的两个通道(通道一和通道二),配置从模式为复位模式,没有进行溢出处理,所以需要考虑捕获的最低频率;第二种是普通的输入捕获模式,采用一个定时器一个通道,有进行溢出处理,所以没有最低频率的限制。

 实验内容:使用高级定时器输入捕获测量PWM的周期和占空比。

 一、原理图

—— —— —— —— —— —— —— ——PWM输入模式—— —— —— —— —— —— —— ——

 二、 CubeMX配置

Step1.打开 STM32CubeMX,点击“New Project”,选择芯片型号,STM32F103VETx。

 Step2.选择时钟源,并配置时钟树。选择Crystal/Ceramic Resonator,并配置系统时钟为72M。

  

Step3.配置SYS,我们这里选择的是Serial Wire。(正常情况配置不配置不影响,debug可以使用。但是你不可以把这两个引脚用于其他复用功能,如果用于其他复用功能,debug就不起作用了。)

 

Step4.串口配置(主要为了在串口调试助手显示测试的时间),因为没有用到中断和DMA所以我们就不过多讲解。

 

 Step5.接下来进行最主要的定时器配置。首先我们先配置PWM信号,用于等会捕获实验。我这边选用的定时器3通道4(PB1引脚),如原理图所示也就是我们蓝灯的控制IO口,我们更直观的观察到PWM信号的情况。

 

 Step6.定时器输入捕获参数的配置,因为我们使用的PWM捕获模式,我选用的定时器8通道1和通道2.(更改一下:直接模式和间接模式应该叫直连模式和非直连模式)

  到这里关于相关参数配置基本已经完成,只需要根据之前文章《STM32Cube HAL:GPIO输入/输出(一)》Step4-Step8,设置相关工程参数和生成代码。

 三、添加功能代码

1、我们等会会向串口调试助手发送数据,进行实验结果的验证。 发送数据我们采用printf函数,所有需要重定向c库函数printf到串口。注意使用时需要在keil设置中勾选微库(use mircolib),同时需要添加头文件#include <stdio.h>。重定向代码如下(usart.c)

//重定向c库函数printf到串口DEBUG_USART,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
	/* 发送一个字节数据到串口DEBUG_USART */
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);	
	
	return (ch);
}

//重定向c库函数scanf到串口DEBUG_USART,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{		
	int ch;
	HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 1000);	
	return (ch);
}

 2、定义相关变量,以及使能相关定时器和计数处理代码(main.c)

宏定义、全局变量
#define cnt_clk 72000000/(71+1)//计数器频率
#define arr 65535//自定重装载值   
uint32_t CCR1,CCR2,end_flag;//存捕获寄存器获取的值的变量
float duty_cycle,frequency;//频率,占空比
//使能相关定时器以及计数结果处理代码
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_4);//开启PWM输出,不需要中断
HAL_TIM_IC_Start_IT(&htim8,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim8,TIM_CHANNEL_2);
	
 //处理代码
 while (1)
  {
		if(end_flag==1)
		{
			printf("\r\n频率=%.2fHZ,占空比=%.2f%%\r\n",frequency,duty_cycle);
			end_flag=0;
		}
		HAL_Delay(1000);
  }

  3、中断回调函数(捕获中断)(main.c)

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	  /*PWM 信号的第一个上升沿时,定时器产生中断,计数器,CCR寄存器被复位。
    当下降沿到来时,IC2 会捕获,对应的是脉冲宽度测量,但不会产生中断。当第
	  二个上升沿时,IC1会捕获,对应的是周期宽度测量,而且会再次进入中断*/
				//printf("0");
				CCR1=HAL_TIM_ReadCapturedValue(&htim8, TIM_CHANNEL_1);
				if(CCR1!=0)
				{
					CCR2=HAL_TIM_ReadCapturedValue(&htim8, TIM_CHANNEL_2);
					frequency=(float)cnt_clk/(CCR1+1);
					duty_cycle=(float)(CCR2+1)*100/(CCR1+1);	
					end_flag=1;
				}
				else
				{
					frequency=0;
					duty_cycle=0;
				}
}

 关于PWM模式主要需要的注意有两点:

一、PWM模式只能使用通道1和通道2,PWM输入模式工作原理如下图:

二、用于捕获的定时器时基设置,需要考虑到能捕获的最低频率。

公式:能捕获的最低频率f=(时钟频率/(分频系数PSC+1))/(重装载值ARR+1)

 结合这次配置的时基,可得:f=(72000000/(71+1))/(65535+1)=15.2HZ

—— —— —— —— —— —— —— 普通的输入捕获模式—— —— —— —— —— —— ——

 二、 CubeMX配置

step1-step4与上面PWM输入模式一致

step5.同样是配置PWM信号,用于等会捕获实验。我这边选用的同样是定时器3通道4(PB1引脚)。唯一不同的是,为了验证溢出处理的功能,我做了一点小改动。配置为频率20HZ,占空比为60%的PWM。

 

 

 Step6.定时器输入捕获参数的配置,因为我们使用的普通的输入捕获模式,我选用的定时器8通道1。这里没有用到从模式,所以不进行配置。捕获频率最低频率设置为33.3HZ,增加使能更新中断,对溢出进行处理,解决了最小捕获频率的限制。因此我们可以捕获小于33.3HZ的频率。

到这里关于串口参数配置基本已经完成,只需要根据之前文章《STM32Cube HAL:GPIO输入/输出(一)》Step4-Step8,设置相关工程参数和生成代码。

 三、添加功能代码

1、我们等会会向串口调试助手发送数据,进行实验结果的验证。 发送数据我们采用printf函数,所有需要重定向c库函数printf到串口。注意使用时需要在keil设置中勾选微库(use mircolib),同时需要添加头文件#include <stdio.h>。(代码同上)

2、定义相关变量,以及使能相关定时器和处理代码(main.c)

//宏定义,及全局变量
#define cnt_clk 72000000/(71+1)//计时器时钟
#define arr 30000  //重装载寄存器的值,根据实际情况设置。
uint32_t ccr_cnt1,ccr_cnt2;//存捕获寄存器获取的值的变量
uint32_t Period_cnt,Period_cnt1,Period_cnt2;//更新中断次数以及存放更新中断次数的变量
uint32_t ic_flag,end_flag;//触发标志位,捕获完成标志
float duty_cycle,frequency;//频率,占空比
//使能相关定时器功能
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_4);//开启PWM输出,不需要中断
	
__HAL_TIM_CLEAR_IT(&htim8,TIM_CHANNEL_1);//清除更新中断标志位,防止一使能就进入更新中断
HAL_TIM_Base_Start_IT(&htim8);//使能定时器,更新中断
HAL_TIM_IC_Start_IT(&htim8,TIM_CHANNEL_1);//使能定时器,使能捕获输入以及捕获中断
//捕获数据处理
while (1)
  {
   
		if(end_flag==1)//捕获完成标志位
		{
     	duty_cycle=(float)(Period_cnt1*(arr+1)+ccr_cnt1+1)*100/(Period_cnt2*(arr+1)+ccr_cnt2+1);
  		frequency=(float)cnt_clk/(Period_cnt2*(arr+1)+ccr_cnt2+1);
			printf("\r\n频率=%.2fHZ,占空比=%.2f%%\r\n",frequency,duty_cycle);
			end_flag=0;//复位捕获完成标志
			
		}
  }

 3、中断回调函数(更新中断、捕获中断)(main.c)

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	Period_cnt++;
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
				switch(ic_flag)//触发标志位判断
				{
					case 0://第一个上升沿捕获
					{
						__HAL_TIM_SET_COUNTER(&htim8,0);//清除计数器的计数
						ccr_cnt1=0;//初始化相关变量
						ccr_cnt2=0;
						Period_cnt=0;
						Period_cnt1=0;
						Period_cnt2=0;
						__HAL_TIM_SET_CAPTUREPOLARITY(&htim8,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING); //设置成下降沿触发	
						ic_flag=1;//更改捕获标志位,进入case1进行相关变量的处理。
						break;
					}
					case 1://第一个下降沿捕获
					{
						ccr_cnt1=__HAL_TIM_GET_COMPARE(&htim8,TIM_CHANNEL_1);//获取存放在CCR寄存器的值(捕获值)
						Period_cnt1=Period_cnt;//获取第一个下降沿到来时的进入更新中断的次数
						__HAL_TIM_SET_CAPTUREPOLARITY(&htim8,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);	//设置成上升沿触发	
						ic_flag=2;	//更改捕获标志位,进入case2进行相关变量的处理
						break;
					}
					case 2://第二个上沿捕获	
					{
						ccr_cnt2=__HAL_TIM_GET_COMPARE(&htim8,TIM_CHANNEL_1);//获取存放在CCR寄存器的值(捕获值)
						Period_cnt2=Period_cnt;//获取第二个上升沿到来时的进入更新中断的次数
						ic_flag=0;	//更改捕获标志位,进入case0进行相关变量的处理。
						end_flag=1;//捕获完成标志
						break;
					}	
					default:
					break;
				}
}

 关于普通的输入模式捕获PWM。主要工作流程:

1、第一次捕获到上升沿,计数器清零,存捕获寄存器值的变量清零,存中断次数的变量清零。改变触发边沿为下降沿触发,并将触发标志位为设置为1,使下次下降沿触发时,能进行相对应的处理。

2、第一次捕获到下降沿,将捕获寄存器(CCR寄存器)的值,中断次数存入相应的变量。同时更改触发边沿为上升沿触发,并将触发标志位为设置为2,使下次上升沿触发时,能进行相对应的处理。

3、第二次捕获到上升沿,再次将捕获寄存器(CCR寄存器)的值,中断次数存入相应的变量。将触发标志设置为0,目的为能够循环捕获。同时捕获完成标志为置1。

 4、在main函数中,使用在while循环,使用if语句进行捕获标志的轮询,从而在捕获完成后进行相应的数据处理。

虽然目前代码的配置以及实验结果是没有问题的。但是在调试时候,碰到一个比较疑惑的问题,ARR的设置影响了捕获的准确性,比如在设置为999和1000的时候,同样是存在溢出的,也进行了溢出处理。但是AAR=999时候频率不稳定,AAR=1000频率正常。暂时还是没法找到合理的解释。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【STM32Cube HAL】输入捕获(六)——PWM测量 的相关文章

  • HAL库 STM32 串口通信函数

    HAL UART Receive IT串口 xff01 HAL UART Receive IT amp UART1 Handler u8 aRxBuffer RXBUFFERSIZE HAL UART Receive IT函数使用的时候 简
  • PWM互补输出,以及死区时间计算

    本文基于野火例程进行解说 实验内容 本次实验输出一对互补的pwm波 xff0c 且进行死区时间的计算说明 代码 互补输出对应的定时器初始化代码 xff1a bsp advance tim c span class token comment
  • 怎么把PWM信号转为模拟量

    有一个测量位置变化的位置传感器 xff0c 用万用表电压档测量传感器的输出信号 xff0c 结果显示的是模拟量信号 xff0c 即位置和信号输出大小呈线性关系 但是 xff0c 用示波器 xff08 Picoscope 4227 xff09
  • 舵机PWM信号转互斥继电器开关信号

    本文由 麦粒电子 撰写 xff0c 并提供相应产品服务 叙述 上次的PWM转继电器开关方案得到大家的不少好评 xff08 博客链接 xff09 xff0c 但是发现有些玩家需要一路PWM同时去控制两路继电器开关通断 xff0c 并且两者是互
  • STM32 HAL 串口收发(无DMA,中断接收)

    STM32CUBE配置 一 使用printf发送数据 xff0c 在usart c中添加代码串口重定向 USER CODE BEGIN 0 include lt stdio h gt ifdef GNUC define PUTCHAR PR
  • HAL_UART_IRQHandler(UART_HandleTypeDef *huart)里面的中断接收函数(作者自己生成的函数代码,中间有关闭接收中断,但是原子教程中没有关闭中断的语句注意区别)

    前言 1 UART Receive IT 2 HAL UART Receive 3 HAL UART Receive IT 前言 看了很长时间串口中断的HAL库 xff0c 最容易混淆的就是函数的名称 xff0c 主要集中在UART Rec
  • STM32F103控制PCA9685产生16路PWM波控制SG90舵机

    STM32控制PCA9685产生16路PWM波控制SG90舵机 如果你能点开这篇文章 xff0c 说明你已经知道PCA9685是多么强大 xff0c NXP公司原本做这片芯片是为了提供给LED使用 xff0c 在其官方文档里也能看到所有PW
  • 基于HAL库的stm32f103c8t6的快速开发笔记(简易版)—— 5、STM32的PWM输出(附舵机控制)

    1 概念了解 首先了解到 PWM生成是在通用定时器的基础上配置的 每个通用定时器都有多路通道输出PWM信号 这里以TIM4 定时器4 为例 在图形配置面板找到TIM4的通道一作为PWM输出管脚 其管脚为PB6 打开左侧定时器配置面板 可以看
  • 直流电机控制 pwm 和 pid 算法

    下面的文章是我转载的 所以作者若是看到不允许转载 请给我留言或给我邮件 lushiliangcsdn 163 com 我会立即删除 转载原因 这篇文章把pid 算法解释的很详细 我担心以后这篇文章无故删除 才转载到我这边的 谢谢 转载来源于
  • 使用HAL库开发STM32:系统时间基础及进阶使用

    文章目录 目的 基础使用 进阶使用 总结 目的 HAL库默认提供了系统时间 系统时间默认情况下由SysTick定时器计数产生 系统时间一方面用于HAL库自身调用 另一方面用户也可以使用 为开发带来便利 本文提到的相关使用主要应用于未使用OS
  • mega328p-ADC,PWM,UART驱动

    ADC驱动 函 数 名 Ai Init 函数功能 Ai端口初始化 输入参数 void 输出参数 void 返 回 值 void 参考文档 void 创 件 人 程强刚 创建日期 2016 02 09 修改历史 void Ai Init vo
  • STM32 基础系列教程 33 - Lwip_tcp_client

    前言 学习stm32 以太网接口使用 及LWIP使用 用LWIP快速实现一个TCP client网络通信功能 学会基本LWIP的网络数据接收与发送功能 让初学者了解lwip 关于Lwip更多的功能介绍将会在后期的STM32 中级教程中介绍
  • stm32f407 usb cdc设备无法启动问题

    最新要做一个项目 要求基于STM32F407实现USB CDC设备 首先想到的就是直接用STM32CUBEMX工具来生成 OK 话不多说 直接上过程 RCC配置 Sys配置 USB OTG FS配置 USB DEVICE配置 时钟配置 然后
  • 使用HAL库开发STM32:使用Timer输出PWM信号

    文章目录 目的 基础说明 输出PWM信号 总结 目的 单片机输出PWM信号是很常用的一种功能需求 STM32中通常使用Timer来输出PWM信号 这篇文章将对相关内容做个说明 基础说明 在使用Timer输出PWM信号需要了解一些Timer的
  • STM32CubeMX—串口空闲中断+DMA接收

    一 实验说明 实验平台 STM32F103C8T6 实验内容 使用串口一空闲中断结合DMA 完成不定长数据接收 STM32的串口接收数据的方式 1 轮询接收 所谓轮询 就是在主函数中判断接收完成的标志位 举个不太恰当例子 就比如 此时你正在
  • STM32Cube学习(2)——定时器中断

    0 引言 单片机 STM32F407ZGT6 仿真器 ST Link V2 开发环境 STM32CubeIDE 1 10 1 功能说明 采用定时器中断的方式 实现LED按照定时器频率闪烁 前情提要 STM32Cube学习 1 点灯 配置 参
  • 使用HAL库开发STM32:GPIO口基础使用与外部中断

    文章目录 目的 GPIO口基础使用 基础说明 初始化设置 输出与控制 读取端口值 GPIO口与外部中断 总结 目的 对于MCU来说GPIO口的使用是最基础的内容 仅使用GPIO口和延时等 就可以完成很多功能了 GPIO口基础使用 基础说明
  • STM32 基础系列教程 30 - 文件系统

    前言 学习stm32中FATFS 文件系统的基础使用 学会文件的打开及读写删除等基本操作 理解文件系统基本概念 示例详解 基于硬件平台 STM32F10C8T6最小系统板 MCU 的型号是 STM32F103c8t6 使用stm32cube
  • [STM32系列]一、HAL库的串口中断接收

    STM32系列 一 HAL库的串口中断任意长度接收 1 前言 2 回调函数 3 HAL库中断接收函数使用 1 前言 HAL即硬件抽象层 英语 Hardware Abstraction Layer 实现了不同硬件的统一接口操作 这就极大的简化
  • BeagleBone Black (v4.14) 上的 PWM 芯片到引脚映射

    关于如何在较新版本的内核上配置 Beaglebone 进行 PWM 的信息非常少 我按照以下指示进行操作BeagleBone Black v4 14 上的 PWM https stackoverflow com questions 5020

随机推荐