I had that idea to use the STM32duino to add Webserver capability quite easily to my little STM32 project that relies only on the peripherals (timers & interrupts).
Turns out it won't function as intended (well, does that ever happen?).
Here's a rough description of what I want to do:
a rising edge on a pin triggers Timer2 which generates a pulse for 2ms. On the end of that pulse, another pulse is started and held until a falling edge on the input pin occurs.
The triggering should be selectable between falling and rising edge.
As a variant the second pulse might be time controlled.
What I did is work out the peripheral config with the help of CubeIDE and wrote it down completely in either LL-functions or direct register manipulation.
I then created an Arduino sketch to have my webserver functionality. Basically a simple html page that has one or two fields in form to POST values that change the times. Switching between pulse-controlled output and time-controlled output is to be done by jumper. Selecting the active edge as well.
I the pasted the initialization code into the setup of the arduino sketch.
and it did not work

So, before I start digging into the depth of the STM32duino cores and other sources:
Has anyone done something similar before?
What should one take care of when trying to do such a project?
Any help/ideas welcome
here's the contents main arduino sketch file
Code: Select all
#include <Ethernet.h>
#include <EEPROM.h>
#include "SystemDefines.h"
#include "SystemVariables.h"
#include "Servers.h"
#include "stm32l4xx_ll_bus.h"
#include "stm32l4xx_ll_system.h"
#include "stm32l4xx_ll_exti.h"
#include "stm32l4xx_ll_gpio.h"
void setup()
{
memset(cPostParameters, 0, sizeof(cPostParameters));
Serial.begin(115200);
EEPROM.get(ADRESS_PULSLAENGE, dGesamtPulsdauer);
EEPROM.get(ADRESS_24V_ZEIT, d24V_Pulsdauer);
dAlteGesamtPulsdauer = dGesamtPulsdauer;
dAlte24V_Pulsdauer = d24V_Pulsdauer;
liCounter5V = ((dGesamtPulsdauer - d24V_Pulsdauer) * 250) - 1;
liCounter24V = (d24V_Pulsdauer * 250) - 1;
Serial.print("Pulslaenge 5V: "); Serial.println((dGesamtPulsdauer), 2);
Serial.print("Pulslaenge 24V: "); Serial.println((d24V_Pulsdauer), 2);
if(ETHERNET)
{
setupWebServer();
}
// setup interrupts
pinMode(3, OUTPUT);
pinMode(11, OUTPUT);
digitalWrite(3, LOW);
pinMode(2, INPUT); // Trigger comes as a rising slope on pin 2. External Pulldown needed, 100nF to Ground to avoid bouncing
pinMode(7, INPUT_PULLUP);
bPulseDurationIs = digitalRead(7);
if(bPulseDurationIs == TIME_CONTROLLED)Serial.println("bPulseDurationIs = TIME_CONTROLLED");
if(bPulseDurationIs == PULSE_CONTROLLED)Serial.println("bPulseDurationIs = PULSE_CONTROLLED");
//*-- GPIOA -----------------------------------------------
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
// Input to trigger pulse generation
LL_GPIO_SetPinMode( TRIGGER_24V_GPIO_Port, TRIGGER_24V_Pin, LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetPinSpeed( TRIGGER_24V_GPIO_Port, TRIGGER_24V_Pin, LL_GPIO_SPEED_FREQ_VERY_HIGH);
LL_GPIO_SetPinOutputType( TRIGGER_24V_GPIO_Port, TRIGGER_24V_Pin, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetAFPin_0_7( TRIGGER_24V_GPIO_Port, TRIGGER_24V_Pin, LL_GPIO_AF_2);
LL_GPIO_SetPinPull( TRIGGER_24V_GPIO_Port, TRIGGER_24V_Pin, LL_GPIO_PULL_NO);
// Output to 24V BTS
LL_GPIO_SetPinMode( BTS_24V_GPIO_Port, BTS_24V_Pin, LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetPinSpeed( BTS_24V_GPIO_Port, BTS_24V_Pin, LL_GPIO_SPEED_FREQ_VERY_HIGH);
LL_GPIO_SetPinOutputType( BTS_24V_GPIO_Port, BTS_24V_Pin, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull( BTS_24V_GPIO_Port, BTS_24V_Pin, LL_GPIO_PULL_UP);
LL_GPIO_SetAFPin_0_7( BTS_24V_GPIO_Port, BTS_24V_Pin, LL_GPIO_AF_1);
// Output to 5V BTS
LL_GPIO_SetPinMode( BTS_5V_GPIO_Port, BTS_5V_Pin, LL_GPIO_MODE_OUTPUT);
LL_GPIO_SetPinSpeed( BTS_5V_GPIO_Port, BTS_5V_Pin, LL_GPIO_SPEED_FREQ_VERY_HIGH);
LL_GPIO_SetPinOutputType( BTS_5V_GPIO_Port, BTS_5V_Pin, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull( BTS_5V_GPIO_Port, BTS_5V_Pin, LL_GPIO_PULL_UP);
// Simulated Trigger output, uses Timer 15 to generate a 25ms pulse every 60ms
LL_GPIO_SetPinMode( TRIGGER_SIMUL_GPIO_Port, TRIGGER_SIMUL_Pin, LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetPinSpeed( TRIGGER_SIMUL_GPIO_Port, TRIGGER_SIMUL_Pin, LL_GPIO_SPEED_FREQ_VERY_HIGH);
LL_GPIO_SetPinOutputType( TRIGGER_SIMUL_GPIO_Port, TRIGGER_SIMUL_Pin, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull( TRIGGER_SIMUL_GPIO_Port, TRIGGER_SIMUL_Pin, LL_GPIO_PULL_UP);
LL_GPIO_SetAFPin_0_7( TRIGGER_SIMUL_GPIO_Port, TRIGGER_SIMUL_Pin, LL_GPIO_AF_14);
//---------------------------------------------------------------------------*/
//*-- Timer 2 -----------------------------------------------
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(TIM2_IRQn);
TIM2->CR1 |= TIM_CR1_ARPE; // enable auto-reload buffer
TIM2->CCMR1 |= TIM_CCMR1_OC2PE; // enable preload register (buffered)
TIM2->CCMR1 |= TIM_CCMR1_OC2M_1; // set PWM mode 1 (togehter with next instruction)
TIM2->CCMR1 |= TIM_CCMR1_OC2M_2; // set PWM mode 1 (togehter with previous instruction)
TIM2->CCR2 = 1; // set compare value to 1 for a minmal pulse, will be overridden by fast mode
TIM2->CCER |= TIM_CCER_CC2P; // output of channel 2 is active low
TIM2->CCMR1 |= TIM_CCMR1_OC2FE; // enable fast mode
TIM2->CR1 |= TIM_CR1_OPM; // select one-pulse mode
TIM2->SMCR |= LL_TIM_SLAVEMODE_TRIGGER; // Timer is enabled in Trigger mode
TIM2->SMCR |= LL_TIM_TS_ETRF; // Trigger input is external pin (filtered)
TIM2->SMCR |= LL_TIM_ETR_FILTER_FDIV1_N2; // Filter external Trigger for 2 cycles
// TIM2->SMCR |= LL_TIM_ETR_FILTER_FDIV1_N4; // Filter external Trigger for 4 cycles
// TIM2->SMCR |= LL_TIM_ETR_FILTER_FDIV1_N8; // Filter external Trigger for 8 cycles
TIM2->CCER |= TIM_CCER_CC2E; // output of channel 2 is enabled
TIM2->BDTR |= TIM_BDTR_MOE; // enable outputs for this Timer
TIM2->CNT = 0; // Reset Count register to 0
TIM2->PSC = 79; // set prescaler in order to get 1µs clocks
TIM2->ARR = 1999; // we use complete period as high-time, so set it do desired duration of 2ms
TIM2->EGR |= TIM_EGR_UG; // generate update event to initialize all preloaded registers
while((!LL_TIM_IsActiveFlag_UPDATE(TIM2))){}; // wait fpr interrupt to have occured
LL_TIM_ClearFlag_UPDATE(TIM2); // clear flag
TIM2->DIER |= TIM_DIER_UIE; // enable interrupt on channel 2 Update
TIM2->DIER |= TIM_DIER_TIE; // enable interrupt on channel 2 Trigger
TIM2->CR1 |= TIM_CR1_CEN; // enable this Timer
//---------------------------------------------------------------------------*/
//*-- EXTI Line5 ------------------------------------------------------------------------------
LL_SYSCFG_SetEXTISource(LL_SYSCFG_EXTI_PORTA, LL_SYSCFG_EXTI_LINE5);
LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_5);
LL_EXTI_DisableEvent_0_31(LL_EXTI_LINE_5);
LL_EXTI_DisableRisingTrig_0_31(LL_EXTI_LINE_5);
LL_EXTI_EnableFallingTrig_0_31(LL_EXTI_LINE_5);
NVIC_SetPriority(EXTI9_5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(EXTI9_5_IRQn);
//---------------------------------------------------------------------------------*/
//*-- Timer 15 -----------------------------------------
// enable this on in last place, since it is the one that generates the simulated trigger
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM15);
TIM15->CR1 |= TIM_CR1_ARPE; // enable auto-reload buffer
TIM15->CCMR1 |= TIM_CCMR1_OC2PE; // enable preload register (buffered)
TIM15->CCMR1 |= TIM_CCMR1_OC2M_1; // set PWM mode 1 (togehter with next instruction)
TIM15->CCMR1 |= TIM_CCMR1_OC2M_2; // set PWM mode 1 (togehter with previous instruction)
TIM15->CCER |= TIM_CCER_CC2E; // output of channel 2 is enabled
TIM15->BDTR |= TIM_BDTR_MOE; // enable outputs for this Timer
TIM15->CNT = 0; // Reset Count register to 0
TIM15->PSC = 79; // set prescaler in order to get 1µs clocks
TIM15->ARR = 59999; // we want a period of 60ms
TIM15->CCR2 = 14999; // and a puls of 25ms
TIM15->EGR |= TIM_EGR_UG; // generate update event to initialize all preloaded registers
while((!LL_TIM_IsActiveFlag_UPDATE(TIM15))){};// wait fpr interrupt to have occured
LL_TIM_ClearFlag_UPDATE(TIM15); // clear flag
TIM15->CR1 |= TIM_CR1_CEN; // enable this Timer
//--------------------------------------------------*/
}
void loop()
{
delay(100);
handleWebRequest();
}
void EXTI9_5_IRQHandler(void)
{
// second edge has been detected, reset 5V BTS and LED
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_5))
{
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_5);
LL_GPIO_ResetOutputPin(BTS_5V_GPIO_Port, BTS_5V_Pin);
LL_GPIO_ResetOutputPin(LED_GPIO_Port, LED_Pin);
}
}
void TIM2_IRQHandler(void)
{
// Update event occured, this means the ms have passed, set 5V BTS
if(LL_TIM_IsActiveFlag_UPDATE(TIM2))
{
LL_TIM_ClearFlag_UPDATE(TIM2);
LL_GPIO_SetOutputPin(BTS_5V_GPIO_Port, BTS_5V_Pin);
}
//* TIM2 got triggered, set the LED
if(LL_TIM_IsActiveFlag_TRIG(TIM2))
{
LL_TIM_ClearFlag_TRIG(TIM2);
LL_GPIO_SetOutputPin(LED_GPIO_Port, LED_Pin);
}
//-----------------------------*/
}