#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"
/*
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;
void print(uint16_t value){
volatile static uint8_t led_disp;
led_disp++;
if(led_disp>4) led_disp = 1;
uint8_t digit;
const uint8_t symbols[10] = {
0b00000011,
0b10011111,
0b00100101,
0b00001101,
0b10011001,
0b01001001,
0b01000001,
0b00011111,
0b00000001,
0b00001001,
};
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);
switch(led_disp){
case 1:
digit = (value/1000)%10;
break;
case 2:
digit = (value/100)%10;
break;
case 3:
digit = (value/10)%10;
break;
case 4:
digit = value%10;
break;
}
GPIO_Write(GPIOD, (GPIOD->ODR & (~(1<<1))) | (!!((1<<7) & symbols[digit]) << 1)); // A - PD1
GPIO_Write(GPIOD, (GPIOD->ODR & (~(1<<4))) | (!!((1<<6) & symbols[digit]) << 4)); // B - PD4
GPIO_Write(GPIOB, (GPIOB->ODR & (~(1<<4))) | (!!((1<<5) & symbols[digit]) << 4)); // C - PB4
GPIO_Write(GPIOC, (GPIOC->ODR & (~(1<<5))) | (!!((1<<4) & symbols[digit]) << 5)); // D - PC5
GPIO_Write(GPIOC, (GPIOC->ODR & (~(1<<6))) | (!!((1<<3) & symbols[digit]) << 6)); // E - PC6
GPIO_Write(GPIOD, (GPIOD->ODR & (~(1<<5))) | (!!((1<<2) & symbols[digit]) << 5)); // F - PD5
GPIO_Write(GPIOB, (GPIOB->ODR & (~(1<<5))) | (!!((1<<1) & symbols[digit]) << 5)); // G - PB5
GPIO_Write(GPIOC, (GPIOC->ODR & (~(1<<4))) | (!!((1<<0) & symbols[digit]) << 4)); // . - PC4
switch(led_disp){
case 1:
GPIO_WriteHigh(GPIOC, GPIO_PIN_7);
break;
case 2:
GPIO_WriteHigh(GPIOA, GPIO_PIN_3);
break;
case 3:
GPIO_WriteHigh(GPIOD, GPIO_PIN_6);
break;
case 4:
GPIO_WriteHigh(GPIOC, GPIO_PIN_3);
break;
}
}
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);
}