aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2016-09-01 16:03:57 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2016-09-01 16:03:57 +0200
commit64b906b7d7cca07d0f51030ca300cc2dc33f0ee4 (patch)
tree89d125e853753d44661a951d05911d7385d441f5
parent07090d14e0dafc3b5b564a339cd615c2d9864125 (diff)
downloadstm32f103-playground-64b906b7d7cca07d0f51030ca300cc2dc33f0ee4.tar.gz
stm32f103-playground-64b906b7d7cca07d0f51030ca300cc2dc33f0ee4.tar.bz2
stm32f103-playground-64b906b7d7cca07d0f51030ca300cc2dc33f0ee4.tar.xz
stm32f103-playground-64b906b7d7cca07d0f51030ca300cc2dc33f0ee4.zip
o A couple of stepper motor driver applications.
-rw-r--r--apps/stepper2/CMakeLists.txt3
-rw-r--r--apps/stepper2/stepper2.cpp226
2 files changed, 138 insertions, 91 deletions
diff --git a/apps/stepper2/CMakeLists.txt b/apps/stepper2/CMakeLists.txt
index 67d76b0..928bbfd 100644
--- a/apps/stepper2/CMakeLists.txt
+++ b/apps/stepper2/CMakeLists.txt
@@ -2,6 +2,7 @@ add_executable(stepper2.elf stepper2.cpp
${STM32F10X_STDPERIPH_LIB}/Libraries/CMSIS/CM3/CoreSupport/core_cm3.c
${STM32F10X_STDPERIPH_LIB}/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c
${STM32F10X_STDPERIPH_LIB}/Libraries/STM32F10x_StdPeriph_Driver/src/misc.c
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_adc.c
${STM32F10X_STDPERIPH_LIB}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_rcc.c
${STM32F10X_STDPERIPH_LIB}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_spi.c
${STM32F10X_STDPERIPH_LIB}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_gpio.c
@@ -14,7 +15,7 @@ target_include_directories(stepper2.elf PUBLIC
$<TARGET_PROPERTY:playground,INTERFACE_INCLUDE_DIRECTORIES>
)
target_compile_definitions(stepper2.elf PUBLIC ${STM32F10X_STDPERIPH_DEFINES})
-target_link_libraries(stepper2.elf tinyprintf)
+target_link_libraries(stepper2.elf tinyprintf m)
set_target_properties(stepper2.elf PROPERTIES LINK_FLAGS "-nostartfiles -T${CMAKE_SOURCE_DIR}/cmake/stm32.ld")
add_extra_commands(stepper2.elf)
diff --git a/apps/stepper2/stepper2.cpp b/apps/stepper2/stepper2.cpp
index 75603ac..dea3088 100644
--- a/apps/stepper2/stepper2.cpp
+++ b/apps/stepper2/stepper2.cpp
@@ -1,5 +1,7 @@
+#include <inttypes.h>
#include <stdint.h>
#include <stm32f10x.h>
+#include <stm32f10x_adc.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_dma.h>
@@ -28,89 +30,66 @@ void HardFault_Handler_C(uint32_t *hardfault_args) {
volatile bool dma_busy;
-struct motor_t {
+struct hbridge_t {
GPIO_TypeDef *gpio_port;
const uint16_t ah;
const uint16_t al;
};
-static struct motor_t motor_a = {
- gpio_port: GPIOA,
- ah : GPIO_Pin_0,
- al : GPIO_Pin_1,
-};
-
-TIM_TypeDef *pwm_timer = TIM2;
-
-struct apb_bus_1 {
-};
-struct apb_bus_2 {
+struct motor_t {
+ TIM_TypeDef *pwm_timer;
+ ADC_TypeDef *adc;
+ uint8_t adc_channel;
+ GPIO_TypeDef *shunt_gpio_port;
+ uint16_t shunt_pin;
+ hbridge_t a;
+ hbridge_t b;
};
-template<typename apb_bus>
-class apb_ctrl {
-public:
- static void RCC_PeriphClockCmd(uint32_t peripherals, FunctionalState functionalState) {
- RCC_PeriphClockCmd(apb_bus{}, peripherals, functionalState);
- }
-
-private:
- static void RCC_PeriphClockCmd(apb_bus_1, uint32_t peripherals, FunctionalState functionalState) {
- RCC_APB1PeriphClockCmd(peripherals, functionalState);
- }
-
- static void RCC_PeriphClockCmd(apb_bus_2, uint32_t peripherals, FunctionalState functionalState) {
- RCC_APB2PeriphClockCmd(functionalState, functionalState);
- }
-
-public:
- static void RCC_PeriphResetCmd(uint32_t peripherals, FunctionalState functionalState) {
- RCC_PeriphResetCmd(apb_bus{}, peripherals, functionalState);
- }
-
-private:
- static void RCC_PeriphResetCmd(apb_bus_1, uint32_t peripherals, FunctionalState functionalState) {
- RCC_APB1PeriphResetCmd(peripherals, functionalState);
- }
-
- static void RCC_PeriphResetCmd(apb_bus_2, uint32_t peripherals, FunctionalState functionalState) {
- RCC_APB2PeriphResetCmd(functionalState, functionalState);
- }
+static struct motor_t motor = {
+ pwm_timer: TIM2,
+ adc: ADC1,
+ adc_channel: ADC_Channel_4,
+ shunt_gpio_port: GPIOA,
+ shunt_pin: GPIO_Pin_4, // ADC12_IN4
+ a: {
+ gpio_port: GPIOA,
+ ah : GPIO_Pin_0,
+ al : GPIO_Pin_1,
+ },
+ b: {
+ gpio_port: GPIOA,
+ ah : GPIO_Pin_2,
+ al : GPIO_Pin_3,
+ },
};
-template<typename apb_bus, uint32_t peripheral>
-class apb_device {
-public:
- static void reset() {
- apb_ctrl<apb_bus>::RCC_PeriphResetCmd(peripheral, ENABLE);
- apb_ctrl<apb_bus>::RCC_PeriphResetCmd(peripheral, DISABLE);
- }
-
- static void enable() {
- apb_ctrl<apb_bus>::RCC_PeriphClockCmd(peripheral, ENABLE);
- }
-
- static void disable() {
- apb_ctrl<apb_bus>::RCC_PeriphClockCmd(peripheral, DISABLE);
- }
-};
+volatile bool adc_ready;
+volatile uint16_t adc_current_sample;
-template<typename apb_bus, uint32_t peripheral>
-class gpio_port : public apb_device<apb_bus, peripheral> {
-public:
-};
+void adc_init(const motor_t &motor) {
-class gpio_port_a : public gpio_port<apb_bus_2, RCC_APB2Periph_GPIOA> {
-};
+ GPIO_InitTypeDef init;
+ GPIO_StructInit(&init);
+ init.GPIO_Mode = GPIO_Mode_AIN;
+ init.GPIO_Pin = motor.shunt_pin;
+ init.GPIO_Speed = GPIO_Speed_50MHz;
+ GPIO_Init(motor.shunt_gpio_port, &init);
-class gpio_port_b : public gpio_port<apb_bus_2, RCC_APB2Periph_GPIOB> {
-};
+ adc_ready = false;
-class gpio_port_c : public gpio_port<apb_bus_2, RCC_APB2Periph_GPIOC> {
-};
+ ADC_InitTypeDef adcInit = {
+ ADC_Mode: ADC_Mode_Independent,
+ ADC_ScanConvMode: DISABLE,
+ ADC_ContinuousConvMode: DISABLE,
+ ADC_ExternalTrigConv: ADC_ExternalTrigConv_None,
+ ADC_DataAlign: ADC_DataAlign_Right,
+ ADC_NbrOfChannel: 1
+ };
+ ADC_Init(motor.adc, &adcInit);
-class tim2 : public apb_device<apb_bus_1, RCC_APB1Periph_TIM2> {
-};
+ ADC_RegularChannelConfig(motor.adc, motor.adc_channel, 1, ADC_SampleTime_13Cycles5);
+}
void timer_init(TIM_TypeDef *tim, uint16_t period) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
@@ -141,7 +120,7 @@ void pwm_control(TIM_TypeDef *tim, uint16_t pulse) {
TIM_OC2PreloadConfig(tim, TIM_OCPreload_Enable);
}
-void gpio_init(GPIO_TypeDef* gpio_port, uint16_t pins, bool use_af) {
+void gpio_init(GPIO_TypeDef *gpio_port, uint16_t pins, bool use_af) {
GPIO_InitTypeDef init;
GPIO_StructInit(&init);
init.GPIO_Mode = use_af ? GPIO_Mode_AF_PP : GPIO_Mode_Out_PP;
@@ -154,6 +133,8 @@ volatile bool run = true;
bool use_gpio = false;
+volatile uint32_t millis = 0;
+
int main() {
SystemInit();
@@ -161,15 +142,29 @@ int main() {
dbg_printf("stepper2\n");
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
- NVIC_InitTypeDef NVIC_InitStruct = {
- NVIC_IRQChannel: DMA1_Channel3_IRQn,
- NVIC_IRQChannelPreemptionPriority: 0,
- NVIC_IRQChannelSubPriority: 0,
- NVIC_IRQChannelCmd: ENABLE,
- };
- NVIC_Init(&NVIC_InitStruct);
- NVIC_EnableIRQ(DMA1_Channel3_IRQn);
+ {
+ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
+ NVIC_InitTypeDef NVIC_InitStruct = {
+ NVIC_IRQChannel: DMA1_Channel3_IRQn,
+ NVIC_IRQChannelPreemptionPriority: 0,
+ NVIC_IRQChannelSubPriority: 0,
+ NVIC_IRQChannelCmd: ENABLE,
+ };
+ NVIC_Init(&NVIC_InitStruct);
+ NVIC_EnableIRQ(DMA1_Channel3_IRQn);
+ }
+
+ {
+ NVIC_InitTypeDef NVIC_InitStruct = {
+ NVIC_IRQChannel: ADC1_2_IRQn,
+ NVIC_IRQChannelPreemptionPriority: 0,
+ NVIC_IRQChannelSubPriority: 0,
+ NVIC_IRQChannelCmd: ENABLE,
+ };
+
+ NVIC_Init(&NVIC_InitStruct);
+ NVIC_EnableIRQ(ADC1_2_IRQn);
+ }
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO
| RCC_APB2Periph_GPIOA
@@ -188,23 +183,41 @@ int main() {
uint16_t pulse = 500;
- gpio_init(motor_a.gpio_port, motor_a.ah | motor_a.al, !use_gpio);
- timer_init(pwm_timer, period);
- pwm_control(pwm_timer, pulse);
+ gpio_init(motor.a.gpio_port, motor.a.ah | motor.a.al, !use_gpio);
+ timer_init(motor.pwm_timer, period);
+ pwm_control(motor.pwm_timer, pulse);
+
+ TIM_ARRPreloadConfig(motor.pwm_timer, ENABLE);
+ TIM_Cmd(motor.pwm_timer, ENABLE);
+
+ adc_init(motor);
+
+ ADC_Cmd(motor.adc, ENABLE);
- TIM_ARRPreloadConfig(pwm_timer, ENABLE);
- TIM_Cmd(pwm_timer, ENABLE);
+ dbg_printf("Starting calibration\n");
+ ADC_ResetCalibration(motor.adc);
+ while (ADC_GetResetCalibrationStatus(motor.adc));
+ ADC_StartCalibration(motor.adc);
+ while (ADC_GetCalibrationStatus(motor.adc));
+ ADC_SoftwareStartConvCmd(motor.adc, ENABLE);
+ dbg_printf("ADC calibration done\n");
+
+ if (SysTick_Config(SystemCoreClock / 1000)) {
+ dbg_printf("SysTick_Config failed.\n");
+ }
+
+ ADC_ITConfig(motor.adc, ADC_IT_EOC, ENABLE);
while (run) {
static bool on = false;
if (use_gpio) {
if (on) {
- GPIO_SetBits(motor_a.gpio_port, motor_a.ah);
- GPIO_SetBits(motor_a.gpio_port, motor_a.al);
+ GPIO_SetBits(motor.a.gpio_port, motor.a.ah);
+ GPIO_SetBits(motor.a.gpio_port, motor.a.al);
} else {
- GPIO_ResetBits(motor_a.gpio_port, motor_a.ah);
- GPIO_ResetBits(motor_a.gpio_port, motor_a.al);
+ GPIO_ResetBits(motor.a.gpio_port, motor.a.ah);
+ GPIO_ResetBits(motor.a.gpio_port, motor.a.al);
}
on = !on;
} else {
@@ -219,10 +232,30 @@ int main() {
pulse = 0;
}
- pwm_timer->CCR1 = pulse;
- pwm_timer->CCR2 = period - pulse;
+ motor.pwm_timer->CCR1 = pulse;
+ motor.pwm_timer->CCR2 = period - pulse;
}
}
+
+ static int adc_count = 0;
+ if (adc_ready) {
+ adc_ready = false;
+ ADC_SoftwareStartConvCmd(motor.adc, ENABLE);
+ adc_count++;
+ }
+
+ static uint32_t last_ms = 0;
+ if (millis > last_ms + 1000) {
+ // adc_current_sample = [0, 4096]
+ int a = adc_current_sample * 25; // [0, 102400). 3.3V = 102400
+ int b = a * 33; // [0, 307200). 3.3V = 3379200
+ int c = b / 1024; // [0, 3300]
+ int voltage_mv = c;
+ dbg_printf("adc_count=%d, value=%" PRIu16 "\n", adc_count, adc_current_sample);
+ dbg_printf("voltage=%d\n", voltage_mv);
+ adc_count = 0;
+ last_ms += 1000;
+ }
}
return 0;
@@ -239,3 +272,16 @@ void DMA1_Channel3_IRQHandler() {
dma_busy = false;
}
}
+
+extern "C"
+void ADC1_2_IRQHandler() {
+ adc_ready = true;
+ adc_current_sample = ADC_GetConversionValue(motor.adc);
+
+ ADC_ClearITPendingBit(motor.adc, ADC_IT_EOC | ADC_IT_AWD | ADC_IT_JEOC);
+}
+
+extern "C"
+void SysTick_Handler() {
+ millis++;
+}