【蓝桥杯嵌入式】定时器的PWM输出与输入捕获(测量频率与占空比)

本文主要是介绍【蓝桥杯嵌入式】定时器的PWM输出与输入捕获(测量频率与占空比),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【蓝桥杯嵌入式】定时器的PWM输出与脉冲输 入捕获(测量频率与占空比)

  • PWM输出
    • cubemx配置
    • 程序设计
  • 输入捕获
    • cubemx配置
    • 程序设计
  • 真题典例分析

PWM输出

cubemx配置

  PWM输出引脚配置,这里使用PA6和PA7引脚输出两路PWM信号,分别对应的是由TIM16和TIM17的通道1产生的PWM信号,同时配置定时器的预分频系数PSC和自动重装载值CCR,PWM信号频率即为:
frq = 80000000 / (PSC+1)/ (ARR+1)
这里预分频系数为800-1,自动重装载值为100,则频率 frq = 80000000 / 800 / 100 = 1K Hz,占空比预设置为20%

同理 对TIM17通道1进行相关配置,使得输出频率为2KHz,占空比初始化为20%的PWM信号

程序设计

通过cubemx配置后,初始化信号的参数如下所示

//PA6 1KHz 20%
TIM16->PSC = 800-1;
TIM16->ARR = 100-1;
TIM16->CCR1 = 20;//PA7 2KHz 20%
TIM17->PSC = 400-1;
TIM17->ARR = 100-1;
TIM17->CCR1 = 20;

启动PWM输出: 启动TIM16与TIM17的通道1输出PWM信号

HAL_TIM_PWM_Start(&htim16,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);

修改PWM信号占空比: 通过改变TIM16与TIM17通道1的自动重装载值来改变PWM信号的占空比

TIM16->CCR1 = 50;
TIM17->CCR1 = 25;

修改PWM信号的频率:,可以通过改变预分频系数PSC,或者改变自动重装值,但通过修改自动重装载值修改频率的同时会修改占空比。

TIM16->PSC = 400-1;	//将PA6引脚的频率改为2000 Hz 占空比保持不变
TIM17->ARR = 50-1;	//将PA7的频率改为4000 Hz 但占空比变为原来的2倍

输入捕获

  • 输入捕获可以用来测量PWM波的频率与占空比
  • 输入捕获模式下,当通道输入引脚出现指定高电平跳变时,当前CNT的值将被锁存到CCR中

cubemx配置

  通过查看原理图发现,开发板自带2路555信号发生器,分别通过接口J9和J10接到开发板的PB4和PA15端口,这里取下跳线帽,通过杜邦线将PA6、PA7的PWM信号接入到PA15、PB4引脚,用于检测PWM信号的频率与占空比。

  通过配置PB4引脚为TIM3_CH1,开启定时器3,设置预分频系数,配置从模式、触发源及其时钟源,分别设置通道1和通道2为直接模式与间接模式,同时设置为上升沿触发和下降沿触发。

同理对TIM2进行同样的配置

程序设计

初始化开启定时器的通道捕获

HAL_TIM_IC_Start(&htim2,TIM_CHANNEL_1);
HAL_TIM_IC_Start(&htim3,TIM_CHANNEL_1);
HAL_TIM_IC_Start(&htim2,TIM_CHANNEL_2);
HAL_TIM_IC_Start(&htim3,TIM_CHANNEL_2);

频率和占空比的测量

void pwm_process(void)
{//测量频率frq1 = 1000000.0f / (HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1)+1);frq2 = 1000000.0f / (HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1)+1);//测量占空比duty1 = (HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2)+1) * 100.0f / (HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1)+1);duty2 = (HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_2)+1) * 100.0f / (HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1)+1);
}

真题典例分析

  • PA6输出信号占空比通过电位器R37进行调节如图调节
  • 通过B2按键切换高低频模式,并通过LCD进行实时显示

adc数据采集功能函数:

double getAdcVal(ADC_HandleTypeDef *pin)
{double dat;HAL_ADC_Start(pin);dat = HAL_ADC_GetValue(pin);return dat * 3.3 / 4096;	
}

adc业务逻辑程序进程函数: 首先确定adc数据采集周期为200ms采集一次,并进行数字滤波,最后通过电压与占空比的关系,来确定PA6引脚的占空比。

u32 adc_tick = 0;
double adc_sum = 0;
void adc_process(void)
{//adc采集周期 200msif(uwTick - adc_tick < 200)return;adc_tick = uwTick;//adc数字滤波for(uchar i = 0; i < 10; i++)adc_sum += getAdcVal(&hadc2);vr37 = adc_sum / 10.0f;adc_sum = 0;//通过电压改变PWM占空比if(vr37 <= 1.0f)TIM16->CCR1 = 10;else if(vr37 >= 3.0f)TIM16->CCR1 = 85;elseTIM16->CCR1 = (uchar)(37.5 * (vr37 - 1.0f) + 10);
}

按键二: 启动5秒定时,并确定是从高频到低频,还是从低频到高频

if(key[1].single_flag == 1)
{//按键2短按业务逻辑程序//shake_flag = !shake_flag;up_flag = !up_flag;					//从低频到高频标志sec5_flag = !sec5_flag;			//5秒定时标志HAL_TIM_Base_Start_IT(&htim7);	//启动定时器 改变分频系数key[1].single_flag = 0;
}

定时器中断服务函数

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{	if(htim->Instance == TIM7)		//50ms{if(up_flag)psc--;elsepsc++;}
}

PWM进程函数: 频率、占空比的修改与测量

void pwm_process(void)
{//通过修改预分频系数修改频率TIM16->PSC = psc;//检测PWM信号频率frq1 = 1000000.0f / (HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1)+1);frq2 = 1000000.0f / (HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1)+1);//检测PWM信号占空比duty1 = (HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2)+1) * 100.0f / (HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1)+1);duty2 = (HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_2)+1) * 100.0f / (HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1)+1);
}

最后将实时的频率与占空比显示在LCD屏幕

void lcd_process(void)
{if(ui == 0)					//第一个界面显示的内容{sprintf(text,"     Title1 ");LCD_DisplayStringLine(Line1, (unsigned char *)text);	//LCD显示函数sprintf(text,"    frq1:%dHz  ",frq1);LCD_DisplayStringLine(Line3, (unsigned char *)text);	//LCD显示函数sprintf(text,"    duty1:%d%% ",duty1);LCD_DisplayStringLine(Line4, (unsigned char *)text);	//LCD显示函数sprintf(text,"    frq2:%dHz  ",frq2);LCD_DisplayStringLine(Line5, (unsigned char *)text);	//LCD显示函数sprintf(text,"    duty2:%d%% ",duty2);LCD_DisplayStringLine(Line6, (unsigned char *)text);	//LCD显示函数}
}

这篇关于【蓝桥杯嵌入式】定时器的PWM输出与输入捕获(测量频率与占空比)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/889599

相关文章

使用Python实现一个优雅的异步定时器

《使用Python实现一个优雅的异步定时器》在Python中实现定时器功能是一个常见需求,尤其是在需要周期性执行任务的场景下,本文给大家介绍了基于asyncio和threading模块,可扩展的异步定... 目录需求背景代码1. 单例事件循环的实现2. 事件循环的运行与关闭3. 定时器核心逻辑4. 启动与停

使用Python实现一键隐藏屏幕并锁定输入

《使用Python实现一键隐藏屏幕并锁定输入》本文主要介绍了使用Python编写一个一键隐藏屏幕并锁定输入的黑科技程序,能够在指定热键触发后立即遮挡屏幕,并禁止一切键盘鼠标输入,这样就再也不用担心自己... 目录1. 概述2. 功能亮点3.代码实现4.使用方法5. 展示效果6. 代码优化与拓展7. 总结1.

Springboot如何配置Scheduler定时器

《Springboot如何配置Scheduler定时器》:本文主要介绍Springboot如何配置Scheduler定时器问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录Springboot配置Scheduler定时器1.在启动类上添加 @EnableSchedulin

python多种数据类型输出为Excel文件

《python多种数据类型输出为Excel文件》本文主要介绍了将Python中的列表、元组、字典和集合等数据类型输出到Excel文件中,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录一.列表List二.字典dict三.集合set四.元组tuplepython中的列表、元组、字典

Java捕获ThreadPoolExecutor内部线程异常的四种方法

《Java捕获ThreadPoolExecutor内部线程异常的四种方法》这篇文章主要为大家详细介绍了Java捕获ThreadPoolExecutor内部线程异常的四种方法,文中的示例代码讲解详细,感... 目录方案 1方案 2方案 3方案 4结论方案 1使用 execute + try-catch 记录

Android如何获取当前CPU频率和占用率

《Android如何获取当前CPU频率和占用率》最近在优化App的性能,需要获取当前CPU视频频率和占用率,所以本文小编就来和大家总结一下如何在Android中获取当前CPU频率和占用率吧... 最近在优化 App 的性能,需要获取当前 CPU视频频率和占用率,通过查询资料,大致思路如下:目前没有标准的

Spring AI集成DeepSeek实现流式输出的操作方法

《SpringAI集成DeepSeek实现流式输出的操作方法》本文介绍了如何在SpringBoot中使用Sse(Server-SentEvents)技术实现流式输出,后端使用SpringMVC中的S... 目录一、后端代码二、前端代码三、运行项目小天有话说题外话参考资料前面一篇文章我们实现了《Spring

Rust格式化输出方式总结

《Rust格式化输出方式总结》Rust提供了强大的格式化输出功能,通过std::fmt模块和相关的宏来实现,主要的输出宏包括println!和format!,它们支持多种格式化占位符,如{}、{:?}... 目录Rust格式化输出方式基本的格式化输出格式化占位符Format 特性总结Rust格式化输出方式

使用TomCat,service输出台出现乱码的解决

《使用TomCat,service输出台出现乱码的解决》本文介绍了解决Tomcat服务输出台中文乱码问题的两种方法,第一种方法是修改`logging.properties`文件中的`prefix`和`... 目录使用TomCat,service输出台出现乱码问题1解决方案问题2解决方案总结使用TomCat,

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC