May 20, 2015

STM ARM Cortex-M3 CMSIS Delay


Every time we start working with a microcontroller, we try to find how generate a delay time, because the delay function is extreme necessary, it can be used to generate a square signal through a GPIO pin (for a buzzer/alarm), simply blink a led for a period of time or even a PWM signal. Here you can see how to use a delay function provided by the CMSIS core library, using the SysTick timer with the Keil uVision IDE.

As seen on "STM ARM Cortex-M3 Clock", each clock cycle is 13,88 ns. Great, but how can I generate a delay of  for example, 100 ms ? We need process something for 7204611 (100 / 0,00001388) clock cycles ? for a software solution yes, or use one of the hardware Timers. But isn't a waste use a whole Timer just to generate a delay function? yes, indeed! but the ARM has a "special" kind of timer called "SysTick", as we can see from the datasheet:

This timer is dedicated for OS, but could alsobe used as a standard downcounter. It
features:
  • A 24-bit downcounter
  • Autoreload capability
  • Maskable system interrupt generation when the counter reaches 0
  • Programmable clock source
It's used just by OS, like the FreeRTOS, and if you aren't using any, it's available! As we know, 7204611 clock cycles is needed to generate a 100 ms delay, can the SysTick timer support this value? as it's a 24 bit downcounter timer, yes it can, and values even higher, look 2^24 = 16777216 > 7204611. 

But what if I want something out of this range, like 1 second? now it can't store the value, but if you recall the function until reaches the desired time or use some kind of prescaler with it, then you can. Luckily this is exactly what the CMSIS core library provide us, look:

volatile uint32_t msTicks;

void SysTick_Handler (void) //Enter here every 1 ms
{
  msTicks++;
}

//-------------------------------
void Delay(uint32_t dlyTicks)
{
  uint32_t curTicks;

  curTicks = msTicks;
  while ((msTicks - curTicks) < dlyTicks);
}

//-------------------------------
int main()
{ 
 SystemInit();

 SysTick_Config(SystemCoreClock/1000); // 'prescaler' of SysTick for 1 ms
 
 while(10)
 {
  Delay(100); 
 }
 
}

The video below show a test with the code above as base:



About the versions:
  • Keil uVision 5.11.1.0
  • ARM Cortex-M3 STM32F103C8T6
Download

0 comentários :

Post a Comment