pwm.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, James Jackson
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * * Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "pwm.h"
33 
35 
36 void PWM_OUT::init(const pwm_hardware_struct_t* pwm_init, uint16_t frequency, uint32_t max_us, uint32_t min_us)
37 {
38  GPIO_InitTypeDef gpio_init_struct;
39  TIM_TimeBaseInitTypeDef tim_init_struct;
40  TIM_OCInitTypeDef tim_oc_init_struct;
41 
42  port_ = pwm_init->GPIO;
43  pin_ = pwm_init->GPIO_Pin;
44 
45  GPIO_PinAFConfig(port_, pwm_init->GPIO_PinSource, pwm_init->GIPO_AF_TIM);
46 
47  gpio_init_struct.GPIO_Pin = pin_;
48  gpio_init_struct.GPIO_Mode = GPIO_Mode_AF;
49  gpio_init_struct.GPIO_Speed = GPIO_Speed_50MHz;
50  gpio_init_struct.GPIO_OType = GPIO_OType_PP;
51  gpio_init_struct.GPIO_PuPd = GPIO_PuPd_DOWN;
52  GPIO_Init(port_, &gpio_init_struct);
53 
54  TIM_TypeDef* TIMPtr = pwm_init->TIM;
55 
56  // calculate timer values
57  // This is dependent on how fast the SystemCoreClock is. (ie will change between stm32fX models)
58  const uint16_t prescaler_default = 42;
59  uint32_t freq_prescale = prescaler_default * 2;
60  uint32_t tim_prescaler = prescaler_default;
61 
62  if (TIMPtr == TIM1 || TIMPtr == TIM8 || TIMPtr == TIM9 || TIMPtr == TIM10 || TIMPtr == TIM11)
63  {
64  // For F4's (possibly others) TIM9-11 have a max timer clk double that of all the other TIMs
65  // compensate for this by doubling its prescaler
66  tim_prescaler = tim_prescaler * 2;
67  }
68  uint32_t timer_freq_hz = SystemCoreClock / freq_prescale;
69 
70  cycles_per_us_ = timer_freq_hz / 1000000; // E^6
71  max_cyc_ = max_us * cycles_per_us_;
72  min_cyc_ = min_us * cycles_per_us_;
73 
74  // init timer
75  TIM_TimeBaseStructInit(&tim_init_struct);
76  tim_init_struct.TIM_Period = (2000000 / frequency) - 1; // 0 indexed
77  tim_init_struct.TIM_Prescaler = tim_prescaler - 1;
78  tim_init_struct.TIM_ClockDivision = TIM_CKD_DIV1; // 0x0000
79  tim_init_struct.TIM_CounterMode = TIM_CounterMode_Up;
80  TIM_TimeBaseInit(pwm_init->TIM, &tim_init_struct);
81 
82  // init output compare
83  TIM_OCStructInit(&tim_oc_init_struct);
84  tim_oc_init_struct.TIM_OCMode = TIM_OCMode_PWM2;
85  tim_oc_init_struct.TIM_OutputState = TIM_OutputState_Enable;
86  tim_oc_init_struct.TIM_OutputNState = TIM_OutputNState_Disable;
87  tim_oc_init_struct.TIM_Pulse = min_cyc_ - 1;
88  tim_oc_init_struct.TIM_OCPolarity = TIM_OCPolarity_Low;
89  tim_oc_init_struct.TIM_OCIdleState = TIM_OCIdleState_Set;
90 
91  switch (pwm_init->TIM_Channel)
92  {
93  case TIM_Channel_1:
94  default:
95  TIM_OC1Init(TIMPtr, &tim_oc_init_struct);
97  CCR_ = &TIMPtr->CCR1;
98  break;
99  case TIM_Channel_2:
100  TIM_OC2Init(TIMPtr, &tim_oc_init_struct);
102  CCR_ = &TIMPtr->CCR2;
103  break;
104  case TIM_Channel_3:
105  TIM_OC3Init(TIMPtr, &tim_oc_init_struct);
107  CCR_ = &TIMPtr->CCR3;
108  break;
109  case TIM_Channel_4:
110  TIM_OC4Init(TIMPtr, &tim_oc_init_struct);
112  CCR_ = &TIMPtr->CCR4;
113  break;
114  }
115 
116  // Set Main Output Enable Bit
117  if (TIMPtr == TIM1 || TIMPtr == TIM8)
118  {
119  TIM_CtrlPWMOutputs(TIMPtr, ENABLE);
120  }
121 
122  TIM_ARRPreloadConfig(TIMPtr, ENABLE);
123  TIM_Cmd(TIMPtr, ENABLE);
124 }
125 
127 {
128  GPIO_InitTypeDef gpio_init_struct;
129  gpio_init_struct.GPIO_Mode = GPIO_Mode_AF;
130  gpio_init_struct.GPIO_Pin = pin_;
131 
132  GPIO_Init(port_, &gpio_init_struct);
133 }
134 
136 {
137  // This could conflict with the GPIO_PinAFConfig above
138  GPIO_InitTypeDef gpio_init_struct;
139  gpio_init_struct.GPIO_Mode = GPIO_Mode_OUT;
140  gpio_init_struct.GPIO_Pin = pin_;
141 
142  GPIO_Init(port_, &gpio_init_struct);
144 }
145 
146 void PWM_OUT::write(float value)
147 {
148  *CCR_ = min_cyc_ + static_cast<uint16_t>((max_cyc_ - min_cyc_) * value);
149 }
150 
151 void PWM_OUT::writeUs(uint16_t value)
152 {
153  *CCR_ = value * cycles_per_us_;
154 }
uint16_t TIM_OutputNState
Definition: stm32f4xx_tim.h:92
void GPIO_PinAFConfig(GPIO_TypeDef *GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)
Changes the mapping of the specified pin.
void TIM_OC4Init(TIM_TypeDef *TIMx, TIM_OCInitTypeDef *TIM_OCInitStruct)
Initializes the TIMx Channel4 according to the specified parameters in the TIM_OCInitStruct.
#define TIM1
Definition: stm32f4xx.h:2078
void TIM_TimeBaseInit(TIM_TypeDef *TIMx, TIM_TimeBaseInitTypeDef *TIM_TimeBaseInitStruct)
Initializes the TIMx Time Base Unit peripheral according to the specified parameters in the TIM_TimeB...
GPIO_TypeDef * port_
Definition: pwm.h:55
void TIM_OC4PreloadConfig(TIM_TypeDef *TIMx, uint16_t TIM_OCPreload)
Enables or disables the TIMx peripheral Preload register on CCR4.
#define TIM_Channel_3
#define TIM9
Definition: stm32f4xx.h:2091
#define TIM_OCMode_PWM2
#define TIM_OutputNState_Disable
#define TIM8
Definition: stm32f4xx.h:2079
void enable()
Definition: pwm.cpp:126
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef *TIM_TimeBaseInitStruct)
Fills each TIM_TimeBaseInitStruct member with its default value.
volatile uint32_t * CCR_
Definition: pwm.h:49
#define TIM_Channel_2
uint32_t SystemCoreClock
#define TIM_Channel_4
void GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_InitStruct)
Initializes the GPIOx peripheral according to the specified parameters in the GPIO_InitStruct.
__IO uint32_t CCR3
Definition: stm32f4xx.h:1694
PWM_OUT()
Definition: pwm.cpp:34
#define TIM_OCPolarity_Low
__IO uint32_t CCR1
Definition: stm32f4xx.h:1692
uint16_t TIM_OCPolarity
Definition: stm32f4xx_tim.h:99
void TIM_Cmd(TIM_TypeDef *TIMx, FunctionalState NewState)
Enables or disables the specified TIM peripheral.
uint16_t GPIO_Pin
Definition: system.h:97
#define TIM_OCPreload_Enable
#define TIM_CKD_DIV1
void TIM_ARRPreloadConfig(TIM_TypeDef *TIMx, FunctionalState NewState)
Enables or disables TIMx peripheral Preload register on ARR.
void TIM_CtrlPWMOutputs(TIM_TypeDef *TIMx, FunctionalState NewState)
Enables or disables the TIM peripheral Main Outputs.
void writeUs(uint16_t value)
Definition: pwm.cpp:151
#define TIM_Channel_1
#define TIM10
Definition: stm32f4xx.h:2092
void TIM_OC1PreloadConfig(TIM_TypeDef *TIMx, uint16_t TIM_OCPreload)
Enables or disables the TIMx peripheral Preload register on CCR1.
TIM_TypeDef * TIM
Definition: system.h:99
uint16_t pin_
Definition: pwm.h:56
TIM Time Base Init structure definition.
Definition: stm32f4xx_tim.h:55
void disable()
Definition: pwm.cpp:135
uint32_t cycles_per_us_
Definition: pwm.h:53
void TIM_OC2Init(TIM_TypeDef *TIMx, TIM_OCInitTypeDef *TIM_OCInitStruct)
Initializes the TIMx Channel2 according to the specified parameters in the TIM_OCInitStruct.
void TIM_OC2PreloadConfig(TIM_TypeDef *TIMx, uint16_t TIM_OCPreload)
Enables or disables the TIMx peripheral Preload register on CCR2.
__IO uint32_t CCR4
Definition: stm32f4xx.h:1695
uint16_t TIM_OutputState
Definition: stm32f4xx_tim.h:89
#define TIM_OutputState_Enable
void TIM_OC1Init(TIM_TypeDef *TIMx, TIM_OCInitTypeDef *TIM_OCInitStruct)
Initializes the TIMx Channel1 according to the specified parameters in the TIM_OCInitStruct.
void TIM_OC3Init(TIM_TypeDef *TIMx, TIM_OCInitTypeDef *TIM_OCInitStruct)
Initializes the TIMx Channel3 according to the specified parameters in the TIM_OCInitStruct.
#define TIM11
Definition: stm32f4xx.h:2093
#define TIM_OCIdleState_Set
uint16_t max_cyc_
Definition: pwm.h:51
void init(const pwm_hardware_struct_t *pwm_init, uint16_t frequency, uint32_t max_us, uint32_t min_us)
Definition: pwm.cpp:36
uint8_t GPIO_PinSource
Definition: system.h:98
void TIM_OC3PreloadConfig(TIM_TypeDef *TIMx, uint16_t TIM_OCPreload)
Enables or disables the TIMx peripheral Preload register on CCR3.
void GPIO_ResetBits(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
Clears the selected data port bits.
TIM Output Compare Init structure definition.
Definition: stm32f4xx_tim.h:84
uint8_t TIM_Channel
Definition: system.h:100
void TIM_OCStructInit(TIM_OCInitTypeDef *TIM_OCInitStruct)
Fills each TIM_OCInitStruct member with its default value.
#define TIM_CounterMode_Up
uint16_t min_cyc_
Definition: pwm.h:52
__IO uint32_t CCR2
Definition: stm32f4xx.h:1693
void write(float value)
Definition: pwm.cpp:146
uint16_t TIM_OCIdleState
uint8_t GIPO_AF_TIM
Definition: system.h:101
GPIO_TypeDef * GPIO
Definition: system.h:96


rosflight_firmware
Author(s): Daniel Koch , James Jackson
autogenerated on Thu Apr 15 2021 05:07:47