STM32F103C8T6 - To get started with this ARM board, refer this post
In STM32F103C8T6 only 4 Timers are available, refer datasheet for more details
For creating delay, let use a general purpose - Timer 2. But before configuring the timer lets set the system clock source to get a desired peripheral clock frequency by configuring RCC registers.
Below diagram shows the whole clock picture:
After reset, HSI will be selected as the system clock by default. To change it configure RCC registers.
Note: If Keil startup code is used, it will change the system clock to HSE and frequency to 72 MHz
in SystemInit(). To set your own clock, disable the following:
RCC settings to set SysClk = HSE (8 MHz) :
1. PLLXTPRE = 0 -- HSE clock not divided (default value)
2. PLLSRC = 1 -- HSE oscillator clock selected as PLL input clock
3. PLLMUL -- 0x0111 (PLL * 9)
4. PPRE1 -- 0x100 (APB1 Prescaler / 2), because APB1 max should be 36 MHz
4. SW = 0x2 -- PLL selected as system clock after multiplication
SysClk = 8 * 9 = 72 MHz
Then, AHB Prescaler is 0 by default and if APB1 clock is divided, the clock for timer will be multiplied by 2, making Timer 2 clock frequency = 72 MHz
Below is the final RCC register values observed in STM32Cube programmer:
Timer settings:
1. Enable timer clock
2. Disable timer before setting prescaler and auto-reload value
SysClk = 72 MHz
Prescaler = 10000
Timer frequency = SysClk / Prescaler = 72000000 / 10000 = 7200 Hz
Can make delay from 0.14 ms to 9.1 sec (0 to 65535) with auto-reload value
Auto_reloader = 7200
so, Timer counts till: 1 / f(timer) * Auto_reload = 1 / 7200 * 7200 = 1 sec delay
Auto_reload = required time * (SysClk / Prescaler)
Note: Look into Keil website for correct header file (stm32f10x.h) to include for your board (STM32F103C8T6)
For a basic LED blinking program, refer this post
Program in Keil: reference manual
#include "stm32f10x.h"
void delay(float);
void RCC_config(void);
#define sys_clk 72000000
#define pre_scale (10000 - 1)
void RCC_config() // RCC clock configuration
{
RCC -> CR |= RCC_CR_HSEON; // HSE ON
RCC -> CFGR |= (RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL9);
// Setting PLL - HSE * 9
RCC -> CFGR |= RCC_CFGR_SW_1; // SysClk = PLLCLK
RCC -> CR |= RCC_CR_PLLON;
// Turn ON PLL after above PLL configurations, making SysClk = HSE * 9 = 8 * 9 = 72 MHz
RCC -> CFGR |= RCC_CFGR_PPRE1_DIV2;
// APB1 = AHB / 2 = 72 / 2 = 36 MHz (max)
}
void delay(float i)
{
uint16_t reload = (uint16_t)((float)(sys_clk / pre_scale) * i);
TIM2 -> ARR = reload; // Auto reload value
TIM2 -> CNT = 0; // Counter initialized to 0
TIM2 -> CR1 |= TIM_CR1_CEN; // CEN = 1 - Counter enable
while(TIM2 -> CNT < reload);
TIM2 -> CR1 &= ~TIM_CR1_CEN; // CEN = 0 - Counter disable
}
int main()
{
RCC_config();
/* Timer 2 settings
TIM2 -> CR1 &= ~TIM_CR1_DIR - by default - UP counter */
RCC -> APB1ENR |= RCC_APB1ENR_TIM2EN; // Enable clock for Timer 2
TIM2 -> CR1 &= ~TIM_CR1_CEN; // CEN = 0 - Counter disable
TIM2 -> PSC = (10000 - 1); // Prescaler
/* Port C - pin 13 settings for LED*/
RCC -> APB2ENR |= RCC_APB2ENR_IOPCEN; // Enable PortC Clock
/* Select PortC_Pin 13 as output @2MHZ
* Configure Pin 13 with open-drain */
GPIOC -> CRH |= GPIO_CRH_MODE13_1 | GPIO_CRH_CNF13_0;
GPIOC -> BSRR = GPIO_BSRR_BS13; // Initialize PC13 LED - OFF
while(1)
{
GPIOC -> BSRR = GPIO_BSRR_BR13; // PC13 LED - ON
delay(1); // in sec (can give values from 0.14 ms to 9.1 sec)
GPIOC -> BSRR = GPIO_BSRR_BS13;
delay(1);
}
return 0;
}
Comments
Post a Comment