platformstm32f10xxx

libSTM32F10x_StdPeriph_Lib_V3.5.0

前言

在做三相逆变的时候,需要软件生成SVPWM波形,具体的算法需要产生三对互补的PWM,这样可以驱动六个开关元件,stm32f103中的TIM1高级定时器支持产生三路互补PWM波形,下面进一步学习。

PWM产生的原理

TIM1OC模块,可以产生PWM波形,具体步骤;

  • 寄存器TIMx CNT每过一个时钟周期就会加1
  • 然后TIMx CNT的值与TIMx CCER进行比较;
  • 最终改变OC上的有效电平;

    以上只需要配置好TIM1的寄存器即可,无需再编程干预,当然可以动态修改TIMx CCER的值,从而改变占空比。可以参考下图;

PWM模式

这里主要对PWM模式进行配置的时候做一下区分,存在以下两种情况;

  • TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  • TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;

那么TIM_OCMode_PWM1TIM_OCMode_PWM2有什么区别呢?

  • TIM_OCMode_PWM1 PWM模式1

    在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平

    在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效 电平(OC1REF=1)。
  • TIM_OCMode_PWM2 PWM模式2

    在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平

    在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。

死区插入和刹车功能

互补PWM还支持插入死区时间,最主要的寄存器是TIMx_BDTR,在标准库中把相关的变量封装到TIM_BDTRInitTypeDef结构体中;具体如下;

  1. typedef struct
  2. {
  3. uint16_t TIM_OSSRState; /*!< Specifies the Off-State selection used in Run mode.
  4. This parameter can be a value of @ref OSSR_Off_State_Selection_for_Run_mode_state */
  5. uint16_t TIM_OSSIState; /*!< Specifies the Off-State used in Idle state.
  6. This parameter can be a value of @ref OSSI_Off_State_Selection_for_Idle_mode_state */
  7. uint16_t TIM_LOCKLevel; /*!< Specifies the LOCK level parameters.
  8. This parameter can be a value of @ref Lock_level */
  9. uint16_t TIM_DeadTime; /*!< Specifies the delay time between the switching-off and the
  10. switching-on of the outputs.
  11. This parameter can be a number between 0x00 and 0xFF */
  12. uint16_t TIM_Break; /*!< Specifies whether the TIM Break input is enabled or not.
  13. This parameter can be a value of @ref Break_Input_enable_disable */
  14. uint16_t TIM_BreakPolarity; /*!< Specifies the TIM Break Input pin polarity.
  15. This parameter can be a value of @ref Break_Polarity */
  16. uint16_t TIM_AutomaticOutput; /*!< Specifies whether the TIM Automatic Output feature is enabled or not.
  17. This parameter can be a value of @ref TIM_AOE_Bit_Set_Reset */
  18. } TIM_BDTRInitTypeDef;

相关的含义看注释可以知道大概意思;这里整理了几个比较重要的变量;

  • 死区时间TIM_DeadTime的计算;TIMx_BDTR的低八位的配置决定了死区的时间;

    UTG[7:0]: 死区发生器设置 (Dead-time generator setup)

    这些位定义了插入互补输出之间的死区持续时间。假设DT表示其持续时间:
DTG[7:5]=0xx => DT=DTG[7:0] × Tdtg Tdtg = TDTS;
DTG[7:5]=10x => DT=(64+DTG[5:0]) × Tdtg Tdtg = 2 × TDTS;
DTG[7:5]=110 => DT=(32+DTG[4:0]) × Tdtg Tdtg = 8 × TDTS;
DTG[7:5]=111 => DT=(32+DTG[4:0])× Tdtg Tdtg = 16 × TDTS;

例:若TDTS = 125ns(8MHZ),可能的死区时间为:

0到15875ns,若步长时间为125ns;

16us到31750ns,若步长时间为250ns;

32us到63us,若步长时间为1us;

64us到126us,若步长时间为2us;

注:一旦LOCK级别(TIMx_BDTR寄存器中的LOCK位)设为1、 2或3,则不能修改这些位。

  • TIM_Break 则表示是否决定使用刹车,如果发生错误,则可以通过刹车,第一时间停止PWM波形的产生,从而保证了系统的安全性;

代码实现

  1. #include "stm32f10x.h"
  2. #include "svpwm_driver.h"
  3. #include "stm32f10x_tim.h"
  4. #include "stm32f10x_it.h"
  5. #include <stdio.h>
  6. #define SVPWM_USE_BDT 1
  7. #define USE_HARD_PWM 1
  8. /**
  9. * @brief Configures the different system clocks.
  10. * @param None
  11. * @retval None
  12. */
  13. void pwm_rcc_init(void)
  14. {
  15. /* TIM1, GPIOA, GPIOB, GPIOE and AFIO clocks enable */
  16. RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA |
  17. RCC_APB2Periph_AFIO |
  18. RCC_APB2Periph_GPIOB, ENABLE);
  19. }
  20. void pwm_cnt_irq_init(void)
  21. {
  22. }
  23. /**
  24. * @brief Configure the TIM1 Pins.
  25. * @param None
  26. * @retval None
  27. * @note
  28. * PA8 /T1_CH1 ---> HIn3
  29. * PA9 /T1_CH2 ---> HIn2
  30. * PA10/T1_CH3 ---> HIn1
  31. * Out2 ---> PA0/ADC0
  32. * Out3 ---> PA1/ADC1
  33. * PB15/T1_CHN3 ---> LIn1
  34. * PB14/T1_CHN2 ---> LIn2
  35. * PB13/T1_CHN1 ---> LIn3
  36. */
  37. void pwm_pin_init(void)
  38. {
  39. GPIO_InitTypeDef GPIO_InitStructure;
  40. /* GPIOA Configuration: Channel 1, 2 and 3 as alternate function push-pull */
  41. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 ;
  42. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  43. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  44. GPIO_Init(GPIOA, &GPIO_InitStructure);
  45. /* GPIOB Configuration: Channel 1N, 2N and 3N as alternate function push-pull */
  46. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  47. GPIO_Init(GPIOB, &GPIO_InitStructure);
  48. }
  49. void pwm_tim_init(void){
  50. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  51. TIM_OCInitTypeDef TIM_OCInitStructure;
  52. TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
  53. // NVIC_InitTypeDef NVIC_InitStructure;
  54. uint16_t TimerPeriod = 0;
  55. uint16_t Channel1Pulse = 0, Channel2Pulse = 0, Channel3Pulse = 0;
  56. /* TIM1 Configuration ---------------------------------------------------
  57. Generate 7 PWM signals with 4 different duty cycles:
  58. TIM1CLK = SystemCoreClock, Prescaler = 0, TIM1 counter clock = SystemCoreClock
  59. SystemCoreClock is set to 72 MHz for Low-density, Medium-density, High-density
  60. and Connectivity line devices and to 24 MHz for Low-Density Value line and
  61. Medium-Density Value line devices
  62. The objective is to generate 7 PWM signal at 17.57 KHz:
  63. - TIM1_Period = (SystemCoreClock / 17570) - 1
  64. The channel 1 and channel 1N duty cycle is set to 50%
  65. The channel 2 and channel 2N duty cycle is set to 50%
  66. The channel 3 and channel 3N duty cycle is set to 50%
  67. The Timer pulse is calculated as follows:
  68. - ChannelxPulse = DutyCycle * (TIM1_Period - 1) / 100
  69. ----------------------------------------------------------------------- */
  70. TimerPeriod = (SYS_FRQ / PWM_FRQ ) - 1;
  71. /* Compute CCR1 value to generate a duty cycle at 50% for channel 1 and 1N */
  72. Channel1Pulse = (uint16_t) (((uint32_t) PWM_DUTY * (TimerPeriod - 1)) / 100);
  73. /* Compute CCR2 value to generate a duty cycle at 37.5% for channel 2 and 2N */
  74. Channel2Pulse = (uint16_t) (((uint32_t) PWM_DUTY * (TimerPeriod - 1)) / 100);
  75. /* Compute CCR3 value to generate a duty cycle at 25% for channel 3 and 3N */
  76. Channel3Pulse = (uint16_t) (((uint32_t) PWM_DUTY * (TimerPeriod - 1)) / 100);
  77. //TIM_DeInit(TIM1);
  78. /* Time Base configuration */
  79. TIM_TimeBaseStructure.TIM_Prescaler = TIM_PSCReloadMode_Update;
  80. //TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//
  81. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned2;
  82. TIM_TimeBaseStructure.TIM_Period = TimerPeriod;
  83. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  84. TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  85. TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
  86. /*
  87. TIM_ClearFlag(TIM1, TIM_FLAG_Update);
  88. TIM_ITConfig(TIM1,TIM_IT_Update, ENABLE);
  89. NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
  90. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
  91. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
  92. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  93. NVIC_Init(&NVIC_InitStructure);
  94. */
  95. /* Channel 1, 2, 3 Configuration in PWM mode */
  96. #if USE_HARD_PWM
  97. /**
  98. TIM_OCMode_PWM1 PWM模式1
  99. 在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平
  100. 在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效 电平(OC1REF=1)。
  101. TIM_OCMode_PWM2 PWM模式2
  102. 在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平
  103. 在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。
  104. */
  105. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  106. TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  107. TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
  108. TIM_OCInitStructure.TIM_Pulse = Channel1Pulse;
  109. TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  110. TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;
  111. TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
  112. TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
  113. TIM_OC1Init(TIM1, &TIM_OCInitStructure);
  114. TIM_OCInitStructure.TIM_Pulse = Channel2Pulse;
  115. TIM_OC2Init(TIM1, &TIM_OCInitStructure);
  116. TIM_OCInitStructure.TIM_Pulse = Channel3Pulse;
  117. TIM_OC3Init(TIM1, &TIM_OCInitStructure);
  118. TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);
  119. TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable);
  120. TIM_OC3PreloadConfig(TIM1,TIM_OCPreload_Enable);
  121. #endif
  122. #if SVPWM_USE_BDT
  123. TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
  124. TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
  125. TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
  126. TIM_BDTRInitStructure.TIM_DeadTime = 30;
  127. TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
  128. TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;
  129. TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;
  130. TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
  131. #endif
  132. TIM_CCPreloadControl(TIM1,ENABLE);
  133. /* TIM1 counter enable */
  134. TIM_Cmd(TIM1, ENABLE);
  135. /* TIM1 Main Output Enable */
  136. TIM_CtrlPWMOutputs(TIM1, ENABLE);
  137. }
  138. void pwm_init(void){
  139. pwm_rcc_init();
  140. pwm_pin_init();
  141. pwm_cnt_irq_init();
  142. pwm_tim_init();
  143. }
  144. int32_t get_pwm_period(void){
  145. return (int32_t)((SYS_FRQ / PWM_FRQ ) - 1);
  146. }
  147. void pwm_reset_duty_cnt(uint8_t index, int16_t cnt){
  148. if(cnt <= 0){
  149. cnt = get_pwm_period()/2;
  150. }
  151. switch(index){
  152. case 1:
  153. TIM1->CCR1 = (uint16_t)cnt;
  154. break;
  155. case 2:
  156. TIM1->CCR2 = (uint16_t)cnt;
  157. break;
  158. case 3:
  159. TIM1->CCR3 = (uint16_t)cnt;
  160. break;
  161. }
  162. }
  163. void pwm_disable(void){
  164. TIM_CtrlPWMOutputs(TIM1, DISABLE);
  165. }
  166. void pwm_enable(void){
  167. TIM_CtrlPWMOutputs(TIM1, ENABLE);
  168. }

以上代码主要实现以下几个功能;

  • IM1定时器时钟,使用中央对齐模式1,则会产生上溢信号;
  • PWM模式设置为TIM_OCMode_PWM1
  • 加入了死区;
  • 占空比 50%;

    具体如下图所示;



参考

http://www.stmcu.org.cn/module/forum/thread-613602-1-1.html

STM32 TIM 多通道互补PWM波形输出配置快速入门的更多相关文章

  1. STM32之PWM波形输出配置总结

    一.   TIMER分类: STM32中一共有11个定时器,其中TIM6.TIM7是基本定时器:TIM2.TIM3.TIM4.TIM5是通用定时器:TIM1和TIM8是高级定时器,以及2个看门狗定时器 ...

  2. CodeIgniter框架——数据库类(配置+快速入门)

    CodeIgniter用户指南——数据库类 数据库配置 入门:用法举例 连接数据库 查询 生成查询结果 查询辅助函数 Active Record 类 事务 表格元数据 字段元数据 自定义函数调用 查询 ...

  3. STM32 TIM1高级定时器配置快速入门

    layout: post tags: [STM32] comments: true 文章目录 layout: post tags: [STM32] comments: true 重点内容 时基单元 计 ...

  4. STM32 时钟树配置快速入门

    layout: post tags: [STM32] comments: true 文章目录 layout: post tags: [STM32] comments: true 为什么要了解时钟树? ...

  5. 【python】pycharm常用配置快速入门。

    俗话说,工欲善其事必先利其器.当我们想从事一门新的语言的时候,最重要的是熟悉其常用的编辑器的配置.刚好这两天在学习python,网上看到一篇比较好的文章,转载过来自己学习一下.感谢:https://s ...

  6. Prometheus入门教程(三):Grafana 图表配置快速入门

    文章首发于[陈树义]公众号,点击跳转到原文:https://mp.weixin.qq.com/s/sA0nYevO8yz6QLRz03qJSw 前面我们使用 Prometheus + Grafana ...

  7. STM32 TIM高级定时器死区时间的计算

    STM32 TIM高级定时器的互补PWM支持插入死区时间,本文将介绍如何计算以及配置正确的死区时间. 文章目录 什么是死区时间? 数据手册的参数 如何计算合理的死区时间? STM32中配置死区时间 什 ...

  8. STM32 HAL库学习系列第4篇 定时器TIM----- 开始定时器与PWM输出配置

    基本流程: 1.配置定时器 2.开启定时器 3.动态改变pwm输出,改变值  HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1); 函数总结: __HAL_TIM ...

  9. 基于STM32F429和Cube的主从定时器多通道输出固定个数的PWM波形

    主从定时器的原理已在上篇博文: 基于STM32F429+HAL库编写的定时器主从门控模式级联输出固定个数PWM脉冲的程序 讲解了,这篇重点就讲如何实现多通道的PWM级联输出. 1.软件环境 Keil5 ...

随机推荐

  1. A Bug's Life POJ - 2492 (种类或带权并查集)

    这个题目的写法有很多,用二分图染色也可以写,思路很好想,这里我们用关于并查集的两种写法来做. 题目大意:输入x,y表示x和y交配,然后判断是否有同性恋. 1 带权并查集: 我们可以用边的权值来表示一种 ...

  2. C++枚举算法

    枚举算法 什么是枚举? 枚举,顾名思义,就是用最笨的方法,去解决问题(暴力枚举),一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数.这两种类型经常(但不总是)重叠. 枚举 ...

  3. 讲讲python中函数的参数

    python中函数的参数 形参:定义函数时代表函数的形式参数 实参:调用函数时传入的实际参数 列如: def f(x,y): # x,y形参 print(x, y) f(1, 2) # 1, 2 实参 ...

  4. java内存模型(JMM)和happens-before

    目录 重排序 Happens-Before 安全发布 初始化安全性 java内存模型(JMM)和happens-before 我们知道java程序是运行在JVM中的,而JVM就是构建在内存上的虚拟机, ...

  5. 【集群实战】fatab开机挂载失败案例

    1. nfs挂载加入fstab案例 NFS客户端实现fstab开机自启动挂载 现象:nfs开机挂载卸载了/etc/fstab中,结果无法开机自动挂载nfs 解答:1. nfs客户端命令放在/etc/r ...

  6. mycat入门部署安装

    mycat是一种比较简单的中间件产品,可以帮助mysql进行分库,同时统一在一个逻辑库. 硬件环境:系统:centos 7.6数据库版本:5.7.19mycat:1.6..6.1 github上下载m ...

  7. CCF NOI1039 2的n次方

    问题链接:CCF NOI1039 2的n次方. 时间限制: 1000 ms  空间限制: 262144 KB 题目描述 对于任意给定的n,计算2的n次方. 输入 输入整数n. 输出 输出2的n次方的值 ...

  8. Next.js 7发布,构建速度提升40%

    Next.js团队发布了其开源React框架的7版本.该版本的Next.js主要是改善整体的开发体验,包括启动速度提升57%.开发时的构建速度提升40%.改进错误报告和WebAssembly支持. \ ...

  9. 怎样借助Python爬虫给宝宝起个好名字

    每个人一生中都会遇到一件事情,在事情出现之前不会关心,但是事情一旦来临就发现它极其重要,并且需要在很短的时间内做出重大决定,那就是给自己的新生宝宝起个名字.因为要在孩子出生后两周内起个名字(需要办理出 ...

  10. Clickhouse 时区转换(下)

    Clickhouse 时区转换续—时区参数转换 天天加班,时间不够,主要还是我太懒,流汗,,,,,,另外如果这篇学习笔记超过100阅读量并有评论,我可能半夜也会爬起来更新的. 相信大家看我之前记录的这 ...