Stm32 Delay Using Timers or Systick

Поділитися
Вставка
  • Опубліковано 8 лис 2024

КОМЕНТАРІ • 94

  • @muhammadusmanhussain9426
    @muhammadusmanhussain9426 4 роки тому +7

    Hi thanks for the great video. Maybe you figured it out already but still incase you have not I would like to tell you the reason you could not get 1 sec interrupts with a 72 divider on the ARR register. It was because the HCLK clock frequency after being divided by the APB1/2 prescaler gets further multiplied by "2" before being used by the Timers. Again Thanks for the video was really helpful in my project which I am doing for my degree. Best Regards Usman

  • @microtan6775
    @microtan6775 Рік тому +1

    Best tutorial ever found for stm32!

  • @mistymisty4480
    @mistymisty4480 6 років тому +3

    Excellent stuff! At this rate youight as well go through the other peripherals like i2c, UART, CAN bus etc your videos are so useful making these easier to consume 👍 thanks

    • @kaidenarian1638
      @kaidenarian1638 3 роки тому

      i dont mean to be so offtopic but does anybody know of a way to log back into an instagram account?
      I was dumb lost the login password. I love any tips you can offer me.

    • @taylorlandon2264
      @taylorlandon2264 3 роки тому

      @Kaiden Arian instablaster ;)

    • @kaidenarian1638
      @kaidenarian1638 3 роки тому

      @Taylor Landon Thanks so much for your reply. I found the site thru google and Im waiting for the hacking stuff atm.
      I see it takes quite some time so I will get back to you later when my account password hopefully is recovered.

    • @kaidenarian1638
      @kaidenarian1638 3 роки тому

      @Taylor Landon It did the trick and I now got access to my account again. I'm so happy!
      Thanks so much, you saved my account!

    • @taylorlandon2264
      @taylorlandon2264 3 роки тому

      @Kaiden Arian No problem xD

  • @matejberes1749
    @matejberes1749 5 років тому +6

    Hi, you should clear flag (UIF) before incrementing myTicks variable.The ARR register should be 71 not 72 because the zero is also one state of counter. I hope this helps.

    • @EdwinFairchild
      @EdwinFairchild  5 років тому +1

      Good catch! Thanks!!!!

    • @rishabsrivastava4705
      @rishabsrivastava4705 5 років тому

      That worked !!!
      Thanks.

    • @dungphan7581
      @dungphan7581 4 роки тому

      Can also confirm! clear UIF b4 incrementing myTicks does the trick. I reckon that it reduce the non-counting period between each timer period, is it not?

  • @Synthetech
    @Synthetech 5 років тому +2

    Thanks for posting this video. I needed a delay that allowed the rest of my application to run while pause a moment before I update a 16x2 LCD.
    Evidently the Hitachi LCD needs at least a 2ms delay between updates since it is a bit slow to keep up.. It will stutter/produce garbage if it is hit too fast with data.
    I don't want to use HAL_Delay because it would freeze up a DMA stream while waiting for the Delay :(
    I figured a timer was needed, but this video saved me the trouble of figuring out how to use it ;-)

    • @MilanKarakas
      @MilanKarakas 5 років тому

      Does 16x2 LCD has pin for interrupt? If I remember correctly, it has some flag or interrupt pin that sends to MCU when it is ready to receive new data. Seems that nobody use that feature, maybe one wire more is too much?

    • @Synthetech
      @Synthetech 5 років тому

      @@MilanKarakas I think it's the DB7 Busy Flag pin you are referring to.
      Good idea to check into..

    • @MilanKarakas
      @MilanKarakas 5 років тому

      @@Synthetech Yes, probably that one. I should to check datasheet for exact name and which state is buy and which ready.

    • @MilanKarakas
      @MilanKarakas 5 років тому

      @@Synthetech Okay, that is correct. If DB7 is high, then it means "not ready". So, you can use 4 bits transfer (lower nibble, higher nibble, and then DB7 is free), or better to use 8 bits transfer - but then after transfer first message - change status of this pin on your MCU from output to input and make loop or interrupt that wait for "low" to continue sending data. Then just switch back this pin as output. Sounds complicated, but I bet this will do things faster than calculating how much time LCD need to process data you sent to it.

    • @Synthetech
      @Synthetech 5 років тому +1

      @@MilanKarakas thanks for the tip Milan.
      I may check into that later on.. I'm building a Synthesizer project using a Stm32F407 driving a stereo 16bit DAC via I2S.
      I have good synth Oscillators in various waveforms, now working on using UART to RX MIDI to trigger notes and change parameters with Control Changes.
      I used a LCD to verify the UART rx'ing MIDI.
      I have more bugs to work thru.. Either the UART interrupt or the i2c port is making a slight choke in the I2S stream.. I can hear the sound change a moment every time the LCD updates/UART Rx's MIDI..
      A lot going on in there.. A lot to learn...

  • @jamescullins2709
    @jamescullins2709 5 років тому +3

    I would like to see a video on the one shot timer out of the STM32F1xx.

  • @Alejandro-mr2si
    @Alejandro-mr2si 4 роки тому +1

    thanks, you are more useful than my master degree

    • @aswd45-mk14
      @aswd45-mk14 3 роки тому

      Jesus f**k it’s frustrating. We are paying big $$$ and received no help or little help. Like wtf....😤

  • @mauricekitana6587
    @mauricekitana6587 2 роки тому

    The global variable updated in interrupt handler may require to be declared volatile other under certain compiler optimization will have issues

  • @arielcampos2008
    @arielcampos2008 6 років тому +2

    I'm learning about arm microcontroller at college, thanks for sharing this video. Could You make one explaining how to use Multiplies ADC at the same time?

  • @madeleinekearns919
    @madeleinekearns919 3 роки тому +1

    Great tutorial thanks so much!

  • @ayushmittal4778
    @ayushmittal4778 5 років тому +1

    hello eddie amaya ,
    i really appreciate your understanding of interrupts and timers but i have just a simple thought in mind , instead of working with interrupts if we initialize the prescaler with 36000 (if the system clock is 72 Mhz ) that will make the counter clock to be of 2khz which means 2000 counts in one second , now if we initialize the auto reload register value to be 2000 it should give us a delay of 1 sec . i just want your thoughts on this if i am going somewhere wrong with this idea.

    • @EdwinFairchild
      @EdwinFairchild  5 років тому

      Only one way to find out...give it a shot

  • @facademy4641
    @facademy4641 2 роки тому

    Hello sir, do you know how a timer can be programmed as delay in the ARDUINO IDE using STM32xxx?

  • @akshitshah2963
    @akshitshah2963 4 роки тому

    Thank you .it was really useful

  • @rochdimaria
    @rochdimaria 4 роки тому +1

    Thanks Man ! Could you do a video for Input capture mode

  • @praveenkumars4243
    @praveenkumars4243 4 роки тому +4

    Why such a complicated dMs() function?
    It could simply be
    void dMs(int mS){
    dUs(mS*1000);
    }
    Anyways I love your tutorials. You have good quality information I couldn't find elsewhere. Keep making more videos. :)

    • @mauricekitana6587
      @mauricekitana6587 2 роки тому

      This may not be very accurate because overhead of calling the inner dUs function. Second if the argument mS is large the global variable updated in interrupt may need to be a long int which stm32 cannot guarantee atomic read or write.

  • @caffeinatedinsanity2324
    @caffeinatedinsanity2324 4 роки тому

    I wonder if using the STM32's internal RTC for an Arduino-style millis() timer would be a plausible idea. I mean... I'm using a Blue Pill and it's mainly a Real Time Counter (and not clock because it does not have a hardware calendar).

    • @EdwinFairchild
      @EdwinFairchild  4 роки тому

      yes plausible but unless you need serious "real time" its a lot of effort for what should be an otherwise simple task

  • @emmetray9703
    @emmetray9703 4 роки тому +1

    Did you figre out why it gives us 1 second delay with 144 ARR register value?

    • @emmetray9703
      @emmetray9703 4 роки тому

      @@paatazarnadze7673 ქვემოთ ლინკი დავდე . მაგის მიხედვით ვქენი და ეხლა ორმაგად აღარ შვება.

    • @emmetray9703
      @emmetray9703 4 роки тому

      @@paatazarnadze7673 ფბზე ვერ გიპოვე და ესაა ლინკი.
      www.keil.com/support/docs/3928.htm

  • @MilanKarakas
    @MilanKarakas 5 років тому

    Well done! I need your help. Does this sysTick can act as 'millis' on Arduino? I mean, sometimes aside delay, we should to convert some codes into Keil or other environment. And, please continue making great videos. Thanks.

    • @EdwinFairchild
      @EdwinFairchild  5 років тому

      im not sure how arduino handles millis , but the systick can be used to generate delays via a flag of sorts like i explained in the video. However if using Cube Hal you dont want to modify systick counter. there is also DWT available on certain stm32 which can give even better resolution of micro seconds... more or less

    • @MilanKarakas
      @MilanKarakas 5 років тому

      @@EdwinFairchild I am not using CubeMX and Hal because it is so confusing and hard to understand what is what. Also I will later look for DWT as well. I made stupid cycle loop with NOPs and 'calibrated' on 1 uS, but as number grows it is totally wrong. So, now I am callibrating at 1000 uS, and it is much better - still 1 uS is 1.6 uS or so, 10 uS is 10.2 uS, and going up it goes at oposite direction - 100 uS showed me 97.3 uS. Yet, I am worried when I need short delay for some processes, rather than longer ones.

  • @jericotaleon
    @jericotaleon 5 років тому

    Hi Eddie! I tried this tutorial with my STM32F103C8. I turned on the LED for 10uS, and off for 100uS. So I connected the logic analyzer to PC13 - the problem is, I am getting 7.6uS instead of 10, and 76uS instead of 100. Does it have something to do with default clock settings?

    • @EdwinFairchild
      @EdwinFairchild  5 років тому

      No, it has to do with the fact that we are not taking into account the time it takes to execute functions, load variables change variables, add a number etc.... these are not "REAL TIME" Systems but pretty close. To get even better accuracy if 7us instead of 10us is an issue one would have make the delay in assembly where you can see how many instructions you are using and thus really count clock cycles.. Try this code
      #pragma GCC push_options
      #pragma GCC optimize ("O3")
      void delayUS_DWT(uint32_t us) {
      volatile uint32_t cycles = (SystemCoreClock/1000000L)*us;
      volatile uint32_t start = DWT->CYCCNT;
      do {
      } while(DWT->CYCCNT - start < cycles);
      }

    • @EdwinFairchild
      @EdwinFairchild  5 років тому

      and check this tutorial www.carminenoviello.com/2015/09/04/precisely-measure-microseconds-stm32/

    • @jericotaleon
      @jericotaleon 5 років тому +1

      @@EdwinFairchild Oh I get it! okay will test this and let you know the outcome. Thank you very much Eddie! BTW what is your nationality? just curious.

    • @EdwinFairchild
      @EdwinFairchild  5 років тому

      @@jericotaleon I am from Honduras

  • @neharikamsadhwani5140
    @neharikamsadhwani5140 6 років тому

    This video was very useful but How to add delay in STM32 without using any interrupts in the TIM4?

    • @EdwinFairchild
      @EdwinFairchild  6 років тому

      Neharika M Sadhwani you can have a while loop where you simple check the over flow flag as many times as you need for your specific time required. However what would you not want to use the interrupt since I made it so they only occurred when you need the delay?

  • @abhijeetsingh2842
    @abhijeetsingh2842 5 років тому

    Can you please share me the code because is am starting working on it and I have less knowledge of programing

  • @ryansy1741
    @ryansy1741 4 роки тому

    Hello Sir thank you very much for your tutorial this is very helpful. I just wanted to ask you for some advise regarding the delay when multiple outputs are enabled. I defined the delay as 5ms based on your code. Now I wanted to activate 2 GPIOs with each having their own 5ms delay upon activation regardless of the state of the other GPIO.
    Now problem happens when I activate LED_GPIO2 when LED_GPIO1 is already activated prior to activating LED_GPIO2. The delay becomes more than 5msec for the LED_GPIO2. May I ask how to write the code so that both codes are independent of each other. Thank you very much for your time.
    while (1)
    {
    {
    if(HAL_GPIO_ReadPin(BUTTON_GPIO1_GPIO_Port, BUTTON_GPIO1_Pin))
    {
    timedelay(5);
    HAL_GPIO_WritePin(LED_GPIO1_GPIO_Port, LED_GPIO1_Pin, GPIO_PIN_SET);
    }
    else
    {
    HAL_GPIO_WritePin(LED_GPIO1_GPIO_Port, LED_GPIO1_Pin, GPIO_PIN_RESET);

    }
    }

    {
    if(HAL_GPIO_ReadPin(BUTTON_GPIO2_GPIO_Port, BUTTON_GPIO2_Pin))
    {
    timedelay(5);
    HAL_GPIO_WritePin(LED_GPIO2_GPIO_Port, LED_GPIO2_Pin, GPIO_PIN_SET);
    }
    else
    {
    HAL_GPIO_WritePin(LED_GPIO2_GPIO_Port, LED_GPIO2_Pin, GPIO_PIN_RESET);
    }
    }

  • @kashimgs1396
    @kashimgs1396 3 роки тому

    sir
    please can you help me for creating really long delays like 100 hours and more
    and call interrupts in between

    • @EdwinFairchild
      @EdwinFairchild  3 роки тому

      this is very simple math sir...delay for 1ms, at the end of that delay increment a 32 unsigned variable....when the variable reaches the max number you will have delayed for 1193 hours...think about...its really simple...just change the max number you want the 32 bit variable to count up to in order to get your 100hrs

  • @last-zura8899
    @last-zura8899 Рік тому

    thank you

  • @craigkinney853
    @craigkinney853 4 роки тому

    HI Can you guys here help me with this? i got this timer working a while back but instead of understanding what i'm doing i just accepted that it works but now getting fustrated about not understanding it. the section void TIM4_IRQHandler(void)
    {
    msTicks++;
    TIM4->SR &= ~TIM_SR_UIF;
    };
    how does this work? its not a for loop that doing the incrementing of the msTick++ so how does it make the time increment in the handler?
    secondly not sure about the UIF (update interupt flag) is this part of the interupt circuit and acts as the trigger to tell it that the UEV (Update event) has triggered and the ARR can now be reset?
    Cant get my brain around this so if anyone can give a laymens explination - much Appreciated. Thanks in advance

    • @EdwinFairchild
      @EdwinFairchild  4 роки тому

      Ok so the timer code which is setup in a different section , sets the timer up so that it stays counting up at the value set inside the ARR register. So let's pretend that value is 1000. Everytime the timer reaches 1000 it will jump into the IRQ Handler function and run the code inside it. Obviously the code inside it is Justin reading a variable , even when the regular code is trapped inside a while loop this function will always get called and increment msTicks Everytime the timer reaches it's goal of 1000. Let's say it's takes 1 second for the timer to count to 1000, so once every second this function will get called. So if you wanted to make a delay for 2 seconds you will call the delay function and have it set msTicks to zero, and wait inside a while loop untill msTicks equals 2, since this function will still get called while waiting in that loop, eventually it will be called enough times so that msTiCkS equals 2, and then your whille loop condition will be true and you will have been there for 2 seconds. Hope this helps 🙏😁

    • @craigkinney853
      @craigkinney853 4 роки тому

      @@EdwinFairchild Hi Eddie
      Nah Sorry mate still confused. I under stand the Timer section being set up th the ARR being the count point that is in relation to the frequency created by the PSC. however my brain cannot get around what is going on with this IRQ section. i've tried running it in de-bug mode, however you can run the handler as part of de-bug.
      When you say the ARR register reaches 1000 then jumps to the IRQ. then how does it know to do that ? is it the UEV which forces the UIF?
      As for when you say the function still get called when in the 'While' loop i assume you mean the IRQ is running in the back ground doing the incrementing. i just can see how it all joins together i'm afraid. Thanks for the help any way.
      Keep up the good work.
      Craig

    • @EdwinFairchild
      @EdwinFairchild  4 роки тому

      @@craigkinney853 when the count register matches the ARR value the mcu was designed in a way so that I jump to a specific address, that address is the irq function which is assigned a name and address we cannot change because the chip was designed that way. The irq dies not run in the back ground ... It only runs when count register matches the ARR value , then mcu Jumps to the irq (because hardware design internal to the chip ) then inside the irq we increment the variable ... Then when the irq function is done it's jumps back to where it left off , which was the while loop

    • @EdwinFairchild
      @EdwinFairchild  4 роки тому

      @@craigkinney853 and yes by enabling certain interrupts we tell the mcu to jump to that specific address (irq) ... So if the update event is enabled , it will jump to the irq anything an update even occrs

    • @craigkinney853
      @craigkinney853 4 роки тому

      @@EdwinFairchild Hi Eddie
      OK so as part of the ARR and other part of the timer when they all meet the criteria the IRQ will invoke anyway as this is somehting that ARM (or ST) have built into the chips MCU anyway. The IRQ will increment the msTick variable as part of its function and from what i can work out the TIM->SR &=UIF is reseting this before going back to the program.
      i'm probably hazarding a guess. trying to read stuff from the datasheet.
      Thanks Eddie.I'll buy you a pint one day.

  • @eulaliorodriguez7055
    @eulaliorodriguez7055 4 роки тому

    My program runs ok in debug mode but not in run mode. Why?

    • @EdwinFairchild
      @EdwinFairchild  4 роки тому

      Interesting, send me the code. eddie@edwinfairchild.com

  • @Amin_ab
    @Amin_ab 4 роки тому

    Thank you for your video, if we use systick_config(systemcoreclock / 1000000) we can generate microsecond delay

    • @EdwinFairchild
      @EdwinFairchild  4 роки тому +1

      No, you have to account for the time it takes to excited instructions time it takes to enter and exit a function etc..

  • @MilanKarakas
    @MilanKarakas 5 років тому

    Something is strange here. Tried to watch on oscilloscope and if 10 uS, then it shows 25 uS, so 250%, and for 100 uS, it shows 148 uS, or 148%, for 1000 uS, it shows 1370 uS instead, or 137%. That is bit wrong. I will try to get it right later, after some sleep. Thank you anyway for the motivation.

    • @EdwinFairchild
      @EdwinFairchild  5 років тому +1

      yeah check my math maybe i got something wrong, also check your operating frequency , ARR etc... just redo the math based on what the datasheet says. I really dont remember the formulas off the top of my head. Also keep in mind any overhead of the time required to call a function , raise a pin high or low, clear an interrupt and so on.... this is not a real time system , but you should get decent results. I doont have a scope anymore so i cant check anything right now

    • @MilanKarakas
      @MilanKarakas 5 років тому +1

      @@EdwinFairchild That's true. But, also... How I can be sure that counter always starting from zero, not from some number left earlier? Noticed that cycles on the scope are not stable, so probably after overflow it continues to counting for a while until interrupt flag is not cleared. On the other hand, my loop with nops work stable, always the same no matter it may be slightly wrong in duration. What about counting back from some number we set? If we pre-load counter, then counting back to zero (or underflow), then if needed checking whether our number is sufficient (0-65535), if not add one more loop... That may be very complicated. I remember earlier days of programming PIC in assembler, and only way to do loop is exactly counting how long take one instruction to execute, then including more and more wasted cycles. The strange thing is that I con't know here how much any instruction last, one cycle, half cycle, two cycles or more?

    • @EdwinFairchild
      @EdwinFairchild  5 років тому

      @@MilanKarakas defiantly an assembly based delay would be very much more precise. You should check out ARM thumb instruction set and try some inline assembly in Keil. Again this is not ment to give exact timing or even be deterministic, there are a lot of things that can influence how long it takes to execute something. Specially in the microsecond scale. Critical timing would require another approach. This more like a general timing approach if you need a delay of exact precision I would look into different approaches such as assembly. If you need a delay of 50ms but don't matter if it's not exact then this is fine.

    • @EdwinFairchild
      @EdwinFairchild  5 років тому

      @@MilanKarakas you could also use the internal RTC which will give you much better timing characteristics.

  • @craigkinney853
    @craigkinney853 4 роки тому

    can i get some help please? have been tryingto get this to work but cannot get the timer to increment the MsTick and i'm now getting fustrated.my code is as below. i've checked thqat everything works up until the msTick which seems to get stuck in the while loop.the rest of the code to make an LED blink is on an .h file and i know this works as i've tested that. this has got to be something simple i've done.
    thanks in advnace if anyone can help.
    int msTicks = 0;
    void TIM4_IRQhandler(void);
    void allOn(void);
    void delay(void);
    void allOff(void);
    void dms(int ms);
    void setUp(void);
    int main()
    {
    RCC->AHB1ENR|=(1SR &= ~TIM_SR_UIF;
    };
    below is the delay function that is in the .h file
    RCC->APB1ENR|=(1ARR = 8;
    TIM4->CR1|= TIM_CR1_URS;
    TIM4->DIER|= TIM_DIER_UIE;
    TIM4->EGR|= TIM_EGR_UG;
    NVIC_EnableIRQ(TIM4_IRQn);

    • @EdwinFairchild
      @EdwinFairchild  4 роки тому

      you have a bit to learn, you do not call IRQ handler functions like you do in your while loop. Those functions are called all on their own when the interrupt occurs.

    • @craigkinney853
      @craigkinney853 4 роки тому

      also i'm using the STM 32 f401 nucleo board the above RCC have been changed to RCC->AHB1ENR|=(1

    • @EdwinFairchild
      @EdwinFairchild  4 роки тому

      if youre down later we can chat and i can help.

    • @craigkinney853
      @craigkinney853 4 роки тому

      @@EdwinFairchild hi Eddie. Still struggling through learning this. I was trying to follow the video to create the custom delay. Can you explain what you mean in your reply? Sorry for any hassle if you are at work and stuff. It's nighttime here in the UK.

    • @EdwinFairchild
      @EdwinFairchild  4 роки тому

      Email me you main.c file with all functions delay etc...Amaya.6987@gmail.com I'll look at it later

  • @emmetray9703
    @emmetray9703 4 роки тому

    explanation of "why you are using144 for ARR register value".
    www.keil.com/support/docs/3928.htm

  • @randypeeters3931
    @randypeeters3931 5 років тому

    My delay doesn't work

    • @EdwinFairchild
      @EdwinFairchild  5 років тому

      Sucks. Keep trying

    • @randypeeters3931
      @randypeeters3931 5 років тому +1

      Yesss. By the way your video's are good.

    • @EdwinFairchild
      @EdwinFairchild  5 років тому +1

      @@randypeeters3931 let me know how it goes or if you have a specific question

    • @randypeeters3931
      @randypeeters3931 5 років тому

      Yess thank you i will try it again

    • @randypeeters3931
      @randypeeters3931 5 років тому

      @@EdwinFairchild I can't find the problem in my code, i used 100% the same code and it does still not work.