From 9a3358f1c29d5d677731994e7ad5ebc950120c49 Mon Sep 17 00:00:00 2001 From: Mateusz Lubecki Date: Tue, 19 Apr 2022 19:56:53 +0200 Subject: [PATCH 1/2] pwm input --- .../system/src/drivers/l4/subdir.mk | 3 + include/io.h | 6 + src/it_handlers.c | 1 + src/main.c | 43 +++--- .../include/drivers/l4/pwm_input_stm32l4x.h | 17 +++ system/src/drivers/l4/pwm_input_stm32l4x.c | 141 ++++++++++++++++++ 6 files changed, 189 insertions(+), 22 deletions(-) create mode 100644 system/include/drivers/l4/pwm_input_stm32l4x.h create mode 100644 system/src/drivers/l4/pwm_input_stm32l4x.c diff --git a/STM32L476_ParaMETEO/system/src/drivers/l4/subdir.mk b/STM32L476_ParaMETEO/system/src/drivers/l4/subdir.mk index 742139f..6b6b444 100644 --- a/STM32L476_ParaMETEO/system/src/drivers/l4/subdir.mk +++ b/STM32L476_ParaMETEO/system/src/drivers/l4/subdir.mk @@ -6,16 +6,19 @@ C_SRCS += \ ../system/src/drivers/l4/flash_stm32l4x.c \ ../system/src/drivers/l4/i2c_stm32l4x.c \ +../system/src/drivers/l4/pwm_input_stm32l4x.c \ ../system/src/drivers/l4/serial_stm32l4x.c OBJS += \ ./system/src/drivers/l4/flash_stm32l4x.o \ ./system/src/drivers/l4/i2c_stm32l4x.o \ +./system/src/drivers/l4/pwm_input_stm32l4x.o \ ./system/src/drivers/l4/serial_stm32l4x.o C_DEPS += \ ./system/src/drivers/l4/flash_stm32l4x.d \ ./system/src/drivers/l4/i2c_stm32l4x.d \ +./system/src/drivers/l4/pwm_input_stm32l4x.d \ ./system/src/drivers/l4/serial_stm32l4x.d diff --git a/include/io.h b/include/io.h index e9f7269..566b850 100644 --- a/include/io.h +++ b/include/io.h @@ -8,6 +8,12 @@ #ifndef IO_H_ #define IO_H_ +/** + * This header file (and corresponding .c file is responsible for configuring and servicing + * various things connected to GPIO pins. Watchdog, Output collector out (for ParaTNC) and + * switching on/off different voltages across both ParaTNC and ParaMETEO + */ + #ifdef STM32F10X_MD_VL #include #endif diff --git a/src/it_handlers.c b/src/it_handlers.c index 2c18213..ca67639 100644 --- a/src/it_handlers.c +++ b/src/it_handlers.c @@ -54,6 +54,7 @@ * USART1_IRQHandler - 9 -> uart to comm with KISS host * I2C1_ER_IRQHandler - 10 -> I2C error interrupt * + * TIM8_ - PWM input */ diff --git a/src/main.c b/src/main.c index 0e89b73..72af2eb 100644 --- a/src/main.c +++ b/src/main.c @@ -21,6 +21,7 @@ #include "gsm/sim800c_gprs.h" #include "aprsis.h" +#include "drivers/l4/pwm_input_stm32l4x.h" #endif #include @@ -269,7 +270,7 @@ int main(int argc, char* argv[]){ memset(main_own_aprs_msg, 0x00, OWN_APRS_MSG_LN); -#if defined(PARATNC_HWREV_A) || defined(PARATNC_HWREV_B) || defined(PARATNC_HWREV_C) +#if defined(STM32F10X_MD_VL) RCC->APB1ENR |= (RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM7EN | RCC_APB1ENR_TIM4EN); RCC->APB2ENR |= (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_TIM1EN); RCC->AHBENR |= RCC_AHBENR_CRCEN; @@ -326,7 +327,7 @@ int main(int argc, char* argv[]){ system_clock_configure_rtc_l4(); RCC->APB1ENR1 |= (RCC_APB1ENR1_TIM2EN | RCC_APB1ENR1_TIM3EN | RCC_APB1ENR1_TIM4EN | RCC_APB1ENR1_TIM5EN | RCC_APB1ENR1_TIM7EN | RCC_APB1ENR1_USART2EN | RCC_APB1ENR1_USART3EN | RCC_APB1ENR1_DAC1EN | RCC_APB1ENR1_I2C1EN | RCC_APB1ENR1_USART3EN); - RCC->APB2ENR |= (RCC_APB2ENR_TIM1EN | RCC_APB2ENR_USART1EN); // RCC_APB1ENR1_USART3EN + RCC->APB2ENR |= (RCC_APB2ENR_TIM1EN | RCC_APB2ENR_USART1EN | RCC_APB2ENR_TIM8EN); // RCC_APB1ENR1_USART3EN RCC->AHB1ENR |= (RCC_AHB1ENR_CRCEN | RCC_AHB1ENR_DMA1EN); RCC->AHB2ENR |= (RCC_AHB2ENR_ADCEN | RCC_AHB2ENR_GPIOAEN | RCC_AHB2ENR_GPIOBEN | RCC_AHB2ENR_GPIOCEN | RCC_AHB2ENR_GPIODEN); RCC->BDCR |= RCC_BDCR_RTCEN; @@ -442,7 +443,7 @@ int main(int argc, char* argv[]){ // set packets intervals packet_tx_configure(main_config_data_basic->wx_transmit_period, main_config_data_basic->beacon_transmit_period, main_config_data_mode->powersave); -#if defined(PARATNC_HWREV_A) || defined(PARATNC_HWREV_B) || defined(PARATNC_HWREV_C) +#if defined(STM32F10X_MD_VL) // disabling access to BKP registers RCC->APB1ENR &= (0xFFFFFFFF ^ (RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN)); PWR->CR &= (0xFFFFFFFF ^ PWR_CR_DBP); @@ -515,7 +516,7 @@ int main(int argc, char* argv[]){ // waiting for 1 second to count number of ticks when the CPU is idle main_idle_cpu_ticks = delay_fixed_with_count(1000); -#if defined(PARATNC_HWREV_A) || defined(PARATNC_HWREV_B) || defined(PARATNC_HWREV_C) +#if defined(STM32F10X_MD_VL) // Configure I/O pins for USART1 (Kiss modem) Configure_GPIO(GPIOA,10,PUD_INPUT); // RX @@ -527,7 +528,7 @@ int main(int argc, char* argv[]){ #endif -#if defined(PARAMETEO) +#if defined(STM32L471xx) // USART1 - KISS GPIO_InitTypeDef.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitTypeDef.Pin = LL_GPIO_PIN_10; @@ -581,16 +582,12 @@ int main(int argc, char* argv[]){ #endif -#if defined(PARATNC_HWREV_A) || defined(PARATNC_HWREV_B) - Configure_GPIO(GPIOA,7,GPPP_OUTPUT_2MHZ); // re/te - GPIO_ResetBits(GPIOA, GPIO_Pin_7); -#endif -#if defined(PARATNC_HWREV_C) +#if defined(STM32F10X_MD_VL) Configure_GPIO(GPIOA,8,GPPP_OUTPUT_2MHZ); // re/te GPIO_ResetBits(GPIOA, GPIO_Pin_8); #endif -#if defined(PARAMETEO) +#if defined(STM32L471xx) GPIO_InitTypeDef.Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitTypeDef.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitTypeDef.Pin = LL_GPIO_PIN_2; @@ -600,7 +597,7 @@ int main(int argc, char* argv[]){ LL_GPIO_Init(GPIOA, &GPIO_InitTypeDef); // RE-TE #endif -#if defined(PARATNC_HWREV_A) || defined(PARATNC_HWREV_B) || defined(PARATNC_HWREV_C) +#if defined(STM32F10X_MD_VL) // enabling the clock for both USARTs RCC->APB2ENR |= RCC_APB2ENR_USART1EN; RCC->APB1ENR |= RCC_APB1ENR_USART2EN; @@ -704,15 +701,11 @@ int main(int argc, char* argv[]){ srl_init(main_wx_srl_ctx_ptr, USART2, srl_usart2_rx_buffer, RX_BUFFER_2_LN, srl_usart2_tx_buffer, TX_BUFFER_2_LN, main_target_wx_baudrate, 1); } -#if defined(PARATNC_HWREV_A) || defined(PARATNC_HWREV_B) - main_wx_srl_ctx_ptr->te_pin = GPIO_Pin_7; - main_wx_srl_ctx_ptr->te_port = GPIOA; -#endif -#if defined(PARATNC_HWREV_C) +#if defined(STM32F10X_MD_VL) main_wx_srl_ctx_ptr->te_pin = GPIO_Pin_8; main_wx_srl_ctx_ptr->te_port = GPIOA; #endif -#if defined(PARAMETEO) +#if defined(STM32L471xx) main_wx_srl_ctx_ptr->te_pin = LL_GPIO_PIN_8; main_wx_srl_ctx_ptr->te_port = GPIOA; @@ -726,7 +719,7 @@ int main(int argc, char* argv[]){ main_own_path_ln = ConfigPath(main_own_path, main_config_data_basic); #ifdef INTERNAL_WATCHDOG -#if defined(PARATNC_HWREV_A) || defined(PARATNC_HWREV_B) || defined(PARATNC_HWREV_C) +#if defined(STM32F10X_MD_VL) // enable write access to watchdog registers IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); @@ -767,11 +760,11 @@ int main(int argc, char* argv[]){ digi_init(main_config_data_mode); if ((main_config_data_mode->wx & WX_ENABLED) == 1) { -#if defined(PARATNC_HWREV_A) || defined(PARATNC_HWREV_B) || defined(PARATNC_HWREV_C) +#if defined(STM32F10X_MD_VL) dallas_init(GPIOC, GPIO_Pin_11, GPIO_PinSource11, &rte_wx_dallas_average); #endif -#if defined(PARAMETEO) +#if defined(STM32L471xx) // switch on voltages exclusively for ParaMETEO @@ -945,6 +938,10 @@ int main(int argc, char* argv[]){ //aprsis_init(&main_gsm_srl_ctx, &main_gsm_state, "SP8EBC", 10, 23220); } + + pwm_input_io_init(); + + pwm_input_init(1); #endif if (main_config_data_basic-> beacon_at_bootup == 1) { @@ -969,7 +966,7 @@ int main(int argc, char* argv[]){ ; } -#if defined(PARATNC_HWREV_A) || defined(PARATNC_HWREV_B) || defined(PARATNC_HWREV_C) +#if defined(STM32F10X_MD_VL) // read the state of a button input if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)) { @@ -1259,6 +1256,8 @@ int main(int argc, char* argv[]){ if (!main_afsk.sending) { pwr_save_pooling_handler(main_config_data_mode, main_config_data_basic, packet_tx_get_minutes_to_next_wx(), rte_main_battery_voltage); } + + pwm_input_pool(); #endif #ifdef STM32L471xx diff --git a/system/include/drivers/l4/pwm_input_stm32l4x.h b/system/include/drivers/l4/pwm_input_stm32l4x.h new file mode 100644 index 0000000..362c764 --- /dev/null +++ b/system/include/drivers/l4/pwm_input_stm32l4x.h @@ -0,0 +1,17 @@ +/* + * pwm_input_stm32l4x.h + * + * Created on: Apr 17, 2022 + * Author: mateusz + */ + +#ifndef INCLUDE_DRIVERS_L4_PWM_INPUT_STM32L4X_H_ +#define INCLUDE_DRIVERS_L4_PWM_INPUT_STM32L4X_H_ + +#include + +void pwm_input_io_init(void); +void pwm_input_init(uint8_t channel); +void pwm_input_pool(void); + +#endif /* INCLUDE_DRIVERS_L4_PWM_INPUT_STM32L4X_H_ */ diff --git a/system/src/drivers/l4/pwm_input_stm32l4x.c b/system/src/drivers/l4/pwm_input_stm32l4x.c new file mode 100644 index 0000000..726aa92 --- /dev/null +++ b/system/src/drivers/l4/pwm_input_stm32l4x.c @@ -0,0 +1,141 @@ + +#include "drivers/l4/pwm_input_stm32l4x.h" + +#include +#include +#include + +uint8_t pwm_input_current_channel = 0; +uint16_t pwm_first_channel = 0; +uint16_t pwm_second_channel = 0; + + +void pwm_input_io_init(void) { + + LL_GPIO_InitTypeDef GPIO_InitTypeDef; + + // PC6 - PWM_CH1 + GPIO_InitTypeDef.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitTypeDef.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitTypeDef.Pin = LL_GPIO_PIN_6; + GPIO_InitTypeDef.Pull = LL_GPIO_PULL_NO; + GPIO_InitTypeDef.Speed = LL_GPIO_SPEED_FREQ_MEDIUM; + GPIO_InitTypeDef.Alternate = LL_GPIO_AF_3; + LL_GPIO_Init(GPIOC, &GPIO_InitTypeDef); + + // PC7 - PWM_CH2 + GPIO_InitTypeDef.Pin = LL_GPIO_PIN_7; + LL_GPIO_Init(GPIOC, &GPIO_InitTypeDef); + +} + +void pwm_input_init(uint8_t channel) { + + // check if user provided a channel which make any sense + if (channel == 0 || channel > 2) { + return; + } + + // save current channel what is needed to pooling + pwm_input_current_channel = channel; + + // disable timer + TIM8->CR1 &= (0xFFFFFFFF ^ TIM_CR1_CEN); + + // this will produce 10kHz timebase, counter will overflow every ~6.5 seconds + TIM8->PSC = 2399; + + // reset CCER value + TIM8->CCER = 0; + + // reset CCMR configuration + TIM8->CCMR1 = 0; + + if (channel == 1) { + // 01: CC1 channel is configured as input, IC1 is mapped on TI1 + TIM8->CCMR1 |= TIM_CCMR1_CC1S_0; + + // 10: CC2 channel is configured as input, IC2 is mapped on TI1 + TIM8->CCMR1 |= TIM_CCMR1_CC2S_1; + } + else if (channel == 2) { + // 10: CC1 channel is configured as input, IC1 is mapped on TI2 + TIM8->CCMR1 |= TIM_CCMR1_CC1S_1; + + // 01: CC2 channel is configured as input, IC2 is mapped on TI2 + TIM8->CCMR1 |= TIM_CCMR1_CC2S_0; + } + + /** + * 1: OC1 active low (output mode) / Edge sensitivity selection (input mode, see below) + When CC1 channel is configured as input, both CC1NP/CC1P bits select the active polarity + of TI1FP1 and TI2FP1 for trigger or capture operations. + + CC1NP=0, CC1P=0: non-inverted/rising edge. The circuit is sensitive to TIxFP1 rising edge + (capture or trigger operations in reset, external clock or trigger mode), + TIxFP1 is not inverted (trigger operation in gated mode or encoder + mode). + + CC1NP=0, CC1P=1: inverted/falling edge. The circuit is sensitive to TIxFP1 falling edge + (capture or trigger operations in reset, external clock or trigger mode), + TIxFP1 is inverted (trigger operation in gated mode or encoder mode). + + CC1NP=1, CC1P=1: non-inverted/both edges/ The circuit is sensitive to both TIxFP1 rising + and falling edges (capture or trigger operations in reset, external clock + or trigger mode), TIxFP1is not inverted (trigger operation in gated + mode). This configuration must not be used in encoder mode. + * + * + */ + TIM8->CCER |= TIM_CCER_CC2P; + + // This bit-field selects the trigger input to be used to synchronize the counter. + // 101: Filtered Timer Input 1 (TI1FP1) + TIM8->SMCR |= (TIM_SMCR_TS_2 | TIM_SMCR_TS_0); + + // Slave mode selection + // 0100: Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter + // and generates an update of the registers. + TIM8->SMCR |= TIM_SMCR_SMS_2; + + // 1: Capture mode enabled / OC1 signal is output on the corresponding output pin + TIM8->CCER |= (TIM_CCER_CC1E | TIM_CCER_CC2E); + + // enable timer + TIM8->CR1 |= TIM_CR1_CEN; + +} + +void pwm_input_pool(void) { + + uint16_t pwm_rising_edge = TIM8->CCR2 + 1; + uint16_t pwm_falling_edge = TIM8->CCR1 + 1; + + uint16_t pwm_result = 0; + + // check preconditions + if (pwm_rising_edge != 0 && pwm_falling_edge != 0) { + if (pwm_rising_edge > pwm_falling_edge) { + pwm_result = (pwm_falling_edge / pwm_rising_edge ); + } + } + else { + ; + } + + if (pwm_input_current_channel == 1) { + + // save a result of PWM measurement + pwm_first_channel = pwm_result; + + // switch the channel to second + pwm_input_init(2); + } + else if (pwm_input_current_channel == 1) { + pwm_second_channel = pwm_result; + + pwm_input_init(1); + + + } +} From 96a9d99782cc90ee498219fa1eadf6902740c89c Mon Sep 17 00:00:00 2001 From: Mateusz Lubecki Date: Sun, 24 Apr 2022 18:50:24 +0200 Subject: [PATCH 2/2] pwm input --- system/src/drivers/l4/pwm_input_stm32l4x.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/system/src/drivers/l4/pwm_input_stm32l4x.c b/system/src/drivers/l4/pwm_input_stm32l4x.c index 726aa92..cfc7a6d 100644 --- a/system/src/drivers/l4/pwm_input_stm32l4x.c +++ b/system/src/drivers/l4/pwm_input_stm32l4x.c @@ -6,8 +6,8 @@ #include uint8_t pwm_input_current_channel = 0; -uint16_t pwm_first_channel = 0; -uint16_t pwm_second_channel = 0; +uint32_t pwm_first_channel = 0; +uint32_t pwm_second_channel = 0; void pwm_input_io_init(void) { @@ -18,7 +18,7 @@ void pwm_input_io_init(void) { GPIO_InitTypeDef.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitTypeDef.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitTypeDef.Pin = LL_GPIO_PIN_6; - GPIO_InitTypeDef.Pull = LL_GPIO_PULL_NO; + GPIO_InitTypeDef.Pull = LL_GPIO_PULL_DOWN; GPIO_InitTypeDef.Speed = LL_GPIO_SPEED_FREQ_MEDIUM; GPIO_InitTypeDef.Alternate = LL_GPIO_AF_3; LL_GPIO_Init(GPIOC, &GPIO_InitTypeDef); @@ -108,19 +108,21 @@ void pwm_input_init(uint8_t channel) { void pwm_input_pool(void) { - uint16_t pwm_rising_edge = TIM8->CCR2 + 1; - uint16_t pwm_falling_edge = TIM8->CCR1 + 1; - - uint16_t pwm_result = 0; + uint32_t pwm_rising_edge = TIM8->CCR1 + 1; + uint32_t pwm_falling_edge = TIM8->CCR2 + 1; + uint32_t pwm_result = 0; // check preconditions - if (pwm_rising_edge != 0 && pwm_falling_edge != 0) { + if ((pwm_rising_edge != 0) && (pwm_falling_edge != 0)) { if (pwm_rising_edge > pwm_falling_edge) { + // result value is in percents scaled * 10 (100 means 10 percents) + pwm_falling_edge *= 1000; + pwm_result = (pwm_falling_edge / pwm_rising_edge ); } } else { - ; + ; // if not do nothing and keeps result to zero } if (pwm_input_current_channel == 1) {