【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测量 的相关文章

  • STM32 HAL UART 使用关键思路(无代码,但是很关键)

    1 到底使用哪种方式 xff0c 或者说有哪几种方式 xff1f STM32 中的 UART 允许使用不同的发送 TX 和接收 RX 模式进行配置 xff0c 有什么区别和优势 xff1f xff1a 轮询模式 xff08 简单来说就是无
  • 怎么把PWM信号转为模拟量

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

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

    3线全双工同步传输 带或不带第三根双向数据线的双线单工同步传输 8或16位传输帧格式选择 主或从操作 支持多主模式 8个主模式波特率预分频系数 最大为fPCLK 2 从模式频率 最大为fPCLK 2 主模式和从模式的快速通信 主模式和从模式
  • 魔方机器人之下位机编程---------舵机控制

    1 春天180 舵机 SR 403P 信号线和控制线颜色对应关系 两黑一白 白色信号线 中间电源 另一黑色电源 以上MC9S12XS128单片机通道三产生的周期为20ms 高电平为1 5ms的舵机控制信号 void PWM Init voi
  • 快速学习Stm32舵机控制板控制一个舵机运动

    PWM是什么 PWM 英文名Pulse Width Modulation 是脉冲宽度调制缩写 它是通过对一系列脉冲的宽度进行调制 等效出所需要的波形 包含形状以及幅值 对模拟信号电平进行数字编码 也就是说通过调节占空比的变化来调节信号 能量
  • STM32 基础系列教程 24 - USB_HID_key

    前言 学习stm32 USB接口使用 学会用CUBE工具快速创建USB设备工程及调试 关于usb的相关知道请读者提前准备并学习 当然如果不想深究其中原理的话 跟着本文来操作就可以实现基于USB的设备开发了 需要提示的是 stm32在使用us
  • STM32CubeProg 下载及安装教程

    先点赞 再看博客 顺便点个关注鼓励一下 如果文章看完 觉得不错的话可以点个收藏 日后不迷路 STM32CubeProg 下载及安装教程 1 前言 1 1 基本介绍 1 2 主要特点 1 3 准备工作 2 软件下载 2 1 Java 官网下载
  • STM32 使用TIM2_CH1(PA15) 输出10K PWM信号

    PA15 gt TIM2 Remap CH1 1 apb init RCC APB1PeriphClockCmd RCC APB1Periph TIM2 ENABLE RCC APB2PeriphClockCmd RCC APB2Perip
  • mega328p-ADC,PWM,UART驱动

    ADC驱动 函 数 名 Ai Init 函数功能 Ai端口初始化 输入参数 void 输出参数 void 返 回 值 void 参考文档 void 创 件 人 程强刚 创建日期 2016 02 09 修改历史 void Ai Init vo
  • stm32f407 usb cdc设备无法启动问题

    最新要做一个项目 要求基于STM32F407实现USB CDC设备 首先想到的就是直接用STM32CUBEMX工具来生成 OK 话不多说 直接上过程 RCC配置 Sys配置 USB OTG FS配置 USB DEVICE配置 时钟配置 然后
  • STM32CubeMX—串口空闲中断+DMA接收

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

    1 定时器种类 注 主要使用通用定时器 2 通用计时器特点描述 说明 四个通道互不影响 3 定时器中断触发条件 4 定时器计数模式 分为向上 向下 向上向下模式 5 通用定时器作用用途 测量输入输出波长度等 说明 每个定时器完全独立没有共享
  • 带编码器的直流减速电机——基于STM32F407

    首先 什么是编码器 编码器是将信号或数据进行编制 转换为可用以通讯 传输和存储的信号形式的设备 在这里 编码器就是能够将电机的转动信息 比如转速 转动角度等 转换为脉冲信号的设备 按照原理可分为 常见的 光电编码器 光学式 和霍尔编码器 磁
  • STM32 基础系列教程 45 - FSMC_LCD_Touch

    前言 上一节我们完成了用 STM32F4的 FSMC接口来控制 TFTLCD的显示的操作 其实正点原子的探索者F4开发板带的屏幕支持触摸操作 笔者用的是4 3寸的电容触摸屏 本节我们继续实验 来完成基于STM32的触摸屏的实验 关于触摸屏的
  • [STM32系列]一、HAL库的串口中断接收

    STM32系列 一 HAL库的串口中断任意长度接收 1 前言 2 回调函数 3 HAL库中断接收函数使用 1 前言 HAL即硬件抽象层 英语 Hardware Abstraction Layer 实现了不同硬件的统一接口操作 这就极大的简化
  • STM32 基础系列教程 50 – MbedTls

    前言 mbed TLS 以前称为PolarSSL 是TLS和SSL协议的实现 并且需要相应的加密算法和支持代码 这是双重许可与Apache许可证 2 0版 与GPLv2许可也可 网站上指出 mbed TLS的目标是 易于理解 使用 集成和扩
  • STM32 HAL库更改中断向量表的偏移地址

    以STM32F767为例 打开system stm32f7xx c文件 定位VECT TAB OFFSET 更改此宏定义的值 即可更改偏移量
  • STM32通用定时器使用详解

    1 通用定时器基本介绍 通用定时器包括TIM2 TIM3 TIM4和TIM5 STM32通用定时器是一个通过可编程预分频器驱动的16位自动装载计数器构成 每个定时器都是完全独立的 没有互相共享任何资源 它们可以一起同步操作 定时器可以进行定
  • STM32的HAL中实现单按、长按和双按功能

    我正在尝试实现单击 双击和长按功能来执行不同的功能 到目前为止 我已经理解了单击和长按的逻辑 但我不知道如何检测双击 至于代码 我使用计数器实现了单击和长按 但代码仅停留在第一个 if 条件上 bool single press false

随机推荐