Continuing the STM8 Expedition

STM8S105 Discovery

One Pulse Mode (OPM)

One Pulse Mode (OPM) is an additional feature of STM8 timers. It is like a monostable multivibrator or a one-shot timer that can be used to generate a pulse of fixed width after a defined amount of delay. It has several uses like wake up command generator for other onboard devices/microcontrollers, trigger for sensors like DHT22, etc.

Hardware Connection

opm

Code Example

#include "STM8S.h"


void clock_setup(void);
void GPIO_setup(void);
void TIM1_setup(void);


void main(void)
{
       clock_setup();
       GPIO_setup();
       TIM1_setup();

       while(TRUE)
       {
       };
}


void clock_setup(void)
{
       CLK_DeInit();

       CLK_HSECmd(ENABLE);
       while(CLK_GetFlagStatus(CLK_FLAG_HSERDY) == FALSE);

       CLK_LSICmd(DISABLE);

       CLK_HSICmd(ENABLE);
       while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == FALSE);

       CLK_ClockSwitchCmd(ENABLE);
       CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
       CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);

       CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE,
       DISABLE, CLK_CURRENTCLOCKSTATE_ENABLE);

       CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, ENABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, DISABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, DISABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, DISABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_AWU, DISABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART2, DISABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, DISABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER3, DISABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER4, DISABLE);
}


void GPIO_setup(void)
{            
       GPIO_DeInit(GPIOC);
       GPIO_Init(GPIOC, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST);
       GPIO_WriteHigh(GPIOC, GPIO_PIN_4);
       delay_ms(2000);
}


void TIM1_setup(void)
{
       TIM1_DeInit();

       TIM1_TimeBaseInit(160, TIM1_COUNTERMODE_UP, 10000, 1);

       TIM1_OC4Init(TIM1_OCMODE_PWM2,
                     TIM1_OUTPUTSTATE_ENABLE, 
                     6000,
                     TIM1_OCPOLARITY_HIGH, 
                     TIM1_OCIDLESTATE_RESET);

       TIM1_SelectOnePulseMode(TIM1_OPMODE_SINGLE);
       TIM1_CtrlPWMOutputs(ENABLE);
       TIM1_Cmd(ENABLE);
}

 

Explanation

Firstly, the peripheral and CPU clocks are set at max speed:

CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);
....  
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, ENABLE);

TIM1 is setup is as simply as we would do for PWM generation. However, for one pulse mode (OPM) we must select one pulse mode.

void TIM1_setup(void)
{
       TIM1_DeInit();

       TIM1_TimeBaseInit(160, TIM1_COUNTERMODE_UP, 10000, 1);

       TIM1_OC4Init(TIM1_OCMODE_PWM2,
                     TIM1_OUTPUTSTATE_ENABLE, 
                     6000,
                     TIM1_OCPOLARITY_HIGH, 
                     TIM1_OCIDLESTATE_RESET);

       TIM1_SelectOnePulseMode(TIM1_OPMODE_SINGLE);
       TIM1_CtrlPWMOutputs(ENABLE);
       TIM1_Cmd(ENABLE);
}

At this point it is necessary to describe TIM1 PWM modes. There are two PWM mode – PWM mode 1 and PWM mode 2.

PWM Mode 1

In up-counting mode, the channel is active if the counter is less than CCR1 or else it is inactive.
The opposite is true in down-counting mode.

PWM Mode 2

The channel is inactive as long as the counter is less than CCR1 in up- counting mode.

For OPM example here, we need PWM mode 2.

In this example the pulse width time of the one pulse is about 0.25ms and has a delay of 0.375ms. The calculation is very simple. Since 16MHz clock is used, one cycle takes 62.5ns and so 10000 counts equal 0.625ms. Because we are using PWM mode 2, it will take more than 6000 counts or 0.375ms before the one pulse start. The pulse has a width of (10000 – 6000) = 4000 counts or 0.25ms and will end after this time.

Demo

OPM

opm

Related Posts

19 comments

  • Dear Shawon,
    Thank you for your useful website and articles.
    I have taken a look at ADC1_Init definition and I found it uses ADC1_ConversionConfig to set channels and conversion mode. So it seems using ADC1_Init once with all needed channels is enough. Am I right?
    Thank you very much.

  • Hello,
    I am learning stm8s, but i have a project in my mind, i am making Pong game with two encoders and PCD8544 LCD. Your tutorials are great and it’s very big source of knowledge for me, and i have a question about this article:
    Is it possible to use two encoder this way? Or can it be done in the other way? I have stm8s103f3p6, and i know it has 4 interrupt pins, so I thought about using these for two encoders, but then i saw your article about QEI

  • Hello Friend!!
    Your stuff is great !!!
    Would you have an example 433 mhz rf signal capture with flash code writing?

  • Ola amigo !!!
    Seu material é excelente!
    Você teria algum exemplo de captura de sinal rf 433 mhz com gravação na flash?

  • Hello friends, pleasant paragraph ɑnd good urging commented ɑt tһiѕ ρlace,
    I ɑm truⅼy enjoying ƅy tһese.

  • Hi,
    Thats great work
    Do you have steps for to work ST7735 TFT IN 8 BIT 8080 mode

  • I don’t even understand how I ended up right here, however
    I believed this publish used to be good. I don’t know who you are however definitely
    you’re going to a well-known blogger should you aren’t already.
    Cheers!

  • Sankalp Rai Gambhir

    Thanks Shawon, your blogs are indeed very helpful. Keep Growing.

  • why are you sending the received data back through TX pin?

  • Hi SHAWON SHAHRYIAR

    I am wondering how to get a Max31855 to talk to a STM8s via SPI.

    JP

    • What’s to wonder about it? It is a simple SPI communication and SPI for STM8 is no different from the SPI of other MCUs…. The following lines are taken from the device’s datasheet and the write up there states how to communicate with it:

      “Drive CS low to output the first bit on the SO pin. A complete serial-interface read of the cold-junction compensated thermocouple temperature requires 14 clock cycles. Thirty-two clock cycles are required to read both the thermocouple and reference junction temperatures (Table 2 and Table 3.) The first bit, D31, is the thermocouple temperature sign bit, and is presented to the SO pin within tDV of the falling edge of CS. Bits D[30:18] contain the converted temperature in the order of MSB to LSB, and are presented to the SO pin within tD0 of the falling edge of SCK. Bit D16 is normally low and goes high when the thermocouple input is open or shorted to GND or VCC. The reference junction temperature data begins with D15. CS can be taken high at any point while clocking out con-version data. If T+ and T- are unconnected, the thermocouple temperature sign bit (D31) is 0, and the remainder of the thermocouple temperature value (D[30:18]) is 1.”

Leave a Reply

Your email address will not be published. Required fields are marked *