IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32CubeMX——基本定时器、PWM、输入捕获、输出比较、互补式PWM等综合学习(STM32G431RBT6) -> 正文阅读

[嵌入式]STM32CubeMX——基本定时器、PWM、输入捕获、输出比较、互补式PWM等综合学习(STM32G431RBT6)

  • 通用定时器中断配置(Basic timers):

可以在库中判断具体挂在哪个总线上:(stm32g4xx_hal_rcc.h)

void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();      //可以根据这个直接go to 定义,就在stm32g4xx_hal_rcc.h中
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();

我认为TIM6是挂在APB1上面的,所以是80MHz。 这里对TIM6进行配置:

?定时器的频率为80M/(79+1)/(999+1)=1KHz,即1ms一次中断。

这里对于这个Trigger Event Selection不懂。

基本定时器的功能函数(轮询、中断、DMA)?

我先学习中断处理:

1.在main函数中开启中断:

  HAL_TIM_Base_Start_IT(&htim6);

2.重新定义回调函数并添加自己想要实现的功能(我只用LED闪烁简单测试):

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
   HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
}
  • ?通用定时器/高级定时器(General-purpose timers/Advanced-control timers):

或者在stm32G431RB数据手册中寻找 block diagram(框图)

TIM15挂在APB2上:?

?同样开启中断、代码相似。自动生成tim.h和tim.c文件:

#include "tim.h"

TIM_HandleTypeDef htim6;
TIM_HandleTypeDef htim15;

在main函数中:

HAL_TIM_Base_Start_IT(&htim6);
HAL_TIM_Base_Start_IT(&htim15);

?自己编写对应的函数中断:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance==TIM15)
	{
   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
   HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
	}
	else if(htim->Instance==TIM6)
	{
	 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
   HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);
		
	}
}

if中也可以使用htim->Instance == htim1.Instance?例如这里:if(htim->Instance==htim15.Instance)

?对于instance在TIM的定义中可以看到:(可以区分进入中断的不同定时器)

void MX_TIM15_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  htim15.Instance = TIM15;                             //不同的定时器的instance不同
  htim15.Init.Prescaler = 7999;
  htim15.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim15.Init.Period = 9999;
  htim15.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim15.Init.RepetitionCounter = 0;
  htim15.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim15) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim15, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim15, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
}

?PWM配置:

图片来自B站UP:PetraKing

?详细自动重装载见:自动重装载详解

频率的计算是一样的,pwm占空比的设置是Pulse/Counter Period计算的。

?

?初始化只需要在main函数中添加:

HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);

或者:(IT:interruption中断)要对应打开嵌套向量中断控制器

HAL_TIM_PWM_Start_IT(&htim3,TIM_CHANNEL_1);

这里对优先级不配置:有需要的可以配置 。

更改PWM的频率和占空比:

?通过以上可知,PWM的占空比改变的是CCR寄存器的值(不同通道对应不同的CCR),频率的改变对应的是ARR寄存器的值,也就是下图?

?至于CCR寄存器,我们可以看到初始化中,在sConfigOC.Pulse赋值给我们想要的值。

?而在HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1)的定义中,我们能找到?TIM_OC1_SetConfig(htim->Instance, sConfig);类似的函数,而这个函数中的定义中,

?就能找到实际把Pulse的值给了TIM的CCR寄存器。

__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,100);//占空比
__HAL_TIM_SET_AUTORELOAD(&htim3,9999);//周期

?所以就可以通过这两个来改变占空比和周期(频率)。

PWM互补输出:

用不到,先暂时不学:?互补输出配置示例

输出比较实现PWM:Out Compare模式

?图片来自B站UP:PetraKing

?左边是通用定时器,只有一个自动重装载(ARR),但是有多个CCR,所以同一个定时器下面的通道只有一个频率,但是可以有多个占空比。

上图为详细的原理,讲的很清楚,如果看不懂的话建议找一下这个up的视频看一看。

具体配置:

?这里大概说一下自己的看法:中断是肯定要打开的,因为要不断改CCR的值,这里的预分配和你想写的pulse决定了频率,所以这个ARR是没有用的,至于自动重装载还是打开吧,不然会有什么bug吧,我这里预分频后是80M/8000=10Khz,我想配置的500个的高电平和300个低电平,那么总共是800个,实际的频率就是(800/10k)hz。

具体程序:

	HAL_TIM_OC_Start_IT(&htim16,TIM_CHANNEL_1);

__HAL_TIM_GET_COMPARE也是一个宏定义。?
在stm32f4xx_hal_tim.h文件中可以找到。其作用是获取定时器某一通道的捕获/比较寄存器值

等价于 :??HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1);

void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
   if(htim->Instance==htim16.Instance)
	 {
		 if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)
		 {
		   if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_12)==GPIO_PIN_RESET)
			 {
				 
				 __HAL_TIM_SET_COMPARE(&htim16,TIM_CHANNEL_1,__HAL_TIM_GET_COMPARE(&htim16,TIM_CHANNEL_1)+300);
			 }
			 else
			 {
			 	 __HAL_TIM_SET_COMPARE(&htim16,TIM_CHANNEL_1,__HAL_TIM_GET_COMPARE(&htim16,TIM_CHANNEL_1)+500);
			 }	 
		 }	 
	 }
}

?如果不清楚这if怎么写,可以去定义里面找:

去找TIM_HandleTypeDef的定义:

再去找HAL_TIM_ActiveChannel的定义:(就找到了)(枚举)

?

没有示波器,只用万用表简单测试了一下,感觉电压差不多,然后再去找示波器看一下吧,主要是STM32G431RB好像KEIL不支持它的虚拟示波器,我也没逻辑测试仪,然后看玩再放图吧。

?输入捕获模式:?

输入捕获可以对输入的信号的上升沿,下降沿或者双边沿进行捕获,常用的有测量输入信号的脉
宽和测量 PWM 输入信号的频率和占空比这两种。

1.普通捕获:

?main函数中:

  HAL_TIM_IC_Start_IT(&htim4,TIM_CHANNEL_1);

输入捕获的中断回调函数:?

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{

	if(htim->Instance==htim4.Instance)
	 {
		 if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)
		 {
			 PWM_count=__HAL_TIM_GET_COUNTER(&htim4);
			 __HAL_TIM_SET_COUNTER(&htim4,0);
			 frequency=1000000/PWM_count;
		 }	 
	 }
}

?读出当前计数值,清空,频率就是之前配置的80M/(79+1)/__HAL_TIM_GET_COUNTER()

2.PWM输入模式(输入捕获的一种特殊形式):

?在main函数中:

HAL_TIM_PWM_Start_IT(&htim2,TIM_CHANNEL_1);
HAL_TIM_PWM_Start_IT(&htim2,TIM_CHANNEL_2);

?在中断回调函数中:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{

  if(htim->Instance==htim2.Instance)
	 {
	 		 if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)
		 {
				PWM_count1=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1)+1;
		 }	 
		 else if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_2)
		 {
		    PWM_count2=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2)+1;
		 }
	 
	 }
}

由此读出来PWM_count1是总周期数,PWM_count2是低电平数?。

?我认为input capture direct mode是读取整个周期的,把他设置为上升沿就会在高电平来到时触发,input capture indirect mode则也同时开始,然后再下降沿到来时停止计数,而前一个则一直计算到下一个上升沿。(最后结果都需要加1).

剩下还有很多不会的不理解的,以后慢慢加深学习吧。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 21:07:25  更:2022-03-21 21:08:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:35:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码