You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
parafraktor-stm32/Src/stepper.c

137 lines
4.3 KiB
C

#include "stm32g0b1xx.h"
#include "stepper.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "SEGGER_SYSVIEW.h"
#include "uart_dmx.h"
stepper_T steppers[] = {
{.en_port=GPIOC, .en_pin=11, .dir_port=GPIOB, .dir_pin=4, .step_port=GPIOE, .step_pin=2, .home_port=GPIOF, .home_pin=3}
};
void set_pins(stepper_T* stp){
// Set direction (00: Input, 01: Output, 10: Alternate function, 11: Analog)
// enable
stp->en_port->MODER &= ~(0x3 << (stp->en_pin * 2));
stp->en_port->MODER |= (0x1 << (stp->en_pin * 2));
// direction
stp->dir_port->MODER &= ~(0x3 << (stp->dir_pin * 2));
stp->dir_port->MODER |= (0x1 << (stp->dir_pin * 2));
// step
stp->step_port->MODER &= ~(0x3 << (stp->step_pin * 2));
stp->step_port->MODER |= (0x1 << (stp->step_pin * 2));
// home switch
stp->home_port->MODER &= ~(0x3 << (stp->home_pin * 2));
// make shure stepper is enabled (active low)
stp->en_port->BSRR |= (0x1 << (stp->en_pin + 16));
}
void stepper_gpio_init(){
RCC->IOPENR |= RCC_IOPENR_GPIOBEN;
RCC->IOPENR |= RCC_IOPENR_GPIOCEN;
RCC->IOPENR |= RCC_IOPENR_GPIOEEN;
RCC->IOPENR |= RCC_IOPENR_GPIOFEN;
for(uint8_t i=0; i<(sizeof(steppers)/sizeof(stepper_T)); i++){
set_pins(&steppers[i]);
}
}
void Timer1_Init(void) {
// Step 1: Enable the clock for Timer 1
RCC->APBENR2 |= RCC_APBENR2_TIM1EN; // Enable TIM1 clock
// Step 2: Configure Timer 1
TIM1->PSC = 64;
TIM1->ARR = 100;
TIM1->DIER |= TIM_DIER_UIE; // Enable update interrupt
// Step 3: Enable Timer 1
TIM1->CR1 |= TIM_CR1_CEN; // Enable the timer
// Step 4: Enable the interrupt in NVIC
NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn); // Enable Timer 1 interrupt in NVIC
}
// Timer 1 Update Interrupt Handler
void TIM1_BRK_UP_TRG_COM_IRQHandler(void) {
SEGGER_SYSVIEW_RecordEnterISR();
if (TIM1->SR & TIM_SR_UIF) { // Check if the update interrupt flag is set
TIM1->SR &= ~TIM_SR_UIF; // Clear the update interrupt flag
//SEGGER_SYSVIEW_PrintfHost("do step");
do_steps();
}
SEGGER_SYSVIEW_RecordExitISR();
}
void do_steps(){
static uint32_t timer = 0;
timer++;
for(uint8_t i=0; i<(sizeof(steppers)/sizeof(stepper_T)); i++){
if(steppers[i].ramp_to_speed != 0 && steppers[i].next_step == timer){
/* ramp speed */
if(steppers[i].speed < steppers[i].ramp_to_speed)
steppers[i].speed++;
if(steppers[i].speed > steppers[i].ramp_to_speed)
steppers[i].speed--;
/* limit max speed */
if(steppers[i].speed >= 100)
steppers[i].speed=100;
if(steppers[i].speed <= -100)
steppers[i].speed=-100;
/* get direction from sign */
if(steppers[i].speed>0)
steppers[i].dir_port->BSRR |= 1 << steppers[i].dir_pin;
if(steppers[i].speed<0)
steppers[i].dir_port->BSRR |= 1 << (steppers[i].dir_pin + 16);
/* calculate next step time */
steppers[i].next_step = timer + (1000/abs(steppers[i].speed)); // should be safe for 1 overflow
/* step and count position */
steppers[i].step_port->ODR ^= 1 << steppers[i].step_pin;
if(steppers[i].speed>0)
steppers[i].pos++;
if(steppers[i].speed<0)
steppers[i].pos--;
printf("pos %d\tspeed %d\n", steppers[i].pos, steppers[i].speed);
}
if(steppers[i].homed){
int16_t old_ramp_to_speed = steppers[i].ramp_to_speed;
steppers[i].ramp_to_speed = rxBuffer[1] - steppers[i].pos;
if(steppers[i].ramp_to_speed != 0 && old_ramp_to_speed == 0)
steppers[i].next_step = timer+1;
}
else{
if(~(steppers[i].home_port->IDR) & (1 << steppers[i].home_pin)){
steppers[i].pos = 0;
steppers[i].homed = 1;
steppers[i].speed = 0;
steppers[i].ramp_to_speed = 0;
printf("homed %d\n", i);
}
else{
if(steppers[i].ramp_to_speed == 0){
steppers[i].ramp_to_speed=10;
steppers[i].next_step = timer+1;
}
}
}
}
}