/** ****************************************************************************** * @file Project/main.c * @author "Volodymyr M. Shylov" * @version v.0.1 * @date 24-11-2023 * @brief Main program body. VA-meter from DC/DC XL4005 ****************************************************************************** * @attention * * "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. Shilov V.N. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "stm8s.h" #include "board.h" #include "led.h" #include "delay.h" /* Private define ------------------------------------------------------------*/ #define TIM4_PERIOD (uint8_t)124 /* Private typedef -----------------------------------------------------------*/ /* Private constants ---------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ __IO uint16_t ConversionBuffer[ADC_SMPLS]; __IO uint8_t BufferIndex = 0; static uint16_t Voltage; /* Private function prototypes -----------------------------------------------*/ static void boardInit(void); static void showV(void); static void showC(void); void main(void) { /* Board Configuration */ boardInit(); Delay(100); /* Infinite loop */ while (1) { Delay(100); if (BufferIndex >= ADC_SMPLS) { BufferIndex = 0; int8_t i; uint32_t vbuf = 0; for (i=0; i<64; i++) { vbuf += ConversionBuffer[i]; } vbuf *= ADC_VREF; vbuf += 512; vbuf /= 1023; vbuf *= 45727; vbuf += 5000; vbuf /= 10000; Voltage = vbuf; } showV(); showC(); } } /* Private functions ---------------------------------------------------------*/ static void showV(void) { uint16_t a = (Voltage + 5) / 10; LedDigits[0] = a / 1000; uint16_t b = a % 1000; LedDigits[1] = b / 100; uint8_t c = b % 100; LedDigits[2] = c / 10; LedDigits[3] = c % 10; } static void showC(void) { LedDigits[4] = 5; LedDigits[5] = 6; LedDigits[6] = 7; LedDigits[7] = 8; } static void boardInit(void) { /* Насколько я понял, для частот выше 16МГц нужно вводить задержку при работе с FLASH: - Before using the HSE clock make sure that the "Flash_Wait_States" is set to 1. - To do so : - with STVD (menu: Debug Instrument -> MCU configuration -> Options) - with EWSTM8 (menu: ST-LINK -> Option bytes ->Flash_Wait_States: 1) */ /* Initialization of the clock to 16MHz */ CLK->CKDIVR = 0x00; /* Disable clock of unused peripherial */ CLK->PCKENR1 = (uint8_t)(~(CLK_PCKENR1_UART1 | CLK_PCKENR1_SPI)); CLK->PCKENR2 = (uint8_t)(~(CLK_PCKENR2_CAN | CLK_PCKENR2_AWU)); // | CLK_PCKENR2_ADC /* SWIM clock */ CLK->SWIMCCR = 0x00; /* SWITCH pin to Push-Pull, High, Fast */ SWITCH_PORT->ODR |= (uint8_t)(SWITCH_PIN); SWITCH_PORT->DDR |= (uint8_t)(SWITCH_PIN); SWITCH_PORT->CR1 |= (uint8_t)(SWITCH_PIN); SWITCH_PORT->CR2 |= (uint8_t)(SWITCH_PIN); SWITCH_OFF; /* Configure GPIO used for LED to Push-Pull, High, Fast*/ GPIOA->ODR |= (uint8_t)LED_SEG_CG; GPIOA->DDR |= (uint8_t)LED_SEG_CG; GPIOA->CR1 |= (uint8_t)LED_SEG_CG; GPIOA->CR2 |= (uint8_t)LED_SEG_CG; GPIOB->ODR |= (uint8_t)LED_SEG_DH; GPIOB->DDR |= (uint8_t)LED_SEG_DH; GPIOB->CR1 |= (uint8_t)LED_SEG_DH; GPIOB->CR2 |= (uint8_t)LED_SEG_DH; GPIOC->ODR |= (uint8_t)LED_SEG_BE; GPIOC->DDR |= (uint8_t)LED_SEG_BE; GPIOC->CR1 |= (uint8_t)LED_SEG_BE; GPIOC->CR2 |= (uint8_t)LED_SEG_BE; GPIOD->ODR |= (uint8_t)LED_SEG_AF; GPIOD->DDR |= (uint8_t)LED_SEG_AF; GPIOD->CR1 |= (uint8_t)LED_SEG_AF; GPIOD->CR2 |= (uint8_t)LED_SEG_AF; /* `SPI` pins to Push-Pull, High, Fast */ SPI_PORT->ODR = (uint8_t)(SPI_SCK|SPI_DATA); SPI_PORT->DDR |= (uint8_t)(SPI_SCK|SPI_DATA); SPI_PORT->CR1 |= (uint8_t)(SPI_SCK|SPI_DATA); SPI_PORT->CR2 |= (uint8_t)(SPI_SCK|SPI_DATA); /* I2C GPIO SDA SCL - HiZ, Open drain, Fast */ //GPIOB->DDR |= (GPIO_PIN_4 | GPIO_PIN_5); //GPIOB->ODR |= (GPIO_PIN_4 | GPIO_PIN_5); //GPIOB->CR2 |= (GPIO_PIN_4 | GPIO_PIN_5); /** Configure ADC1 peripheral */ /* Configure the data alignment */ ADC1->CR2 |= (uint8_t)(ADC1_CR2_ALIGN); /* Set the single conversion mode */ ADC1->CR1 &= (uint8_t)(~ADC1_CR1_CONT); /* Clear the ADC1 channels */ ADC1->CSR &= (uint8_t)(~ADC1_CSR_CH); /* Select the ADC1 channel */ ADC1->CSR |= (uint8_t)(ADC_CHNLU); /* Clear the SPSEL bits */ ADC1->CR1 &= (uint8_t)(~ADC1_CR1_SPSEL); /* Select the prescaler division factor according to ADC1_PrescalerSelection values */ ADC1->CR1 |= (uint8_t)(ADC1_PRESSEL_FCPU_D8); /* Enable the external Trigger */ ADC1->CR2 |= (uint8_t)(ADC1_CR2_EXTTRIG); /* Set the 'Internal TIM1 TRGO event' as external trigger */ ADC1->CR2 &= (uint8_t)~(ADC1_CR2_EXTSEL); /* disables the ADC1 Schmitt Trigger on a selected channel(s) */ ADC1->TDRL |= (uint8_t)((uint8_t)0x01 << (uint8_t)ADC_SCHTU); /* Enable the ADC1 peripheral */ ADC1->CR1 |= ADC1_CR1_ADON; /* Enable the ADC1 EOC interrupt */ ADC1->CSR |= (uint8_t)ADC1_IT_EOCIE; /*Start Conversion */ ADC1->CR1 |= ADC1_CR1_ADON; /** Configure TIM1 peripheral. Time Base configuration: Timer period - 3,125 ms TIM1_Period = 50 TIM1_Prescaler = 1000 TIM1_CounterMode = TIM1_COUNTERMODE_UP TIM1_RepetitionCounter = 0 */ /* Set the Autoreload value */ TIM1->ARRH = (uint8_t)(49 >> 8); TIM1->ARRL = (uint8_t)(49); /* Set the Prescaler value */ TIM1->PSCRH = (uint8_t)(999 >> 8); TIM1->PSCRL = (uint8_t)(999); /* Select the Counter Mode */ TIM1->CR1 = 0x0; /* Set the Repetition Counter value */ TIM1->RCR = 0; /* Trigrer configuration */ TIM1->CR2 = (uint8_t)TIM1_TRGOSOURCE_UPDATE; /* Update Interrupt Enable */ //TIM1->IER |= (uint8_t)TIM1_IT_UPDATE; /* Enable TIM1 */ TIM1->CR1 |= TIM1_CR1_CEN; /** TIM4 configuration: - TIM4CLK is set to 16 MHz, the TIM4 Prescaler is equal to 128 so the TIM1 counter clock used is 16 MHz / 128 = 125 000 Hz - With 125 000 Hz we can generate time base: max time base is 2.048 ms if TIM4_PERIOD = 255 --> (255 + 1) / 125000 = 2.048 ms min time base is 0.016 ms if TIM4_PERIOD = 1 --> ( 1 + 1) / 125000 = 0.016 ms - In this example we need to generate a time base equal to 1 ms so TIM4_PERIOD = (0.001 * 125000 - 1) = 124 */ /* Time base configuration. Set the Prescaler value */ TIM4->PSCR = (uint8_t)(TIM4_PRESCALER_128); /* Set the Autoreload value */ TIM4->ARR = (uint8_t)(TIM4_PERIOD); /* Clear TIM4 update flag */ TIM4->SR1 = (uint8_t)(~TIM4_FLAG_UPDATE); /* Enable update interrupt */ TIM4->IER |= (uint8_t)TIM4_IT_UPDATE; /* enable interrupts */ enableInterrupts(); /* Enable TIM4 */ TIM4->CR1 |= (uint8_t)TIM4_CR1_CEN; } /************************ (C) COPYRIGHT Shilov V.N. *****END OF FILE****/