#include "stdint.h" #include "stdlib.h" #include "stdbool.h" #include "stm8s.h" #include "stm8s_gpio.h" #include "stm8s_tim2.h" #include "stm8s_tim4.h" #include "stm8s_clk.h" #include "stm8s_it.h" #include "stm8s_exti.h" /* A ___ A - PD1 | | B - PD4 DIG1 - PC7 F| G |B C - PB4 DIG2 - PA3 |___| D - PC5 DIG3 - PD6 | | E - PC6 DIG4 - PC3 E| D |C F - PD5 |___| . G - PB5 . - PC4 0bABCDEFG. 0 - 0b00000011 1 - 0b10011111 2 - 0b00100101 3 - 0b00001101 4 - 0b10011001 5 - 0b01001001 6 - 0b01000001 7 - 0b00011111 8 - 0b00000001 9 - 0b00001001 */ static uint16_t rpm=0; bool timeout = false; #define SAMPLES 8 static uint16_t periods[SAMPLES]; static uint32_t sum; static uint8_t refresh_cnt; #define DISP_PB(pin) ((0x00000100ull)<<(pin)) #define DISP_PC(pin) ((0x00010000ull)<<(pin)) #define DISP_PD(pin) ((0x01000000ull)<<(pin)) #define _DISP_V_PB(x) (((x)>>8) & 0xff) #define _DISP_V_PC(x) (((x)>>16) & 0xff) #define _DISP_V_PD(x) (((x)>>24) & 0xff) #define DISP_IDX_PB 0 #define DISP_IDX_PC 1 #define DISP_IDX_PD 2 #define DISP_V(x) {_DISP_V_PB(x), _DISP_V_PC(x), _DISP_V_PD(x)} #define SEG_A DISP_PD(1) #define SEG_B DISP_PD(4) #define SEG_C DISP_PB(4) #define SEG_D DISP_PC(5) #define SEG_E DISP_PC(6) #define SEG_F DISP_PD(5) #define SEG_G DISP_PB(5) #define SEG_DOT DISP_PC(4) #define SEG_ALL (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | SEG_DOT) void print(){ static uint8_t led_disp; static const uint16_t digit_vals[4] = {1000, 100, 10, 1}; uint8_t digit; static const uint8_t pins_symbol[10][3] = { [0] = DISP_V(SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F ), [1] = DISP_V( SEG_B | SEG_C ), [2] = DISP_V(SEG_A | SEG_B | SEG_D | SEG_E | SEG_G), [3] = DISP_V(SEG_A | SEG_B | SEG_C | SEG_D | SEG_G), [4] = DISP_V( SEG_B | SEG_C | SEG_F | SEG_G), [5] = DISP_V(SEG_A | SEG_C | SEG_D | SEG_F | SEG_G), [6] = DISP_V(SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G), [7] = DISP_V(SEG_A | SEG_B | SEG_C ), [8] = DISP_V(SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G), [9] = DISP_V(SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G), }; static const uint8_t pins_all[3] = DISP_V(SEG_ALL); if(rpm>9999) rpm = 9999; digit = (rpm / digit_vals[led_disp]) % 10; GPIOC->ODR &= ~GPIO_PIN_7; GPIOA->ODR &= ~GPIO_PIN_3; GPIOD->ODR &= ~GPIO_PIN_6; GPIOC->ODR &= ~GPIO_PIN_3; /* all cathodes high (off) */ /* GPIOA->ODR |= pins_all[DISP_IDX_PA]; */ GPIOB->ODR |= pins_all[DISP_IDX_PB]; GPIOC->ODR |= pins_all[DISP_IDX_PC]; GPIOD->ODR |= pins_all[DISP_IDX_PD]; /* GPIOA->ODR &= ~pins_symbol[digit][DISP_IDX_PA]; */ GPIOB->ODR &= ~pins_symbol[digit][DISP_IDX_PB]; GPIOC->ODR &= ~pins_symbol[digit][DISP_IDX_PC]; GPIOD->ODR &= ~pins_symbol[digit][DISP_IDX_PD]; switch(led_disp){ case 0: GPIOC->ODR |= GPIO_PIN_7; break; case 1: GPIOA->ODR |= GPIO_PIN_3; break; case 2: GPIOD->ODR |= GPIO_PIN_6; break; case 3: GPIOC->ODR |= GPIO_PIN_3; break; } led_disp++; if(led_disp > 3) led_disp = 0; } void main(void) { GPIOA->ODR &= (~GPIO_PIN_3); GPIOA->DDR |= GPIO_PIN_3; /* Pull-Up or Push-Pull */ GPIOA->CR1 |= GPIO_PIN_3; /* No external interrupt or No slope control */ GPIOA->CR2 &= (~GPIO_PIN_3); GPIOB->ODR &= (~(GPIO_PIN_4|GPIO_PIN_5)); GPIOB->DDR |= (GPIO_PIN_4|GPIO_PIN_5); GPIOB->CR1 |= (GPIO_PIN_4|GPIO_PIN_5); GPIOB->CR2 &= (~(GPIO_PIN_4|GPIO_PIN_5)); GPIOC->ODR &= (~( GPIO_PIN_3| GPIO_PIN_4| GPIO_PIN_5| GPIO_PIN_6| GPIO_PIN_7)); GPIOC->DDR |= ( GPIO_PIN_3| GPIO_PIN_4| GPIO_PIN_5| GPIO_PIN_6| GPIO_PIN_7); GPIOC->CR1 |= ( GPIO_PIN_3| GPIO_PIN_4| GPIO_PIN_5| GPIO_PIN_6| GPIO_PIN_7); GPIOC->CR2 &= (~( GPIO_PIN_3| GPIO_PIN_4| GPIO_PIN_5| GPIO_PIN_6| GPIO_PIN_7)); GPIOD->ODR &= (~( GPIO_PIN_1| GPIO_PIN_4| GPIO_PIN_5| GPIO_PIN_6)); GPIOD->DDR |= ( GPIO_PIN_1| GPIO_PIN_4| GPIO_PIN_5| GPIO_PIN_6); GPIOD->CR1 |= ( GPIO_PIN_1| GPIO_PIN_4| GPIO_PIN_5| GPIO_PIN_6); GPIOD->CR2 &= (~( GPIO_PIN_1| GPIO_PIN_4| GPIO_PIN_5| GPIO_PIN_6)); //sensor /* Set Input mode */ GPIOD->DDR &= (~GPIO_PIN_2); /* Pull-Up or Push-Pull */ GPIOD->CR1 |= GPIO_PIN_2; /* Interrupt or Slow slope */ GPIOD->CR2 |= GPIO_PIN_2; /* Enables Clock switch */ CLK->SWCR |= CLK_SWCR_SWEN; /* Disables Switch interrupt */ CLK->SWCR &= (uint8_t)(~CLK_SWCR_SWIEN); /* Selection of the target clock source */ CLK->SWR = CLK_SOURCE_HSE; /* Wait until the target clock source is ready */ while((CLK->SWCR & CLK_SWCR_SWBSY) != 0 ); EXTI->CR1 &= (~EXTI_CR1_PDIS); EXTI->CR1 |= (EXTI_SENSITIVITY_FALL_ONLY << 6); CLK->PCKENR1 |= (1 << CLK_PERIPHERAL_TIMER4); TIM4->IER |= TIM4_IT_UPDATE; TIM4->PSCR = TIM4_PRESCALER_128; TIM4->ARR = 255; enableInterrupts(); TIM4->CR1 |= TIM4_CR1_CEN; CLK->PCKENR1 |= (1 << CLK_PERIPHERAL_TIMER2 ); TIM2->PSCR = TIM2_PRESCALER_256; TIM2->ARRH = 0xFF; TIM2->ARRL = 0xFF; TIM2->CCMR3 |= TIM2_ICSELECTION_DIRECTTI; /* Select the Polarity */ TIM2->CCER2 |= TIM2_CCER2_CC3P; /* Set the CCE Bit */ TIM2->CCER2 |= TIM2_CCER2_CC3E; TIM2->IER |= TIM2_IT_UPDATE; TIM2->CR1 |= TIM2_CR1_CEN; while (1) { if(refresh_cnt == 60){ refresh_cnt = 0; if (timeout) { rpm = 0; } else{ rpm = (uint32_t)(62500 * 60 * SAMPLES) / sum; } } } } INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23) { refresh_cnt++; print(); TIM4->SR1 = ~TIM4_IT_UPDATE; } INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6) { static uint8_t pos; uint16_t current_period=0; if(TIM2->SR1 & TIM2_FLAG_CC3){ current_period = ((uint16_t)TIM2->CCR3H << 8) | TIM2->CCR3L; sum -= periods[pos]; periods[pos] = current_period; sum += current_period; if(++pos == SAMPLES) { pos = 0; } TIM2->SR1 = ~TIM2_FLAG_CC3; timeout = false; TIM2->CNTRH = 0; TIM2->CNTRL = 0; } } INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13) { timeout = true; TIM2->SR1 = ~TIM2_IT_UPDATE; }