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 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32实战总结:HAL之高级定时器 -> 正文阅读

[嵌入式]STM32实战总结:HAL之高级定时器

关于基本定时器参考:

STM32实战总结:HAL之基本定时器_路溪非溪的博客-CSDN博客

关于PWM(通用定时器)参考:

STM32实战总结:HAL之PWM蜂鸣器_路溪非溪的博客-CSDN博客

高级定时器

基本定时器,只有计数定时,产生中断的功能。

通用定时器,在基本定时器的基础上,增加了输入捕获、PWM波生成等功能。

到了高级定时器,又在通用定时器的基础上增加了一些功能。

重复计数器

通俗来说就是:

在基本定时器和通用定时器中,计数值到了之后就会产生中断。而重复计数可以使得在经过了n次重复计数后才产生中断。

这样的好处有很多,举个简单的例子,之前的每次计数是5ms,为了实现每1s灯闪一下,我们需要在中断函数中重复200次中断。而有了这个重复次数计数器,我们可以很容易地解决这个问题,那就是重复计数次数达到200之后再产生中断,而不必在用户程序中处理。

重复次数计数器是8位的,最高能产生256的重复次数。

CNT是16位的,重复次数计数器是8位的,那么这两个加起来一共就是24位的。

互补输出

互补输出比较好理解,就是波形相反输出。

原来低电平变成高电平,原来高电平变成低电平。

如果原来的占空比是25%,那么互补输出后的占空比就是75%。

互补输出可以有如下应用场景:

比如两个MOS管,要求同一时间,一个导通,一个关闭。

死区

举例说明。

比如两个MOS管,要求同一时间,一个导通,一个关闭。

但是因为硬件没有这么完美,有时候导通和关闭并没有那么及时。可能会导致同一时间,两个MOS管都处于导通状态,这样可能会导致短路。

所以,可以通过波形延迟一小段时间,再去改变极性,这样可以确保同一时间,一个导通,一个关闭。

以下为带死区的PWM波:

理想情况下,互补的PWM波在同一时间,肯定是一个高电平一个低电平,状态同时切换。但是不可能这么理想,所以,就设置一个死区时间。

如以上,在PWM2变成低电平的时候,PW1延迟一段时间后再变成高电平,有同时关闭的状态并没有什么关系,关键是,不能同时导通。

在PWM2变成高电平时,如果PWM1同时变到低电平,有可能因为PWM2已经变高电平,但是PWM1还没来得及变成低电平,导致两个MOS都被导通,从而短路。所以,解决方法是让PWM2延迟变高电平。

所以,像这种通过延迟一段时间来避免同时导通的延迟区间,就叫死区时间。

完美的理解MOS就只有开与关两个状态, 但现实并没有这种美事, 在状态转完时(很短的时间), 第三种部分导通的状态出现。当控制两MOS转变电流方向时, 在很短的时间内, 两MOS都处于第三种状态, 而后果是, 很短时间内有电流从上面的MOS流经下面的MOS到地,而不是流到负载去。这种不是流到负载去的电流是损耗, 费工这还是小事, 大事是它会让MOS产生很大的功耗, 比起在关与闭的两种状态下大得多得多,而这功耗将会转化为热能。

为了避免第三种状态引起的问题, 就发明了死区这东东, 意思是上下两管的控制信号不完全是相反的状态, 而是在关闭一MOS的信号后,Delay一段时间, 后才打开另一MOS,这是错开两MOS管的第三种状态的方法,以避免电流直接流经两MOS管,这就是死区的用意。

死区主要防止桥驱动的时候,上管在开的时候,下管也处在开的状态,这样电流就会从上管直接留到下管。而理想状态下,MOS开关没有延时,这种情况下是可以不用死区的。但是实际情况是MOS开关有一个延时,而死区的作用就是确保这个区间不要出现上下管同时打开的情况。而一般这个死区是设置在下管。

带死区的两个波形的特点是,一个波形的高电平永远在另一个波形低电平的范围内。

刹车功能

举例说明。

当电机出现异常的时候,可以通过设置中断服务程序将其关停。

但是软件的响应速度太慢了,所以,可以将异常检测引脚连接到刹车端口,这样,直接触发硬件来关停电机。

这就是刹车功能,讲究实时性。

配置MX

这里用TIM1_CH1和TIM1_CH1N来进行(带死区的)互补输出。

使用TIM1_BKIN来做刹车功能的输入。

所以,以下重点配置TIM1和PE8/PE9/PE15管脚。

先配置PE8/PE9/PE15管脚(注意不是在GPIO分栏下,而是在Single Mapped Signals下):

输出引脚如果频率较高,比如1MHz,那么可以选择High,当然,选择低或者中等也没问题,虽然速度慢,但是节能。

注意:Modified如果修改了默认值就会打钩,没打勾用的就是默认值。

继续配置TIM1:

确认无误后生成初始化代码。

程序和效果

自动生成的TIM1初始化代码:

/* TIM1 init function */
void MX_TIM1_Init(void)
{

  /* USER CODE BEGIN TIM1_Init 0 */

  /* USER CODE END TIM1_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};

  /* USER CODE BEGIN TIM1_Init 1 */

  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 71;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 100;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 50;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  sBreakDeadTimeConfig.DeadTime = 200;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM1_Init 2 */

  /* USER CODE END TIM1_Init 2 */
  HAL_TIM_MspPostInit(&htim1);

}

PWM开启库函数:

在stm32f1xx_hal_tim.h文件中:

/** @addtogroup TIM_Exported_Functions_Group3 TIM PWM functions
  *  @brief   TIM PWM functions
  * @{
  */
/* Timer PWM functions ********************************************************/
HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim);
HAL_StatusTypeDef HAL_TIM_PWM_DeInit(TIM_HandleTypeDef *htim);
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim);
void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef *htim);
/* Blocking mode: Polling */
HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
HAL_StatusTypeDef HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel);
/* Non-Blocking mode: Interrupt */
HAL_StatusTypeDef HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
HAL_StatusTypeDef HAL_TIM_PWM_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
/* Non-Blocking mode: DMA */
HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length);
HAL_StatusTypeDef HAL_TIM_PWM_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel);

PWM波互补波形开启库函数:

在stm32f1xx_hal_tim_ex.h文件中(很多外设都有一个对应的ex扩展文件,一些较为高级的功能通常会放在扩展文件中):

/** @addtogroup TIMEx_Exported_Functions_Group3 Extended Timer Complementary PWM functions
  *  @brief    Timer Complementary PWM functions
  * @{
  */
/*  Timer Complementary PWM functions  ****************************************/
/* Blocking mode: Polling */
HAL_StatusTypeDef HAL_TIMEx_PWMN_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel);

/* Non-Blocking mode: Interrupt */
HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
/* Non-Blocking mode: DMA */
HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length);
HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel);

我们要用的函数是:

HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel);

HAL_StatusTypeDef HAL_TIMEx_PWMN_Start(TIM_HandleTypeDef *htim, uint32_t Channel);

也就是两个开启函数,开启CH1和CH1N互补输出。

借助示波器查看死区

可以通过示波器查看效果。

将示波器探头分别接到CH1和CH1N,可以看到输出了带有死区的互补波形。

如果改变死区时间,会有相应的改变。

如果死区时间是0,那么会对齐:

根据测试:

设置值255-14us左右,200-4us左右,100-1.5us左右,具体死区时间和MX里填的数值之间并不是线性关系。另外死区时间是设定好后不变的,不会因为频率变化而变化。死区时间设置根据硬件的反应能力来调整,也不能设置太长,同时关闭的时间太久也可能出现一些问题。

以上占空比是50%,可以通过TIM1->CCR1去设置。

刹车功能

初始化时设置的是高电平触发刹车,那么,当PE15输入高电平时,就会触发中断进行保护,即停止输出波形控制。

?

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-09-15 02:09:57  更:2022-09-15 02:10:54 
 
开发: 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年12日历 -2024/12/28 17:26:08-

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