PWM channel output pin not working

Post here first, or if you can't find a relevant section!
julian_lpp
Posts: 10
Joined: Tue Dec 24, 2024 4:32 pm

PWM channel output pin not working

Post by julian_lpp »

I wrote this simple code to let anyone check what I'm doing wrong... (I already have a larger code than this example)
The thing is that I expect the asociated channel3 timer3 's pin (PB0) to output the set pwm signal (1000hz 50%) but there seems to be no output whatsoever in PB0 pin.
On the other hand, using the interrupts service routines I can manage to drive some led connected to PB6, so the timer is already running as expected... (the led varies when I change the duty cicle as well)
So why there's no pwm in PB0?

I'm using a bluepill board (not sure if's a clone but I'd bet it is)

regards,
julian

Code: Select all

#define pin_T3_CH_3_PWM PB0
uint32_t T3_channel_3;
HardwareTimer *gTimer3PWM = new HardwareTimer(TIM3);  // Use Timer 3

const int PIN_LED = PB6;

setup(){

    digitalWrite(PIN_LED, LOW); 
    pinMode(PIN_LED, OUTPUT);

     T3_channel_3 = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(pin_T3_CH_3_PWM), PinMap_PWM));
     gTimer3PWM->setMode(T3_channel_3, TIMER_OUTPUT_COMPARE_PWM1, pin_T3_CH_3_PWM);   
     gTimer3PWM->setOverflow(1000, HERTZ_FORMAT);
     gTimer3PWM->setCaptureCompare(T3_channel_3, 50, PERCENT_COMPARE_FORMAT);
     gTimer3PWM->attachInterrupt(IRQ_T3_Update_IT_callback);
     gTimer3PWM->attachInterrupt(T3_channel_3, IRQ_T3_Compare_IT_callback);
     gTimer3PWM->resume();
	//rest of the code....
}

loop{
}

void IRQ_T3_Update_IT_callback(void){ 
    digitalWrite(PIN_LED, HIGH); 
}

void IRQ_T3_Compare_IT_callback(void){ 
    digitalWrite(PIN_LED, LOW);
}

fpiSTM
Posts: 1920
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 107
Location: Le Mans
Contact:

Re: PWM channel output pin not working

Post by fpiSTM »

Issue come from the Timer instance.
PB0 is TIM1 CH2N and not TIM3_CH3.

See the PinMap_TIM (PinMap_PWM) array:
https://github.com/stm32duino/Arduino_C ... #L109-L111

So 2 options:

Code: Select all

- HardwareTimer *gTimer3PWM = new HardwareTimer(TIM3);  // Use Timer 3
+HardwareTimer *gTimer3PWM = new HardwareTimer(TIM1);  // Use Timer 1
or

Code: Select all

- #define pin_T3_CH_3_PWM PB0
+ #define pin_T3_CH_3_PWM PB0_ALT1
To be generic you can also simply retrieve the instance:

Code: Select all

  // Automatically retrieve TIM instance and channel associated to pin
  // This is used to be compatible with all STM32 series automatically.
  TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(digitalPinToPinName(pin), PinMap_PWM);
julian_lpp
Posts: 10
Joined: Tue Dec 24, 2024 4:32 pm

Re: PWM channel output pin not working

Post by julian_lpp »

Great.
Now the problem evolves, cause in my original code I was already using the TIMER 1 channel 2 (pA8) , so now when I define

#define pin_T3_CH_3_PWM PB0_ALT1

the program freezes...

So the question is:
Is it possible to use the T1 channel2 (PA8) for capture event, and T3 channel 3 (PA0) for PWM given the fact that T1 channel 2 uses both PA8 and PA0 ?

regards

julian
ag123
Posts: 1883
Joined: Thu Dec 19, 2019 5:30 am
Answers: 30

Re: PWM channel output pin not working

Post by ag123 »

it is likely you need to configure the mux for each pin e.g. PA0 to connect to T3 ch 3 for PWM and PA8 to connect to T1 channel 2 and you can use that for capture event if it is defined in the specs sheet and/or ref manual that the alternate function exists.

accordingly
https://www.st.com/resource/en/datashee ... f103c8.pdf
it seemed PA0 has T2 ch1
and PA8 has T1 ch1

if you want T1 ch 2, that is on PA9 if you use this pin then you need to mux either uart1 or your timer at this pin, not both.
default PA9 goes to uart1 tx.
and in rm0008
https://www.st.com/resource/en/referenc ... ronics.pdf
chapter 14 Advanced-control timers (TIM1 and TIM8)
review this chapter and look at
Figure 52. Advanced-control timer block diagram
there may be some limitations to use both input capture and output compare from the same timer.
I'm not too certain how far can each channel be configured for different purposes.
But more than likely the full period needs to be the same for both, but it seemed the capture compare register can be set differently per channel, but i'm not sure about mixing the usage of input capture and output compare.

--
as for clone vs real stm32f103, for particular chips some of the issues I noted are like accessing some RTC registers in a correct way will freeze / hang the chip, and need to reset. then that some 'clone' chips has fake / non-existant temperature sensor which gives temperatures that are wildly incorrect using the formula in the datasheet / ref manual. there are also other issues such as an external LSI crystal will not oscillate I think there are after all fake 32k crystals sold on AliX, i.e. the cans may after all not be crystals, but just a can with 2 leads.
A google search would probably return other stories about them.
julian_lpp
Posts: 10
Joined: Tue Dec 24, 2024 4:32 pm

Re: PWM channel output pin not working

Post by julian_lpp »

I'll try to read carefully what you've posted. It's certainly very interesting

but
there may be some limitations to use both input capture and output compare from the same timer.
What I was trying to do is to use the inpùt capture with TIMER 1 and PWM with Timer 3 (Different timers). It's just (I guess) about being able to set up the PB0 for timer 3 rather than using it for Timer 1.
And again when I used the alternate definition "PB0_ALT1" the program stops working...
I'll keep working on it and maybe paste some example code to address specifically this issue
regards
julian
julian_lpp
Posts: 10
Joined: Tue Dec 24, 2024 4:32 pm

Re: PWM channel output pin not working

Post by julian_lpp »

Here I wrote a small fragment to reproduce the issue
Both timers 1 and 3 are working

With timer3 I feed the T1 input capture (PA8) to read the pwm frequency, the thing is that I need to produce the pwm doing a DigitalWrite inside pwm isr (and use another pin such as PB6 in this case) rather than being able to use the hardware PB0 T3 channel 3 pin

PB6 ----> PA8 reads the freq (pb6 is toggling inside pwm ISR by a digitalWrite)
PB0 ----> PA8 nothing read


I tried defining T3channel3 as PB0_ALT1 and PB0 with no luck
Hopefully there's some aditional insight I'm not seeing, thanks in advance

Note that I'm using a tft display to debug, cause I dont have a scope and never being able to use serial port with stlink either...

regards
julian

Code: Select all

#include <Arduino.h>

    const int PIN_LED = PB6;
    
    ///TIMER 3
    #define pin_T3_CH_3_PWM PB0_ALT1 //PB0
    uint32_t T3_channel_3;
    HardwareTimer *gTimer3PWM = new HardwareTimer(TIM3); 
       
    ///TIMER 1
    const uint32_t CPU_CLOCK = 72000000;  // STM32 clock (72 MHz)
    const uint32_t TIMER1_PRESCALER = 72;   // Prescaler value (72 gives 1 MHz timer frequency, 1 µs per tick) 
    #define pin_T1_CH1 PA8  // 
    HardwareTimer *gTimer1 = new HardwareTimer(TIM1);


    //esta macro fue sacada de st7789_Fast.h
	#define INCLUDE_BRG_to565(r,g,b) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | ((b) >> 3)) 

    #define TFT_DEF_black          0x0000
    //BLUE GREEN RED
    #define TFT_DEF_lila           0xf81F //0 OK
    #define TFT_DEF_rojo           0x001F //1 ok
    #define TFT_DEF_naranja        INCLUDE_BRG_to565(25,102,225) // 2 OK
    #define TFT_DEF_amarillo       INCLUDE_BRG_to565(0,255,255) //3 
    #define TFT_DEF_verde_claro    INCLUDE_BRG_to565(0,255,0) //4
    #define TFT_DEF_verde_oscuro   INCLUDE_BRG_to565(60,255,60)//5
    #define TFT_DEF_azul           INCLUDE_BRG_to565(255,0,0) //6
    #define TFT_DEF_celeste        0xFFE0  // 7 OK
    #define TFT_DEF_gris_claro     INCLUDE_BRG_to565(200,200,200) // 8 OK
    #define TFT_DEF_gris_oscuro    INCLUDE_BRG_to565(150,150,150) // 9 OK
    #define TFT_DEF_white          0xFFFF //10 OK


    #include <Adafruit_GFX.h>    // Core graphics library
    #include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
    //#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
    #include <SPI.h>
    //ANDANDO con el display 188
    #define TFT_CS     PB7
    #define TFT_DC     PB8
    #define TFT_RST    PB9
    Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);


    // Variables for pulse measurement
    volatile uint32_t v_lastCapture = 0;         // Last captured timer value
    volatile uint32_t v_periodTicks = 0;         // Calculated period in timer ticks
    volatile uint32_t v_overflowCount = 0;       // Overflow counter
    volatile bool v_newPeriodAvailable = false;  // Flag indicating a new period is available
    volatile uint32_t v_pulseCount = 0;          // Total pulse count


void setup() {

    SPI.begin(); 

    tft.initR( INITR_GREENTAB );
    tft.fillScreen(TFT_DEF_black);
    tft.setRotation(2);
       
    digitalWrite(PIN_LED, LOW); 
    pinMode(PIN_LED, OUTPUT); 

    Serial.begin(115200);  // Start serial communication


    T3_channel_3 = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(pin_T3_CH_3_PWM), PinMap_PWM));
    gTimer3PWM->setMode(T3_channel_3, TIMER_OUTPUT_COMPARE_PWM1, pin_T3_CH_3_PWM);   
    gTimer3PWM->setOverflow(125, HERTZ_FORMAT); // 
    gTimer3PWM->setCaptureCompare(T3_channel_3, 50, PERCENT_COMPARE_FORMAT); // 50% duty cycle
    gTimer3PWM->attachInterrupt(IRQ_T3_Update_IT_callback); ///OVERFLOW IRQ
    gTimer3PWM->attachInterrupt(T3_channel_3, IRQ_T3_Compare_IT_callback);
    gTimer3PWM->resume();


    // Timer 1 configuration for input capture
    pinMode(pin_T1_CH1, INPUT);
    gTimer1->setPrescaleFactor(TIMER1_PRESCALER);       // Set prescaler to 72
    gTimer1->setOverflow(0xFFFFFFFF, TICK_FORMAT);     // Use full 32-bit counter
    gTimer1->setMode(1, TIMER_INPUT_CAPTURE_RISING, pin_T1_CH1);  // Capture rising edges

    // Attach callbacks for input capture and overflow
    gTimer1->attachInterrupt(1, timerCaptureCallback);  // Capture interrupt
    gTimer1->attachInterrupt(timerOverflowCallback);   // Overflow interrupt
    gTimer1->resume();  // Start the timer
}

void loop() {

    static int i=0;

    if (v_newPeriodAvailable) {
        disableTimer1Interrupts();
        uint32_t periodTicks = v_periodTicks;
        v_newPeriodAvailable = false; 
        enableTimer1Interrupts(); 

        float frequencyHz = 0.0;

        if (periodTicks > 0) {
            // (se podrìa hacer todo en segundos y usar 1.0) Convert period ticks to time in microseconds
            float periodMicroseconds = periodTicks * (1.0 / CPU_CLOCK * TIMER1_PRESCALER) * 1e6;
            // Calculate frequency in Hz
            frequencyHz = 1000000.0 / periodMicroseconds;
        }

        static int iHz = 0;

        iHz += 50;
        if (iHz>1000){
            iHz=50;
        }
        gTimer3PWM->setOverflow(iHz, HERTZ_FORMAT); //             

        //tft.fillScreen(TFT_DEF_black);
        tft.setTextColor(TFT_DEF_naranja,TFT_DEF_black );
        tft.setCursor(0 , 0);    
        tft.setTextSize(2);
        tft.print(frequencyHz);

        delay(500);  
    }
}


void timerCaptureCallback() {
    uint32_t currentCapture = TIM1->CCR1;  // Capture value from Timer 1, Channel 1

    // Calculate the period in ticks
    if (v_lastCapture <= currentCapture) {
        v_periodTicks = currentCapture - v_lastCapture + (v_overflowCount << 32);
    } else {
        v_periodTicks = (0xFFFFFFFF - v_lastCapture + currentCapture) + (v_overflowCount - 1) << 32;
    }

    v_lastCapture = currentCapture;  // Update the last capture value
    v_overflowCount = 0;  // Reset overflow counter
    v_newPeriodAvailable = true;  // Set flag for new period
    
}

void timerOverflowCallback() {
    v_overflowCount++;  // Increment the overflow counter
}

void IRQ_T3_Update_IT_callback(void){ // Update event correspond to Rising edge of PWM when configured in PWM1 mode
    digitalWrite(PIN_LED, HIGH); 
}

void IRQ_T3_Compare_IT_callback(void){ // Compare match event correspond to falling edge of PWM when configured in PWM1 mode
    digitalWrite(PIN_LED, LOW);
}

// Disable only TIM1 interrupts
void disableTimer1Interrupts() {
  NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn);  // Disable TIM1 overflow interrupt
  NVIC_DisableIRQ(TIM1_CC_IRQn);        // Disable TIM1 capture/compare interrupt
}

// Enable only TIM1 interrupts
void enableTimer1Interrupts() {
  NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);   // Enable TIM1 overflow interrupt
  NVIC_EnableIRQ(TIM1_CC_IRQn);         // Enable TIM1 capture/compare interrupt
}


julian_lpp
Posts: 10
Joined: Tue Dec 24, 2024 4:32 pm

Re: PWM channel output pin not working

Post by julian_lpp »

Dont ask me how nor why, but it's working now after lot of rebuildings and mofifications.... Of course I was doing something badly wrong,
Now the pwm of timer3 feeds correctly the timer1 input capture channel

Thanks fpiSTM you were right with PB0_ALT1
regards,
julian

Code: Select all

    #include <Arduino.h>

    const int PIN_LED = PB6;
    
    ///TIMER 3
    #define pin_T3_CH_3_PWM PB0_ALT1 // PB0_ALT1  == 3 (timer3)   //PB0 == 2 (timer1)
    uint32_t T3_channel_3;
    HardwareTimer *gTimer3PWM = new HardwareTimer(TIM3); 
       
    ///TIMER 1
    const uint32_t CPU_CLOCK = 72000000;  // STM32 clock (72 MHz)
    const uint32_t TIMER1_PRESCALER = 72;   // Prescaler value (72 gives 1 MHz timer frequency, 1 µs per tick) 
    #define pin_T1_CH1 PA8  // 
    uint32_t T1_channel_1;
    HardwareTimer *gTimer1 = new HardwareTimer(TIM1);


    //esta macro fue sacada de st7789_Fast.h
	#define INCLUDE_BRG_to565(r,g,b) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | ((b) >> 3)) 

    #define TFT_DEF_black          0x0000
    //BLUE GREEN RED
    #define TFT_DEF_lila           0xf81F //0 OK
    #define TFT_DEF_rojo           0x001F //1 ok
    #define TFT_DEF_naranja        INCLUDE_BRG_to565(25,102,225) // 2 OK
    #define TFT_DEF_amarillo       INCLUDE_BRG_to565(0,255,255) //3 
    #define TFT_DEF_verde_claro    INCLUDE_BRG_to565(0,255,0) //4
    #define TFT_DEF_verde_oscuro   INCLUDE_BRG_to565(60,255,60)//5
    #define TFT_DEF_azul           INCLUDE_BRG_to565(255,0,0) //6
    #define TFT_DEF_celeste        0xFFE0  // 7 OK
    #define TFT_DEF_gris_claro     INCLUDE_BRG_to565(200,200,200) // 8 OK
    #define TFT_DEF_gris_oscuro    INCLUDE_BRG_to565(150,150,150) // 9 OK
    #define TFT_DEF_white          0xFFFF //10 OK


    #include <Adafruit_GFX.h>    // Core graphics library
    #include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
    //#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
    #include <SPI.h>
    //ANDANDO con el display 188
    #define TFT_CS     PB7
    #define TFT_DC     PB8
    #define TFT_RST    PB9
    Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);


    // Variables for pulse measurement
    volatile uint32_t v_lastCapture = 0;         // Last captured timer value
    volatile uint32_t v_periodTicks = 0;         // Calculated period in timer ticks
    volatile uint32_t v_overflowCount = 0;       // Overflow counter
    volatile bool v_newPeriodAvailable = false;  // Flag indicating a new period is available
    volatile uint32_t v_pulseCount = 0;          // Total pulse count


void setup() {

    SPI.begin(); 

    tft.initR( INITR_GREENTAB );
    tft.fillScreen(TFT_DEF_black);
    tft.setRotation(2);
       
    digitalWrite(PIN_LED, LOW); 
    pinMode(PIN_LED, OUTPUT); 

    //Serial.begin(115200);  // Start serial communication
    pinMode(pin_T3_CH_3_PWM, OUTPUT);
    T3_channel_3 = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(pin_T3_CH_3_PWM), PinMap_PWM));
    gTimer3PWM->setMode(T3_channel_3, TIMER_OUTPUT_COMPARE_PWM1, pin_T3_CH_3_PWM);   
    gTimer3PWM->setOverflow(125, HERTZ_FORMAT); // 
    gTimer3PWM->setCaptureCompare(T3_channel_3, 50, PERCENT_COMPARE_FORMAT); // 50% duty cycle
    gTimer3PWM->attachInterrupt(IRQ_T3_Update_IT_callback); ///OVERFLOW IRQ
    gTimer3PWM->attachInterrupt(T3_channel_3, IRQ_T3_Compare_IT_callback);
    gTimer3PWM->resume();

  
    // Timer 1 configuration for input capture


    // Configure Timer 1 in Input Capture mode
    pinMode(pin_T1_CH1, INPUT);
    T1_channel_1 = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(pin_T1_CH1), PinMap_PWM));
    gTimer1->setMode(T1_channel_1, TIMER_INPUT_CAPTURE_RISING, pin_T1_CH1); // Channel 2, Rising edge
    gTimer1->setPrescaleFactor(TIMER1_PRESCALER );              // Set prescaler to 7200
    gTimer1->setOverflow(0x10000); // Maximo valor de overflow para timer de 16 bits EN HEXADECIMAL
    gTimer1->attachInterrupt(T1_channel_1, timerCaptureCallback);   // Attach callback for TIM1_CH2
    gTimer1->attachInterrupt(timerOverflowCallback); // Attach overflow callback
    gTimer1->resume();    



}

void loop() {

    static int i=0;

    if (v_newPeriodAvailable) {
        disableTimer1Interrupts();
        uint32_t periodTicks = v_periodTicks;
        v_newPeriodAvailable = false; 
        enableTimer1Interrupts(); 

        float frequencyHz = 0.0;

        if (periodTicks > 0) {
            // (se podrìa hacer todo en segundos y usar 1.0) Convert period ticks to time in microseconds
            float periodMicroseconds = periodTicks * (1.0 / CPU_CLOCK * TIMER1_PRESCALER) * 1e6;
            // Calculate frequency in Hz
            frequencyHz = 1000000.0 / periodMicroseconds;
        }

        static int iHz = 0;

        iHz += 50;
        if (iHz>1000){
            iHz=50;
        }
        gTimer3PWM->setOverflow(iHz, HERTZ_FORMAT); //             

        //tft.fillScreen(TFT_DEF_black);
        tft.setTextColor(TFT_DEF_naranja,TFT_DEF_black );
        tft.setCursor(0 , 0);    
        tft.setTextSize(2);
        tft.print(frequencyHz);
        //tft.print("x");

        delay(500);  
    }
}


void timerCaptureCallback() {
    uint32_t currentCapture = TIM1->CCR1;  // Capture value from Timer 1, Channel 1

    // Calculate the period in ticks
    if (v_lastCapture <= currentCapture) {
        v_periodTicks = currentCapture - v_lastCapture + (v_overflowCount << 32);
    } else {
        v_periodTicks = (0xFFFFFFFF - v_lastCapture + currentCapture) + (v_overflowCount - 1) << 32;
    }

    v_lastCapture = currentCapture;  // Update the last capture value
    v_overflowCount = 0;  // Reset overflow counter
    v_newPeriodAvailable = true;  // Set flag for new period
    
}

void timerOverflowCallback() {
    v_overflowCount++;  // Increment the overflow counter
}

void IRQ_T3_Update_IT_callback(void){ // Update event correspond to Rising edge of PWM when configured in PWM1 mode
    //digitalWrite(PIN_LED, HIGH); 
}

void IRQ_T3_Compare_IT_callback(void){ // Compare match event correspond to falling edge of PWM when configured in PWM1 mode
    //digitalWrite(PIN_LED, LOW);
}

// Disable only TIM1 interrupts
void disableTimer1Interrupts() {
  NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn);  // Disable TIM1 overflow interrupt
  NVIC_DisableIRQ(TIM1_CC_IRQn);        // Disable TIM1 capture/compare interrupt
}

// Enable only TIM1 interrupts
void enableTimer1Interrupts() {
  NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);   // Enable TIM1 overflow interrupt
  NVIC_EnableIRQ(TIM1_CC_IRQn);         // Enable TIM1 capture/compare interrupt
}


ag123
Posts: 1883
Joined: Thu Dec 19, 2019 5:30 am
Answers: 30

Re: PWM channel output pin not working

Post by ag123 »

I took a closer look at the pin mux in stm32f103
https://www.st.com/resource/en/referenc ... ronics.pdf
Chapter 9 General-purpose and alternate-function I/Os (GPIOs and AFIOs)

vs stm32f401
https://www.st.com/resource/en/referenc ... ronics.pdf
Chapter 8 General-purpose I/Os (GPIO)

It is fairly apparent that the pin mux between F103xx vs F4xx series is different
on the STM32F103 AFIO outputs depends on the port bit configuration CNF1 (Table 20) and that the several AFIO sharing the same pin are not further muxed. This means that it is necessary to enable only one peripheral e.g. at PA9 either UART1 TX or T1 CH2.
If you enable T1 CH2 by configuring that at the timer, you would need to disable UART1 (i.e. Serial1) in the peripheral enable/disable register.

Whereas in stm32f401 there are 2 mux config in the GPIO port, Table 24. Port bit configuration table MODER controls selecting between GPIO and AFIO. Alternate function is further selected by GPIOx_AFRL, GPIOx_AFRH registers
And that alternate function selection is by groups in table 9 Alternate function mapping
https://www.st.com/resource/en/datashee ... f401cb.pdf
this allows for more precise selection of specific AFIO at the selected port.
However, the selection of AFIO functions by group means that certain combinations are not possible, as only one group is selected for the port at a time.
julian_lpp
Posts: 10
Joined: Tue Dec 24, 2024 4:32 pm

Re: PWM channel output pin not working

Post by julian_lpp »

Interesting, however I imagine that all that direct register manipulation is done here:

Code: Select all

gTimer3PWM->setMode(T3_channel_3, TIMER_OUTPUT_COMPARE_PWM1, pin_T3_CH_3_PWM);  
cause in no place I specified that I wanted to use PB0''s alternate function... :roll:

regards,
julian
ag123
Posts: 1883
Joined: Thu Dec 19, 2019 5:30 am
Answers: 30

Re: PWM channel output pin not working

Post by ag123 »

@julian_lpp
it would take reviewing the codes to figure out what is done, but that among the things that needs to be done at the register level are:
- to configure Timer (3) (e.g. output compare) and the output registers so that the timer output goes to the pin (setting the timer registers)
- to configure the GPIO pin so that it select AFIO instead of gpio (setting the gpio registers)
this 2 steps would make the Timer PWM outputs appear at the pin.

I've not really played with input capture prior, but I'd guess for input capture, the gpio pin only needs to be in 'input' as inputs can be shared.
Then to configure the timer (1) to do input capture.

--
Off-topic:
for LCD I'd guess mainly SPI is used. So that is mainly for the backlight?

I'm more a fan of the stm32f4xx series, stm32f103c{8,b} is ok but performance, sram, flash trails e.g. stm32f401/f411 and generally the f4xx family
for stm32f4xx boards there are offerings from :
weact (apparently pretty popular)
https://github.com/WeActStudio/WeActStu ... iSTM32F4x1
https://stm32-base.org/boards/STM32F411 ... -V2.0.html
ST itself has stm32f411/f401 nucleo
https://www.st.com/en/evaluation-tools/ ... 411re.html
https://www.st.com/en/evaluation-tools/ ... 401re.html
then Adafruit has stm32f405
https://www.adafruit.com/product/4382
Adafruit's board is 'costly' but it is a big chip, and it may depend on your location as say if you are in US or Europe, shipping may cost less vs say in Asia.
Then micropython has boards
https://store.micropython.org/
and Olimex has boards
https://www.olimex.com/Products/ARM/ST/

and if you goto Aliexpress and search stm32f401 keyword, boards show up as well. Not necessary from WeAct, but I've a few working ones that works well/ok.
Last edited by ag123 on Fri Jan 10, 2025 5:05 am, edited 2 times in total.
Post Reply

Return to “General discussion”