10400 - Clock

2011.06.30

Clock

This is the heart-beat.

The clock is the reference timing for most parts of the microcontroller. The clock system can be quite complicated in some microcontrollers. A critical application requires the clocking system to be studied carefully to meet any serious application.

The clock system had improved over the years. It now provides various alternative and flexibilities. This, however, requires the correct set up before the rest of the program executes. In general the source of the clock, either from a crystal or a low-cost RC circuit etc, is to be chosen. Then usually a divider (or a PLL) may be chosen to give the required frequency.

In most applications, especially where a real time clock is needed, an accurate clock is required and this can only from a crystal oscillator. The frequency is usually some nice number such as 8 MHz or 16 MHz. Some special functions, such as the USB or internet, may require a frequency which may make programming the timer more difficult.

The correct set up of the clock system can be verified by using an oscilloscope. Where this is not available, it is then necessary to write a program to generate a suitable time interval, produced by a timer interrupt. That time interval can then be used to generate accurate 1-second intervals which can then be verified with a stop watch. Such a test is usually done when 8 LED’s connected to a port is available in the project prototype.

The clock system on the STM8S requires quite an effort to understand. However, by using the firmware library, most of the details can be left for future reading. Of course it is still important to verify the correctness of the timer operation by suitable time measurements. And this requires the use of interrupt.

The following code generates 1-second counting:

//  m36T4I24.c  Timer 4 Interrupt

#include "stm8s.h"
unsigned int msec ;
unsigned char Second ;

int main(void)
{
  CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE);
  GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_PP_LOW_SLOW);
  SPI_Init(SPI_FIRSTBIT_MSB, SPI_BAUDRATEPRESCALER_256, SPI_MODE_MASTER, SPI_CLOCKPOLARITY_LOW, SPI_CLOCKPHASE_1EDGE, SPI_DATADIRECTION_2LINES_FULLDUPLEX, SPI_NSS_SOFT, 0x07);
  SPI_Cmd(ENABLE);
 
  TIM4_TimeBaseInit(TIM4_PRESCALER_64, 249);
  TIM4_Cmd(ENABLE);
  TIM4_ClearFlag(TIM4_FLAG_UPDATE);
  TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
  msec = 0 ;
  Second = 0xF0 ;
  __enable_interrupt();

  while(1){;}               // Wait for interrupt

//  return 0;
}

#pragma vector = 25
__interrupt void Timer4_ISR(void)
{
  TIM4_ClearFlag(TIM4_FLAG_UPDATE);
  msec++ ;
  if(msec==1000){      // 1 second
    while(SPI_GetFlagStatus(SPI_FLAG_TXE)==0);
    SPI_SendData(Second);
    msec = 0 ;
    Second++;
  }
}