#include <stdint.h>
#include "stm32f103_hal.h"
// tiempos
volatile uint32_t last_time = 0;
volatile uint32_t current_time = 0;
volatile uint32_t dt_us = 0; // retardo
volatile uint32_t dt_ticks = 0;
/*
* #REVISIÓN: Se agrega "Tmotor_us" para hacer mas eficiente sus cálculos
*/
volatile uint32_t Tmotor_us = 0;
/*
* #REVISIÓN: Se ponen sin volatile por eficiencia en código,
* principalmente rpm, dado que no se necesita realmente.
*/
float rpm = 0;
float temp = 25.0;
#define N_TEETH 180
#define OFFSET_US 0 // ajuste fino
/* F */
/*
* #REVISIÓN: Tmotor_us es variable global, ya no se necesita como
* argumento de entrada.
*/
// calcula rpm
float calcular_rpm(void) {
if (Tmotor_us == 0) return 0;
return (60000000.0F / Tmotor_us);
}
// lee temperatura
float leer_temp(void) {
uint16_t adc = adc_read(ADC1);
return (adc * 500) / 4095.0;
}
/*
* #REVISIÓN: Tmotor_us es variable global, ya no se necesita como
* argumento de entrada.
*/
// calcula retardo
uint32_t calcular_dt() {
if (Tmotor_us <= 0) return 0;
uint32_t Tmotor_quarter = Tmotor_us/4;
uint32_t Tmotor_half = Tmotor_us/2;
//uint32_t Tmotor_us = (60.0 / rpm) * 1e6;
int32_t dt = Tmotor_us * (130 - (uint32_t)temp) / 120;
/*
* #REVISIÓN: Acorde a la especificación Tmotor / 4 <= dt <= Tmotor / 2
*/
if(dt < Tmotor_quarter) dt = Tmotor_quarter;
else if(dt > Tmotor_half) dt = Tmotor_half;
return dt;
}
/* CONFIG =======================================*/
// pines e interrupciones
void gpio_init(void) {
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPBEN;
// entradas
GPIOA->CRL &= ~(0xF << 0); // PA0 CKP
GPIOA->CRL |= (0x4 << 0);
GPIOA->CRL &= ~(0xF << 4); // PA1 CKPZ
GPIOA->CRL |= (0x4 << 4);
GPIOA->CRL &= ~(0xF << 8); // PA2 TDC
GPIOA->CRL |= (0x4 << 8);
// salida
GPIOB->CRL &= ~(0xF << 24); // PB6
GPIOB->CRL |= (0x3 << 24);
AFIO->EXTICR[0] = 0;
EXTI->IMR |= (1<<0)|(1<<1)|(1<<2);
EXTI->RTSR |= (1<<0)|(1<<1)|(1<<2);
NVIC_EnableIRQ(EXTI0_IRQn);
NVIC_EnableIRQ(EXTI1_IRQn);
NVIC_EnableIRQ(EXTI2_IRQn);
}
// timer medir tiempo
void tim1_init(void) {
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
TIM1->PSC = 8-1;
TIM1->ARR = 0xFFFF;
TIM1->CR1 |= TIM_CR1_CEN;
}
// timer retardo
void tim2_init(void) {
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
// Los retardos pueden ser relativ
TIM2->PSC = 80-1;
TIM2->DIER |= TIM_DIER_UIE;
TIM2->CR1 |= TIM_CR1_OPM; // One-shot
NVIC_EnableIRQ(TIM2_IRQn);
}
// timer pulso inyector
void tim4_init(void) {
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
TIM4->PSC = 8-1;
TIM4->ARR = 20000; // 2 ms
TIM4->DIER |= TIM_DIER_UIE;
TIM4->CR1 |= TIM_CR1_OPM;
NVIC_EnableIRQ(TIM4_IRQn);
}
//interrupcion
// CKP
void EXTI0_IRQHandler(void) {
current_time = TIM1->CNT;
/*
* #REVISIÓN: Protección contra overflow del timer 1
*/
if(current_time< last_time) dt_ticks = 65535-last_time + current_time;
else dt_ticks = current_time - last_time;
last_time = current_time;
//rpm = calcular_rpm(dt_ticks);
/*
* #REVISIÓN: Se calcula "Tmotor_us" aquí para hacer mas eficiente el programa
*/
Tmotor_us = dt_ticks*N_TEETH;
EXTI->PR |= (1 << 0);
}
// CKPZ: No es necesaria ya que usa TDC como referencia
void EXTI1_IRQHandler(void) {
EXTI->PR |= (1 << 1);
}
// TDC
void EXTI2_IRQHandler(void) {
//temp = leer_temp();
//dt_us = calcular_dt(rpm, temp);
if(dt_us)
{
TIM2->CNT = 0;
TIM2->ARR = dt_us/10;
TIM2->SR = 0;
TIM2->CR1 |= TIM_CR1_CEN;
}
EXTI->PR |= (1 << 2);
}
// fin retardo
void TIM2_IRQHandler(void) {
if (TIM2->SR & TIM_SR_UIF) {
TIM2->SR = 0;
GPIOB->BSRR = (1 << 6); // subir
TIM4->CNT = 0;
TIM4->SR = 0;
TIM4->CR1 |= TIM_CR1_CEN;
}
}
// fin pulso
void TIM4_IRQHandler(void) {
if (TIM4->SR & TIM_SR_UIF) {
TIM4->SR = 0;
GPIOB->BSRR = (1 << (6 + 16));
}
}
int main(void) {
gpio_init();
gpio_set_output(GPIOA, GPIO_PIN_4, GPIO_OUTPUT_PP, GPIO_SPEED_50MHZ);
gpio_set_output(GPIOC, GPIO_PIN_13, GPIO_OUTPUT_PP, GPIO_SPEED_2MHZ);
gpio_set_input(GPIOA, GPIO_PIN_3, GPIO_INPUT_ANALOG);
adc_init(ADC1, ADC_MODE_SINGLE, ADC_TRIG_SOFTWARE, ADC_ALIGN_RIGHT);
adc_set_channel(ADC1, ADC_CHANNEL_3, ADC_SMP_7_5);
tim1_init();
tim2_init();
tim4_init();
while (1) {
temp = leer_temp();
rpm = calcular_rpm();
dt_us = calcular_dt();
}
}Loading
stm32-bluepill
stm32-bluepill