diff --git a/keil_project/MyDrivers/MyUart.c b/keil_project/MyDrivers/MyUart.c new file mode 100644 index 0000000..b907c68 --- /dev/null +++ b/keil_project/MyDrivers/MyUart.c @@ -0,0 +1,67 @@ +#include "MyUart.h" +#include "stm32f1xx_ll_bus.h" +#include "stm32f1xx_ll_usart.h" +#include "stm32f1xx_ll_gpio.h" + +void MyUart_Conf(USART_TypeDef * uart_port, int baudrate){ + + LL_USART_InitTypeDef My_LL_Usart_Init_Struct; + + if (uart_port==USART1) { + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1); + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA); + LL_GPIO_InitTypeDef tx; + tx.Mode = LL_GPIO_MODE_ALTERNATE; + tx.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + tx.Speed = LL_GPIO_SPEED_FREQ_LOW; + tx.Pin = LL_GPIO_PIN_9; + LL_GPIO_Init(GPIOA, &tx); + } + if (uart_port==USART2){ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART2); + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA); + LL_GPIO_InitTypeDef tx; + tx.Mode = LL_GPIO_MODE_ALTERNATE; + tx.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + tx.Pull = LL_GPIO_PULL_UP; + tx.Speed = LL_GPIO_SPEED_FREQ_LOW; + tx.Pin = LL_GPIO_PIN_2; + LL_GPIO_Init(GPIOA, &tx); + } + if (uart_port==USART3){ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART3); + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOC); + LL_GPIO_InitTypeDef tx; + tx.Mode = LL_GPIO_MODE_ALTERNATE; + tx.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + tx.Pull = LL_GPIO_PULL_UP; + tx.Speed = LL_GPIO_SPEED_FREQ_LOW; + tx.Pin = LL_GPIO_PIN_10; + LL_GPIO_Init(GPIOC, &tx); + } + + My_LL_Usart_Init_Struct.BaudRate = baudrate; + My_LL_Usart_Init_Struct.DataWidth = LL_USART_DATAWIDTH_8B ; + My_LL_Usart_Init_Struct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; + My_LL_Usart_Init_Struct.OverSampling = LL_USART_OVERSAMPLING_16; + My_LL_Usart_Init_Struct.Parity = LL_USART_PARITY_NONE; + My_LL_Usart_Init_Struct.StopBits = LL_USART_STOPBITS_1; + My_LL_Usart_Init_Struct.TransferDirection = LL_USART_DIRECTION_TX_RX ; + + LL_USART_Init(uart_port,&My_LL_Usart_Init_Struct); + LL_USART_Enable(uart_port); + + /*int periph_speed; + if (uart_port==USART1) periph_speed = 36000000; + if (uart_port==USART2) periph_speed = 72000000; + if (uart_port==USART3) periph_speed = 72000000; + + LL_USART_SetBaudRate(uart_port, periph_speed, baudrate); +*/} + +void MyUart_send_bytes(USART_TypeDef * uart_port,char* buf, int len){ + for(int i = 0; i < len; i++){ + LL_USART_TransmitData8(uart_port, buf[i]); + while(!LL_USART_IsActiveFlag_TXE(uart_port)); + } +} diff --git a/keil_project/MyDrivers/MyUart.h b/keil_project/MyDrivers/MyUart.h new file mode 100644 index 0000000..6641c92 --- /dev/null +++ b/keil_project/MyDrivers/MyUart.h @@ -0,0 +1,10 @@ +#ifndef MYUART_H +#define MYUART_H + +#include "stm32f1xx_ll_usart.h" + +void MyUart_Conf(USART_TypeDef * uart_port, int baudrate); + +void MyUart_send_bytes(USART_TypeDef * uart_port,char* buf, int len); + +#endif \ No newline at end of file diff --git a/keil_project/Services/DcMotor.c b/keil_project/Services/DcMotor.c new file mode 100644 index 0000000..da755eb --- /dev/null +++ b/keil_project/Services/DcMotor.c @@ -0,0 +1,67 @@ +#include "DcMotor.h" +#include "stm32f1xx_ll_gpio.h" +#include "stm32f1xx_ll_bus.h" +#include "stm32f1xx_ll_tim.h" + +#define ARR_DC_MOTOR 20000 +void DC_MOTOR_Init(void) { + // use TIM2 since it has pa1 at channel 2 output + // setup timer 2 + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); + LL_TIM_InitTypeDef tim_init; + // todo check switching behavior of the mosfet to determine period of switching + tim_init.Prescaler = 71; + tim_init.Autoreload = ARR_DC_MOTOR - 1; + tim_init.ClockDivision=LL_TIM_CLOCKDIVISION_DIV1; + tim_init.CounterMode=LL_TIM_COUNTERMODE_UP; + tim_init.RepetitionCounter=0; + LL_TIM_Init(TIM2, &tim_init); + + // setup gpio + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA); + LL_GPIO_InitTypeDef servo_gpio_init; + servo_gpio_init.Pin = LL_GPIO_PIN_1; + servo_gpio_init.Mode = LL_GPIO_MODE_ALTERNATE; + servo_gpio_init.Speed = LL_GPIO_SPEED_FREQ_LOW; + servo_gpio_init.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + LL_GPIO_Init(GPIOA, &servo_gpio_init); + + // setup output compare + LL_TIM_OC_InitTypeDef oc_init; + oc_init.OCMode = LL_TIM_OCMODE_PWM1; + oc_init.OCState = LL_TIM_OCSTATE_ENABLE; + oc_init.OCNState = LL_TIM_OCSTATE_ENABLE; + oc_init.CompareValue = 0; // off at start + oc_init.OCPolarity = LL_TIM_OCPOLARITY_HIGH; + oc_init.OCNPolarity = LL_TIM_OCPOLARITY_LOW; + oc_init.OCIdleState = LL_TIM_OCIDLESTATE_LOW; + oc_init.OCNIdleState = LL_TIM_OCIDLESTATE_HIGH; + LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH2, &oc_init); + LL_TIM_EnableCounter(TIM2); + + // init gpio for direction (sense) pin + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA); + + + LL_GPIO_InitTypeDef pa2_init_conf; + pa2_init_conf.Mode = LL_GPIO_MODE_OUTPUT; + pa2_init_conf.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + pa2_init_conf.Speed = LL_GPIO_SPEED_FREQ_LOW; + pa2_init_conf.Pin = LL_GPIO_PIN_2; + LL_GPIO_Init(GPIOA, &pa2_init_conf); + +} + +void DC_MOTOR_SetSpeed(int speed){ + if(speed <= 100 && speed >= 0){ + LL_GPIO_SetOutputPin(GPIOA,LL_GPIO_PIN_2); + int converted_speed = speed * (ARR_DC_MOTOR / 100); + TIM2->CCR2 = converted_speed; + } else if (speed >= -100 && speed <= 0) { + LL_GPIO_ResetOutputPin(GPIOA,LL_GPIO_PIN_2); // TODO maybe switch around set and reset, depending on direction of turning + int converted_speed = (-1) * speed * (ARR_DC_MOTOR / 100); + TIM2->CCR2 = converted_speed; + } else { + TIM2->CCR2 = 0; + } +} diff --git a/keil_project/Services/DcMotor.h b/keil_project/Services/DcMotor.h new file mode 100644 index 0000000..178164f --- /dev/null +++ b/keil_project/Services/DcMotor.h @@ -0,0 +1,4 @@ +void DC_MOTOR_Init(void); + +// set a speed between -100 (full throttle clockwise) 0 (stop) and 100 (full throttle counterclockwise) +void DC_MOTOR_SetSpeed(int speed); diff --git a/keil_project/Services/IncrEncoder.c b/keil_project/Services/IncrEncoder.c new file mode 100644 index 0000000..bc9f795 --- /dev/null +++ b/keil_project/Services/IncrEncoder.c @@ -0,0 +1,98 @@ +#include "IncrEncoder.h" +#include "stm32f1xx_ll_gpio.h" +#include "stm32f1xx_ll_bus.h" +#include "stm32f1xx_ll_exti.h" +#include "stm32f1xx_ll_tim.h" + +int index_passed = 0; +int counts_per_revolution = 360; + +void INCR_ENCODER_Init(void){ + + // GPIO initialization for channels a and b of the encoder + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA); + LL_GPIO_InitTypeDef channel_a_pin_conf, channel_b_pin_conf; + + channel_a_pin_conf.Mode = LL_GPIO_MODE_FLOATING; + channel_a_pin_conf.Pin = LL_GPIO_PIN_6; + LL_GPIO_Init(GPIOA, &channel_a_pin_conf); + + channel_b_pin_conf.Mode = LL_GPIO_MODE_FLOATING; + channel_b_pin_conf.Pin = LL_GPIO_PIN_7; + LL_GPIO_Init(GPIOA, &channel_b_pin_conf); + + // timer init + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3); + LL_TIM_InitTypeDef tim3_init_struct; + + tim3_init_struct.Autoreload= counts_per_revolution*4-1; + tim3_init_struct.Prescaler=0; + tim3_init_struct.ClockDivision=LL_TIM_CLOCKDIVISION_DIV1; + tim3_init_struct.CounterMode=LL_TIM_COUNTERMODE_UP; + tim3_init_struct.RepetitionCounter=0; + + LL_TIM_Init(TIM3, &tim3_init_struct); + + // timer as encoder init + LL_TIM_ENCODER_InitTypeDef encoder_init_struct; + encoder_init_struct.EncoderMode = LL_TIM_ENCODERMODE_X4_TI12; + encoder_init_struct.IC1Polarity = LL_TIM_IC_POLARITY_RISING; + encoder_init_struct.IC2Polarity = LL_TIM_IC_POLARITY_RISING; + encoder_init_struct.IC1ActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI; + encoder_init_struct.IC2ActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI; + encoder_init_struct.IC1Prescaler = LL_TIM_ICPSC_DIV1; + encoder_init_struct.IC2Prescaler= LL_TIM_ICPSC_DIV1; + encoder_init_struct.IC1Filter = LL_TIM_IC_FILTER_FDIV1 ; + encoder_init_struct.IC2Filter = LL_TIM_IC_FILTER_FDIV1 ; + + LL_TIM_ENCODER_Init(TIM3, &encoder_init_struct); + + LL_TIM_EnableCounter(TIM3); + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA); + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_AFIO); + + + // gpio init for index (interrup) pin + LL_GPIO_InitTypeDef index_pin_conf; + + index_pin_conf.Pin = LL_GPIO_PIN_5; + index_pin_conf.Mode = LL_GPIO_MODE_FLOATING; + + LL_GPIO_Init(GPIOC, &index_pin_conf); + + // exti init (interrupt) + LL_EXTI_InitTypeDef exti; + + exti.Line_0_31 = LL_EXTI_LINE_5; + exti.LineCommand = ENABLE; + exti.Mode = LL_EXTI_MODE_IT; + exti.Trigger = LL_EXTI_TRIGGER_RISING; + + LL_EXTI_Init(&exti); + LL_GPIO_AF_SetEXTISource(LL_GPIO_AF_EXTI_PORTA, LL_GPIO_AF_EXTI_LINE5); + + // enable interrupt from exti in NVIC + NVIC_SetPriority(EXTI9_5_IRQn, 12); // prio?? + NVIC_EnableIRQ(EXTI9_5_IRQn); + +} + +void EXTI9_5_IRQHandler(void){ + index_passed = 1; + // reset counter = encoder position to 0 position + LL_TIM_WriteReg(TIM3,CNT,0); + + // clear pending (EXTI necessary ?) + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_5); + NVIC_ClearPendingIRQ(EXTI9_5_IRQn); +} + +int INCR_ENCODER_IsAbsolute(void) +{ + return index_passed; +}; + +int INCR_ENCODER_GetAngle(void) +{ + return LL_TIM_ReadReg(TIM3,CNT); +}; diff --git a/keil_project/Services/IncrEncoder.h b/keil_project/Services/IncrEncoder.h new file mode 100644 index 0000000..7767b5e --- /dev/null +++ b/keil_project/Services/IncrEncoder.h @@ -0,0 +1,11 @@ +#ifndef INCR_ENCODER + +/** + */ +void INCR_ENCODER_Init(void); + +int INCR_ENCODER_IsAbsolute(void); + +int INCR_ENCODER_GetAngle(void); + +#endif diff --git a/keil_project/Src/main.c b/keil_project/Src/main.c index a32e19c..b107345 100644 --- a/keil_project/Src/main.c +++ b/keil_project/Src/main.c @@ -20,8 +20,8 @@ #include "stm32f1xx_ll_utils.h" // utile dans la fonction SystemClock_Config #include "stm32f1xx_ll_system.h" // utile dans la fonction SystemClock_Config -#include "Chrono.h" #include "RFInput.h" +#include "IncrEncoder.h" void SystemClock_Config(void); @@ -40,23 +40,12 @@ int main(void) /* Configure the system clock to 72 MHz */ SystemClock_Config(); - /*GPIOB->CRH &= ~GPIO_CRH_CNF8_1; - GPIOB->CRH |= GPIO_CRH_CNF8_0; // set cnf to 01 -> floating input - GPIOB->CRH &= ~GPIO_CRH_MODE8; // set mode to 00 -> input - - GPIOC->CRH &= ~GPIO_CRH_CNF10; // set cnf to 00 -> push-pull - GPIOC->CRH &= ~GPIO_CRH_MODE10; - GPIOC->CRH |= GPIO_CRH_MODE10_1; // set mode to 10 -> output at 2 mhz (recommended to use minimum speed) - */ - - /* Add your application code here */ - // Configuration chronomètre RF_INPUT_Init(); - /* Infinite loop */ while (1) { + } }