/**
******************************************************************************
* @file : main.c
* @author : Fernando Hermosillo Reynoso
* @author2 : Eduardo Carmona Aguirre
* @brief : Main program body
******************************************************************************
*/
//-------------------------------------------------------
//REVISADO POR PROFESOR EL MARTES 14 DE ABRIL DE 2026
//-------------------------------------------------------
#include <stdint.h>
#include "stm32f103_hal.h"
//volatile para evitar cache, se mantengan vivas
volatile uint32_t dientes_vuelta = 0; // Dientes contados en la rev pasada
volatile uint32_t contador_dientes = 0; // Dientes que van en la vuelta actual que se resetea con angl0
volatile uint32_t dientes_seg = 0; // Para rpm
volatile uint32_t contador_seg = 0; // Contador de dientes por segundo
volatile uint32_t delta_t_ticks = 0; // Retardo de inyección, en tck10 microsec dividido
int main(void)
{
rcc_clock_enable(RCC_GPIOA); // a0 thru 8
rcc_clock_enable(RCC_GPIOB); // b6 inyect
rcc_clock_enable(RCC_GPIOC); // Pc13
rcc_clock_enable(RCC_TIM2); // Timer 2 retardo delta_t
rcc_clock_enable(RCC_TIM3); // Timer 3 conv en 1 segundo para medir RPM/sec
rcc_clock_enable(RCC_TIM4); // Timer 4 PWM inyector 10ms t div
rcc_clock_enable(RCC_ADC1); // ADC1 voltaje temp sens
rcc_clock_enable(RCC_EXTI); // AFIO interrupt a pines
gpio_set_output(GPIOC, GPIO_PIN_13, GPIO_OUTPUT_PP, GPIO_SPEED_2MHZ); //flipear pc13 para que este apagado en 0
gpio_bitwise_set(GPIOC, 1<<13);
gpio_set_input(GPIOA, GPIO_PIN_0, GPIO_INPUT_FLOAT); //angl0 en a0
gpio_set_input(GPIOA, GPIO_PIN_1, GPIO_INPUT_FLOAT); //tdc en a1
gpio_set_input(GPIOA, GPIO_PIN_8, GPIO_INPUT_FLOAT); //diente en a8, dice +90 en diagrama leds porque lo tengo para 4 dientes
gpio_set_input(GPIOA, GPIO_PIN_2, GPIO_INPUT_ANALOG); //a2 to adc para temp input
exti_set_interrupt(PA0, EXTI_IRQ_RISING); // rising edge es instante donde empieza a pasar diente angl0
nvic_enable_irq(EXTI0_IRQn); //para que nvic pueda considerarlo digamos, exti0
exti_set_interrupt(PA1, EXTI_IRQ_RISING); //mismo pero tdc
nvic_enable_irq(EXTI1_IRQn); //mismo ahora con exti1
exti_set_interrupt(PA8, EXTI_IRQ_RISING); // diente / +90 degr si son 4 dientes
nvic_enable_irq(EXTI9_5_IRQn); //exti 8
adc_init(ADC1, ADC_MODE_SINGLE, ADC_TRIG_SOFTWARE, ADC_ALIGN_RIGHT);
//este tuve que usar recursos externos para saber cómo funciona el sensor, como cita QUOTE
/* ADC_MODE_SINGLE: convierte un canal una vez por disparo de software */
/* ADC_TRIG_SOFTWARE: la conversión inicia cuando el software lo ordena */
/* ADC_ALIGN_RIGHT: los 12 bits del resultado quedan alineados a la derecha del registro */
//ENDQUOTE
adc_set_channel(ADC1, ADC_CHANNEL_2, ADC_SMP_239_5);//adc 2 para pa2 tempsens, //TEMP
// 239.5 sample cicle de fuente ext
timer_init(TIM4, TIMER_MODE_UP, 9, 7); //calculos arr, psc en nota adjuntada. //PWM
timer_set_oc_channel(TIM4, TIMER_CHANNEL_1, TIMER_OC_PWM2, TIMER_OC_POLARITY_HIGH, 8, true);
timer_init(TIM2, TIMER_MODE_UP, 1000, 79); //arr placeholder para exti1 //RETARDO
timer_set_interrupt(TIM2, TIMER_IRQ_UPDATE, IRQ_ENABLE); //como limit variable, cuanto llegue a limit
//se causa overflow, entonces interrupt se activa y entra inyector
nvic_enable_irq(TIM2_IRQn); //igual para que nvic lo managee
timer_init(TIM3, TIMER_MODE_UP, 9999, 799); //100 microsec tick. Trabajo en nota adjuntada. //RPM
timer_set_interrupt(TIM3, TIMER_IRQ_UPDATE, IRQ_ENABLE);
nvic_enable_irq(TIM3_IRQn);
timer_start(TIM3, TIMER_CONTINUOUS);
float temperatura = 85.0f; //referencia que se dio //LOOP
float rpm = 0.0f; //rpm es 0 al incializar
while(1)
{
uint16_t adc_val = adc_read(ADC1);
temperatura = (adc_val * 330.0f) / 4095.0f; //igual para convertir temp analog a 12 bit
if (dientes_vuelta > 0 && dientes_seg > 0) {
rpm = ((float)dientes_seg / (float)dientes_vuelta) * 60.0f;
}
//para esti igual usé recursos externos para la sintaxis, ejemplo: float
if (rpm > 0.0f) {
float Tmotor = (60.0f / rpm) * 1000000.0f; //periodo en microsec
float Tmotor_4 = Tmotor / 4.0f; //periodo/4 = tdc
float dt = Tmotor_4 * (1.0f + 200.0f * (85.0f - temperatura));
if (dt > (Tmotor / 2.0f)) dt = Tmotor / 2.0f;
if (dt < Tmotor_4) dt = Tmotor_4;
/* Convertir de microsegundos a ticks de TIM2 (cada tick = 10 µs) */
delta_t_ticks = (uint32_t)(dt / 10.0f);
}
}
}
void EXTI0_IRQHandler(void) {
if (EXTI->PR & (1<<0)) {
EXTI->PR = (1<<0);
dientes_vuelta = contador_dientes;
contador_dientes = 0;
}
}
void EXTI1_IRQHandler(void) {
if (EXTI->PR & (1<<1)) {
EXTI->PR = (1<<1);
if (delta_t_ticks > 0) {
TIM2->CNT = 0; // De debug externo QUOTE CRÍTICO: resetear el contador del timer a 0.
// Sin esto, si TIM2 quedó en medio de un conteo anterior,
// el tiempo sería incorrecto. ENDQUOTE
TIM2->ARR = delta_t_ticks - 1;
//ARR-1 porque el overflow ocurre cuando CNT pasa ARR,
timer_start(TIM2, TIMER_ONESHOT); //oneshot hasta arr
}
}
}
void EXTI9_5_IRQHandler(void) {
if (EXTI->PR & (1<<8)) {
EXTI->PR = (1<<8);
contador_dientes++;
contador_seg++;
}
}
void TIM3_IRQHandler(void) {
if (TIM3->SR & TIM_SR_UIF) {
TIM3->SR &= ~TIM_SR_UIF;
dientes_seg = contador_seg;
contador_seg = 0;
}
}
void TIM2_IRQHandler(void) {
if (TIM2->SR & TIM_SR_UIF) {
TIM2->SR &= ~TIM_SR_UIF; //clear flag
timer_start(TIM4, TIMER_ONESHOT); // TIM4 pwm inyect, autocutoff 2microsec
gpio_bitwise_toggle(GPIOC, 1<<13); //pc13
}
}Loading
stm32-bluepill
stm32-bluepill
+90° | | 0° | | TDC(90°) | | Inyect.
Inyector
Azul = Debug