Evo jedan fin i poucan primer kako baratati "low-level" registrima unutar STM32F103, bez upotrebe perifernih biblioteka ili CubeMX, koristi se samo osnovni CMSIS koji obezbeduje definiciju svih registra i dodaje start_up code.
Primer samo brzo togluje LED na plocici (PC13), brzinom oko 17.5MHz i zanimljivo je to posmatrati preko osciloskopa gde se vidi da je baratanje portom maksimalnom brzinom od 36MHz i da je while() struktura dosta sporija (oko 4.5MHz) pa se vide "pauze".
Program sam pokrenuo preko Keil uVision 5, ali posto je potpuno nezavistan od drugih biblioteka lako ga je portovati na GCC okruzenje, to planiram u narednim danima, trebam napisati make/linker skriptu ...
Primer samo brzo togluje LED na plocici (PC13), brzinom oko 17.5MHz i zanimljivo je to posmatrati preko osciloskopa gde se vidi da je baratanje portom maksimalnom brzinom od 36MHz i da je while() struktura dosta sporija (oko 4.5MHz) pa se vide "pauze".
Program sam pokrenuo preko Keil uVision 5, ali posto je potpuno nezavistan od drugih biblioteka lako ga je portovati na GCC okruzenje, to planiram u narednim danima, trebam napisati make/linker skriptu ...
PHP Code:
/*
Bare minimum primer za blink LED za BluePill plocicu sa STM32F103C8
Koristi se samo osnovni CMSIS core bez dodatnih drajvera
Primer je pokrenut kroz Keil uVision 5
*/
#include "stm32f10x.h"
int main(void) {
//-------------------------------------------------------
//----------- Konfiguracija za Clock --------------------
//-------------------------------------------------------
//prilikom reseta default je interni RC oscilator, da bi radio sa externim
//kristalom mora da se enabluje HSE (High Speed External) u RCC (Reset and Clock Control)
RCC->CR |= RCC_CR_HSEON; //External High Speed clock enable
//posto treba vremena da se stabilizuje clock, cekamo RCC_CR_HSERDY flag
while (!(RCC->CR & RCC_CR_HSERDY )) {
; //cekaj tu
}
//aktiviramo PLL za HSE
RCC->CR |= RCC_CR_PLLON;
//postavljamo da je HSE izvor cloka za PLL
RCC->CFGR |= RCC_CFGR_PLLSRC_HSE;
//stavljamo x9 za PLL (8MHz * 9 = 72MHz) u registar RCC_CFGR
RCC->CFGR |= RCC_CFGR_PLLMULL9;
//cekamo PLL da se stabilizuje
while (!(RCC->CFGR & RCC_CIR_PLLRDYC )) {
; //cekaj tu
}
//za APB1 bus je prebrzo 72MHz, maksimum je 36MHz,
//ukljucujemo delitelj /2
RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
//-------------------------------------------------------
//----------- Konfiguracija za I/O port -----------------
//-------------------------------------------------------
//svaka periferija je po resetu iskljucena tako sto
//joj je iskljucen clock
//Da bi radila mora da se ukljuci
//ukljuci clock za sistemski bus AHB
//ovo je opciono, po default je ukljuceno za SRAM i FLASH memoriju
RCC->AHBENR |= RCC_AHBENR_SRAMEN;
RCC->AHBENR |= RCC_AHBENR_FLITFEN;
//ukljuci clock za APB2, on je za sve GPIOx
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; //GPIOA
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; //GPIOB
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; //GPIOC
//konfiguracija PC13
//po default svi pinovi su Input
//ima dva registra CRL za pinove 0-7 i CRH za pinove 8-15
//definisi ga kao general purpose Output push-pull, 50MHz
GPIOC->CRH &= ~GPIO_CRH_CNF13_0; //ocisti bit CNF13_0
GPIOC->CRH &= ~GPIO_CRH_CNF13_1; //ocisti bit CNF13_1
GPIOC->CRH |= GPIO_CRH_MODE13_0; //setuj bit MODE13_0
GPIOC->CRH |= GPIO_CRH_MODE13_1; //setuj bit MODE13_1
//atomic setovanje (BS) ili resotovanje (BR) pojedinacnog bita porta
GPIOC->BSRR=GPIO_BSRR_BR13; //0 = TURN LED ON
while(1) {
//tu se vrtimo ...
GPIOC->BSRR=GPIO_BSRR_BR13;
GPIOC->BSRR=GPIO_BSRR_BS13;
GPIOC->BSRR=GPIO_BSRR_BR13;
GPIOC->BSRR=GPIO_BSRR_BS13;
GPIOC->BSRR=GPIO_BSRR_BR13;
GPIOC->BSRR=GPIO_BSRR_BS13;
GPIOC->BSRR=GPIO_BSRR_BR13;
GPIOC->BSRR=GPIO_BSRR_BS13;
}
}