#define __SDCC__ #include "stdint.h" #include "stdlib.h" #include "stdbool.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" #define _BV(x) (1 << x) /* 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 */ volatile uint16_t rpm=0; volatile static uint16_t current_period=0; volatile static uint16_t periods[8]={0}; volatile static int16_t sum = 0; volatile static uint8_t pos = 0; volatile static bool filled = false; volatile static bool overflow = false; volatile uint32_t average; #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) static uint8_t get_digit_4(int16_t val, uint8_t idx) { } void print(uint16_t value){ 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[4] = DISP_V(SEG_ALL); if(value>9999) value = 9999; GPIO_WriteLow(GPIOC, GPIO_PIN_7); GPIO_WriteLow(GPIOA, GPIO_PIN_3); GPIO_WriteLow(GPIOD, GPIO_PIN_6); GPIO_WriteLow(GPIOC, GPIO_PIN_3); digit = (value / digit_vals[led_disp]) % 10; /* 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: GPIO_WriteHigh(GPIOC, GPIO_PIN_7); break; case 1: GPIO_WriteHigh(GPIOA, GPIO_PIN_3); break; case 2: GPIO_WriteHigh(GPIOD, GPIO_PIN_6); break; case 3: GPIO_WriteHigh(GPIOC, GPIO_PIN_3); break; } led_disp++; if(led_disp >= 4) led_disp = 0; } void main(void) { GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_FAST); GPIO_Init(GPIOB, GPIO_PIN_4| GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_FAST); GPIO_Init(GPIOC, GPIO_PIN_3| GPIO_PIN_4| GPIO_PIN_5| GPIO_PIN_6| GPIO_PIN_7, GPIO_MODE_OUT_PP_LOW_FAST); GPIO_Init(GPIOD, GPIO_PIN_1| GPIO_PIN_4| GPIO_PIN_5| GPIO_PIN_6, GPIO_MODE_OUT_PP_LOW_FAST); //sensor GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_IN_PU_IT); EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOD,EXTI_SENSITIVITY_FALL_ONLY); CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE); CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER4,ENABLE); TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE); TIM4_TimeBaseInit(TIM4_PRESCALER_128, 255); enableInterrupts(); TIM4_Cmd(ENABLE); CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, ENABLE); TIM2_TimeBaseInit(TIM2_PRESCALER_256, 0xFFFF); TIM2_ICInit(TIM2_CHANNEL_3, TIM2_ICPOLARITY_FALLING,TIM2_ICSELECTION_DIRECTTI, TIM2_ICPSC_DIV1,0x00); TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE); TIM2_Cmd(ENABLE); while (1) { if (overflow) { rpm = 0; } else { rpm = (uint32_t)(62500 * 60) / average; } for (uint16_t i = 1; i < 65200; i++) { for (uint16_t j = 1; j < 3; j++); } } } INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23) { print(rpm); TIM4_ClearITPendingBit(TIM4_IT_UPDATE); } INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6) { if(TIM2_GetFlagStatus(TIM2_FLAG_CC3)){ current_period = TIM2_GetCapture3(); sum = sum - periods[pos]; periods[pos] = current_period; sum += current_period; if(++pos == sizeof(periods)/sizeof(*periods)) { pos = 0; filled = true; } size_t count = filled ? sizeof(periods)/sizeof(*periods) : pos; average = (sum < 0 ? sum - count / 2 : sum + count / 2 ) / count; TIM2_ClearFlag(TIM2_FLAG_CC3); overflow = false; TIM2_SetCounter(0); } } INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13) { overflow = true; TIM2_ClearITPendingBit(TIM2_IT_UPDATE); }