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
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
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.
@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.
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.
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?
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 ;-)
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 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.
@@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...
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?
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.
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. :)
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.
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).
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.
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
@@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.
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?
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); }
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?
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);
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
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
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 🙏😁
@@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
@@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
@@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
@@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.
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.
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
@@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?
@@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.
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);
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.
@@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.
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
Best tutorial ever found for stm32!
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
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.
@Kaiden Arian instablaster ;)
@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.
@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!
@Kaiden Arian No problem xD
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.
Good catch! Thanks!!!!
That worked !!!
Thanks.
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?
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 ;-)
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?
@@MilanKarakas I think it's the DB7 Busy Flag pin you are referring to.
Good idea to check into..
@@Synthetech Yes, probably that one. I should to check datasheet for exact name and which state is buy and which ready.
@@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.
@@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...
I would like to see a video on the one shot timer out of the STM32F1xx.
thanks, you are more useful than my master degree
Jesus f**k it’s frustrating. We are paying big $$$ and received no help or little help. Like wtf....😤
The global variable updated in interrupt handler may require to be declared volatile other under certain compiler optimization will have issues
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?
Ariel Campos sure
Great tutorial thanks so much!
You're welcome
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.
Only one way to find out...give it a shot
Hello sir, do you know how a timer can be programmed as delay in the ARDUINO IDE using STM32xxx?
Thank you .it was really useful
Thanks Man ! Could you do a video for Input capture mode
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. :)
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.
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).
yes plausible but unless you need serious "real time" its a lot of effort for what should be an otherwise simple task
Did you figre out why it gives us 1 second delay with 144 ARR register value?
@@paatazarnadze7673 ქვემოთ ლინკი დავდე . მაგის მიხედვით ვქენი და ეხლა ორმაგად აღარ შვება.
@@paatazarnadze7673 ფბზე ვერ გიპოვე და ესაა ლინკი.
www.keil.com/support/docs/3928.htm
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.
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
@@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.
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?
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);
}
and check this tutorial www.carminenoviello.com/2015/09/04/precisely-measure-microseconds-stm32/
@@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.
@@jericotaleon I am from Honduras
This video was very useful but How to add delay in STM32 without using any interrupts in the TIM4?
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?
Can you please share me the code because is am starting working on it and I have less knowledge of programing
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);
}
}
sir
please can you help me for creating really long delays like 100 hours and more
and call interrupts in between
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
thank you
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
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 🙏😁
@@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
@@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
@@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
@@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.
My program runs ok in debug mode but not in run mode. Why?
Interesting, send me the code. eddie@edwinfairchild.com
Thank you for your video, if we use systick_config(systemcoreclock / 1000000) we can generate microsecond delay
No, you have to account for the time it takes to excited instructions time it takes to enter and exit a function etc..
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.
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
@@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?
@@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.
@@MilanKarakas you could also use the internal RTC which will give you much better timing characteristics.
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);
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.
also i'm using the STM 32 f401 nucleo board the above RCC have been changed to RCC->AHB1ENR|=(1
if youre down later we can chat and i can help.
@@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.
Email me you main.c file with all functions delay etc...Amaya.6987@gmail.com I'll look at it later
explanation of "why you are using144 for ARR register value".
www.keil.com/support/docs/3928.htm
My delay doesn't work
Sucks. Keep trying
Yesss. By the way your video's are good.
@@randypeeters3931 let me know how it goes or if you have a specific question
Yess thank you i will try it again
@@EdwinFairchild I can't find the problem in my code, i used 100% the same code and it does still not work.