Skip to content

Commit a865de9

Browse files
committed
[NUCLEO_F030R8] Add pwmout api
1 parent 6a30215 commit a865de9

File tree

2 files changed

+163
-1
lines changed

2 files changed

+163
-1
lines changed

libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F030R8/PeripheralNames.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ typedef enum {
6565
} I2CName;
6666

6767
typedef enum {
68-
TIM_1 = (int)TIM1_BASE,
68+
TIM_3 = (int)TIM3_BASE,
6969
TIM_14 = (int)TIM14_BASE,
7070
TIM_16 = (int)TIM16_BASE
7171
} PWMName;
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/* mbed Microcontroller Library
2+
*******************************************************************************
3+
* Copyright (c) 2014, STMicroelectronics
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+
* 1. Redistributions of source code must retain the above copyright notice,
10+
* this list of conditions and the following disclaimer.
11+
* 2. Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation
13+
* and/or other materials provided with the distribution.
14+
* 3. Neither the name of STMicroelectronics nor the names of its contributors
15+
* may be used to endorse or promote products derived from this software
16+
* without specific prior written permission.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28+
*******************************************************************************
29+
*/
30+
#include "pwmout_api.h"
31+
32+
#include "cmsis.h"
33+
#include "pinmap.h"
34+
#include "error.h"
35+
36+
static const PinMap PinMap_PWM[] = {
37+
{PA_7, TIM_14, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_NOPULL, GPIO_AF_4)}, // TIM14_CH1
38+
{PC_7, TIM_3, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_NOPULL, GPIO_AF_0)}, // TIM3_CH2
39+
{PB_6, TIM_16, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_NOPULL, GPIO_AF_2)}, // TIM16_CH1N --> FAIL
40+
{NC, NC, 0}
41+
};
42+
43+
void pwmout_init(pwmout_t* obj, PinName pin) {
44+
// Get the peripheral name from the pin and assign it to the object
45+
obj->pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
46+
47+
if (obj->pwm == (PWMName)NC) {
48+
error("PWM pinout mapping failed");
49+
}
50+
51+
// Enable TIM clock
52+
if (obj->pwm == TIM_3) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
53+
if (obj->pwm == TIM_14) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);
54+
if (obj->pwm == TIM_16) RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM16, ENABLE);
55+
56+
// Configure GPIO
57+
pinmap_pinout(pin, PinMap_PWM);
58+
//pin_mode(pin, PullUp);
59+
60+
obj->pin = pin;
61+
obj->period = 0;
62+
obj->pulse = 0;
63+
64+
pwmout_period_us(obj, 20000); // 20 ms per default
65+
}
66+
67+
void pwmout_free(pwmout_t* obj) {
68+
TIM_TypeDef *tim = (TIM_TypeDef *)(obj->pwm);
69+
TIM_DeInit(tim);
70+
}
71+
72+
void pwmout_write(pwmout_t* obj, float value) {
73+
TIM_TypeDef *tim = (TIM_TypeDef *)(obj->pwm);
74+
TIM_OCInitTypeDef TIM_OCInitStructure;
75+
76+
if (value < 0.0) {
77+
value = 0.0;
78+
} else if (value > 1.0) {
79+
value = 1.0;
80+
}
81+
82+
obj->pulse = (uint32_t)((float)obj->period * value);
83+
84+
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
85+
TIM_OCInitStructure.TIM_Pulse = obj->pulse;
86+
87+
// Configure channel 1
88+
if (obj->pin == PA_7) {
89+
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
90+
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
91+
TIM_OC1PreloadConfig(tim, TIM_OCPreload_Enable);
92+
TIM_OC1Init(tim, &TIM_OCInitStructure);
93+
}
94+
95+
// Configure channel 1N
96+
if (obj->pin == PB_6) {
97+
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
98+
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
99+
TIM_OC1PreloadConfig(tim, TIM_OCPreload_Enable);
100+
TIM_OC1Init(tim, &TIM_OCInitStructure);
101+
}
102+
103+
// Configure channel 2
104+
if (obj->pin == PC_7) {
105+
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
106+
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
107+
TIM_OC2PreloadConfig(tim, TIM_OCPreload_Enable);
108+
TIM_OC2Init(tim, &TIM_OCInitStructure);
109+
}
110+
}
111+
112+
float pwmout_read(pwmout_t* obj) {
113+
float value = 0;
114+
if (obj->period > 0) {
115+
value = (float)(obj->pulse) / (float)(obj->period);
116+
}
117+
return ((value > 1.0) ? (1.0) : (value));
118+
}
119+
120+
void pwmout_period(pwmout_t* obj, float seconds) {
121+
pwmout_period_us(obj, seconds * 1000000.0f);
122+
}
123+
124+
void pwmout_period_ms(pwmout_t* obj, int ms) {
125+
pwmout_period_us(obj, ms * 1000);
126+
}
127+
128+
void pwmout_period_us(pwmout_t* obj, int us) {
129+
TIM_TypeDef *tim = (TIM_TypeDef *)(obj->pwm);
130+
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
131+
float dc = pwmout_read(obj);
132+
133+
TIM_Cmd(tim, DISABLE);
134+
135+
obj->period = us;
136+
137+
TIM_TimeBaseStructure.TIM_Period = obj->period - 1;
138+
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick
139+
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
140+
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
141+
TIM_TimeBaseInit(tim, &TIM_TimeBaseStructure);
142+
143+
// Set duty cycle again
144+
pwmout_write(obj, dc);
145+
146+
TIM_ARRPreloadConfig(tim, ENABLE);
147+
148+
TIM_Cmd(tim, ENABLE);
149+
}
150+
151+
void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
152+
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
153+
}
154+
155+
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
156+
pwmout_pulsewidth_us(obj, ms * 1000);
157+
}
158+
159+
void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
160+
float value = (float)us / (float)obj->period;
161+
pwmout_write(obj, value);
162+
}

0 commit comments

Comments
 (0)