/**
******************************************************************************
* @file : main.c
* @author : Fernando Hermosillo Reynoso
* @brief : Main program body
******************************************************************************
*/
#include <stdint.h>
#include "stm32f103_hal.h"
#include "lcd.h"
volatile int cont = 0;
volatile float rpm = 0;
volatile int timp = 0;
/* Defines -----------------------------------------------------*/
/* Private Variables ------------------------------ */
/* Private constants -------------------------------*/
/* Prototype Function ------------------------------*/
/* User code -----------------------------------------------------*/
void delay_ms(uint16_t ms) {
volatile unsigned long t = 0;
for(uint16_t i = 0; i < ms; i++)
{
for(t = 0; t < 800; t++);
}
}
void delay_us(uint16_t us)
{
for (volatile unsigned int cycles = 0; cycles < us; cycles++);
}
void int_to_string(int num, char* str, int size) {
int is_negative = 0;
// 1. Asegurar el terminador nulo al final
str[size - 1] = '\0';
// 2. Manejo de números negativos
if (num < 0) {
is_negative = 1;
num = -num;
}
// 3. Llenar de derecha a izquierda
for (int x = size - 2; x >= 0; x--) {
if (num > 0 || x == size - 2) { // Escribir dígitos o al menos un '0' si el num es 0
str[x] = (num % 10) + '0';
num /= 10;
}
else if (is_negative) { // Poner el signo menos justo después del último dígito
str[x] = '-';
is_negative = 0;
}
else {
str[x] = ' '; // Rellenar con espacios (o '0' si prefieres zero-padding)
}
}
}
int main(void) {
// 1. Habilitar reloj para el puerto GPIOB, AFIO (para EXTI) y el Timer 2
rcc_clock_enable(RCC_GPIOB);
rcc_clock_enable(RCC_GPIOC);
rcc_clock_enable(RCC_AFIO);
rcc_clock_enable(RCC_TIM2);
rcc_clock_enable(RCC_TIM3);
rcc_clock_enable(RCC_ADC1);
gpio_set_input(GPIOB, 0, GPIO_INPUT_PD);
gpio_set_output(GPIOC, GPIO_PIN_13, GPIO_OUTPUT_PP, GPIO_SPEED_2MHZ);
gpio_set_input(GPIOB, GPIO_PIN_1, GPIO_INPUT_ANALOG);
gpio_set_input(GPIOB, 10, GPIO_INPUT_PD);
exti_set_interrupt(PB0, EXTI_IRQ_RISING);
nvic_enable_irq(EXTI0_IRQn);
timer_init(TIM2, TIMER_MODE_UP, 4999, 799);
timer_init(TIM3, TIMER_MODE_UP, 4999, 799);
timer_set_interrupt(TIM2, TIMER_IRQ_UPDATE, IRQ_ENABLE);
nvic_enable_irq(TIM2_IRQn);
timer_set_interrupt(TIM3, TIMER_IRQ_UPDATE, IRQ_ENABLE);
nvic_enable_irq(TIM3_IRQn);
exti_set_interrupt(PB10, EXTI_IRQ_RISING);
nvic_enable_irq(EXTI15_10_IRQn);
timer_start(TIM2, TIMER_CONTINUOUS);
adc_init(ADC1, ADC_MODE_SINGLE,ADC_TRIG_SOFTWARE, ADC_ALIGN_RIGHT);
adc_set_channel(ADC1, ADC_CHANNEL_9, ADC_SMP_239_5);
nvic_enable();
LCD_Init();
char str[4];
while (1) {
float T = (adc_read(ADC1) * 500.0f) / 4095.0f;
int_to_string(cont, str,4);
LCD_SetCursor(0,0);
LCD_Print(str);
delay_ms(100);
if(T>40)GPIOC->ODR &= ~(1<<13);
else GPIOC->ODR |= 1<<13;
}
}
void EXTI0_IRQHandler(void) {
if (EXTI->PR & (1 << 0)) {
EXTI->PR |= (1 << 0); // Limpiar la bandera de interrupción
cont++;
}
}
void TIM2_IRQHandler(void) {
if (TIM2->SR & TIM_SR_UIF) {
TIM2->SR &= ~TIM_SR_UIF; // Limpiar la bandera de interrupción
rpm = (cont*120)/180;
cont = 0;
}
}
void TIM3_IRQHandler(void) {
if (TIM2->SR & TIM_SR_UIF) {
TIM2->SR &= ~TIM_SR_UIF; // Limpiar la bandera de interrupción
rpm = (cont*120)/180;
cont = 0;
}
}
void EXTI15_10_IRQHandler(void) {
// Verificar si la interrupción fue causada específicamente por la línea 10
if (EXTI->PR & (1 << 10)) {
EXTI->PR |= (1 << 10); // Limpiar la bandera (escribiendo un 1)
// --- TU CÓDIGO AQUÍ ---
// Ejemplo: cont2++;
timer_start(TIM2, TIMER_ONE_SHOT);
}
}