Items:
1 PC (Windows 7)
2 Internet access
3 ST-Link V2 US$ 2.57
4 STM32F103C8T6 Minimum System Development Board US$ 2.15
5 IDE (Keil MDK523)
6 Breadboard, connectors, LEDs, resistors etc
7 74HC164
8 LCD 1602
Setup:
Read STM32F103xx Reference Manual
Read STM32F103x8 Datasheet
Download The-Generic-STM32F103-Pinout-Diagram
Install IDE including the STM32F100 pack and the ST-Link V2 driver
Connect the STM32F103 to the ST-LinkV2
Plug the ST-LinkV2 to the PC
Programming:
Launch the IDE
Create a new uVision project with STM32F103C8 as the device,
and include the CMSIS CORE and the Device Startup.
In "Options for Target", use ST-Link Debugger with 'SW' setting.
Type in a program, name it main.c and add it to the project
Rebuild and (Click Start/Stop) Debug (Session)
(Click) Run and check that the STM32F103 behaves as in the program.
Approach:
IDE usage and downloading
Simple output
Interrupt
SPI output
Clock and timing
LCD 1602 next...
Notes on the Examples:
T10.c Just to test program compilation and downloading.
T11.c Turn on the LED on the board.
T15.c Blink the LED.
T16.c Brightness control, just for fun. Not useful.
T21.c Test interrupt programming.
T32.c SPI1 Output to 74HC164
T40.c Check clock source
T42.c Select HSI, 1-second interval
T43.c HSI with PLL --> 16 MHz
T44.c HSI with PLL --> 64 MHz
T46.c Select HSE (8-MHz)
T47.c HSE with PLL --> 72 MHz
Examples:
==========
// T10.c
int main(void){
while(1);
}
==========
// T11.c
#include <stm32f10x.h>
int main(void){
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN ;
GPIOC->CRH &= ~GPIO_CRH_MODE13 ; // Mask
GPIOC->CRH &= ~GPIO_CRH_CNF13 ; // Mask
GPIOC->CRH |= GPIO_CRH_MODE13_1 ; // 00 10 PushPull Output 2 MHz
GPIOC->ODR &= ~(1<<13) ; // Clear bit 13 LED on.
while(1){}
}
==========
// T15.c
#include <stm32f10x.h>
int main(void){
int i,j ;
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN ;
GPIOC->CRH &= ~GPIO_CRH_MODE13 ; // Mask
GPIOC->CRH &= ~GPIO_CRH_CNF13 ; // Mask
GPIOC->CRH |= GPIO_CRH_MODE13_1 ; // 00 10 PushPull Output 2 MHz
GPIOC->ODR &= ~(1<<13) ; // Clear bit 13 LED on.
while(1){
GPIOC->ODR &= ~(1<<13) ;
for(i=0;i<=1000;i++){for(j=0;j<=1000;j++);} // Software delay
GPIOC->ODR |= (1<<13) ;
for(i=0;i<=1000;i++){for(j=0;j<=1000;j++);} // Software delay
}
//while(1){}
}
==========
// T16.c
#include <stm32f10x.h>
int main(void){
int i,j ;
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN ;
GPIOC->CRH &= ~GPIO_CRH_MODE13 ; // Mask
GPIOC->CRH &= ~GPIO_CRH_CNF13 ; // Mask
GPIOC->CRH |= GPIO_CRH_MODE13_1 ; // 00 10 PushPull Output 2 MHz
GPIOC->ODR &= ~(1<<13) ; // Clear bit 13 LED on.
while(1){
for(j=10;j<4990;j++){
GPIOC->ODR &= ~(1<<13) ;
for(i=0;i<j;i++); // ON delay
GPIOC->ODR |= (1<<13) ;
for(i=0;i<(5000-j);i++); // Off delay
}
}
//while(1){}
}
==========
// T21.c
#include <stm32f10x.h>
int i ;
int main(void){
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN ;
GPIOC->CRH &= ~GPIO_CRH_MODE13 ; // Mask
GPIOC->CRH &= ~GPIO_CRH_CNF13 ; // Mask
GPIOC->CRH |= GPIO_CRH_MODE13_1 ; // 00 10 PushPull Output 2 MHz
GPIOC->ODR &= ~(1<<13) ; // Clear bit 13 LED on.
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN ;
TIM2->PSC = 999 ; // 1000
//TIM2->ARR = 999 ;
TIM2->CR1 |= TIM_CR1_CEN ; // Enable Timer
TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Flag
TIM2->DIER |= TIM_DIER_UIE ; // Enable Timer Interrupt
NVIC->ISER[0] |= 1<<TIM2_IRQn ;
i = 0 ;
while(1){} // Wait for interrupt
}
void TIM2_IRQHandler(void){
TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Flag
i++ ;
if(i<=4)GPIOC->ODR &= ~(1<<13) ;
else GPIOC->ODR |= (1<<13) ;
if(i>5) i = 0 ;
}
==========
// T32.c
#include <stm32f10x.h>
int main(void){
int i,j,k ;
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN ;
GPIOC->CRH &= ~GPIO_CRH_MODE13 ; // Mask
GPIOC->CRH &= ~GPIO_CRH_CNF13 ; // Mask
GPIOC->CRH |= GPIO_CRH_MODE13_1 ; // 00 10 PushPull Output 2 MHz
GPIOC->ODR &= ~(1<<13) ; // Clear bit 13 LED on.
// SPI1
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN ;
GPIOA->CRL &= ~GPIO_CRL_MODE5 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF5 ; // Mask
GPIOA->CRL |= GPIO_CRL_MODE5_1 ; // Output 2 MHz
GPIOA->CRL |= GPIO_CRL_CNF5_1 ; // Sck (Alt Ftn) Pushpull
GPIOA->CRL &= ~GPIO_CRL_MODE6 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF6 ; // Mask
// GPIOA->CRL // Input
// GPIOA->CRL // MISO float
GPIOA->CRL &= ~GPIO_CRL_MODE7 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF7 ; // Mask
GPIOA->CRL |= GPIO_CRL_MODE7_1 ; // Output 2 MHz
GPIOA->CRL |= GPIO_CRL_CNF7_1 ; // MOSI (Alt Ftn) Pushpull
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN ;
SPI1->CR1 |= SPI_CR1_BR ; // f/256
SPI1->CR1 &= ~SPI_CR1_DFF ; // 8-bit
SPI1->CR1 &= ~SPI_CR1_CPOL ; // POL=0
SPI1->CR1 &= ~SPI_CR1_CPHA ; // Rising edge
SPI1->CR1 &= ~SPI_CR1_LSBFIRST ; // MSB first
SPI1->CR1 |= SPI_CR1_SSM ; // SSM=1
SPI1->CR1 |= SPI_CR1_SSI; // SSI=1
SPI1->CR1 |= SPI_CR1_MSTR ; // Master
SPI1->CR1 |= SPI_CR1_SPE ; // Enable SPI
while((SPI1->SR&SPI_SR_TXE)==0); // Wait till transmitter empty
SPI1->DR = 0x53 ; // Just show something
k = 0 ;
while(1){
// for(i=0;i<=1000;i++){for(j=0;j<=10000;j++);} // Software delay
// while((SPI1->SR&SPI_SR_TXE)==0); // Wait till transmitter empty
// SPI1->DR = k ;
// k++ ;
}
}
==========
// T40.c Check clock source
#include <stm32f10x.h>
int i ;
int main(void){
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN ;
GPIOC->CRH &= ~GPIO_CRH_MODE13 ; // Mask
GPIOC->CRH &= ~GPIO_CRH_CNF13 ; // Mask
GPIOC->CRH |= GPIO_CRH_MODE13_1 ; // 00 10 PushPull Output 2 MHz
GPIOC->ODR &= ~(1<<13) ; // Clear bit 13 LED on.
// SPI1
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN ;
GPIOA->CRL &= ~GPIO_CRL_MODE5 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF5 ; // Mask
GPIOA->CRL |= GPIO_CRL_MODE5_1 ; // Output 2 MHz
GPIOA->CRL |= GPIO_CRL_CNF5_1 ; // Sck (Alt Ftn) Pushpull
GPIOA->CRL &= ~GPIO_CRL_MODE6 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF6 ; // Mask
// GPIOA->CRL // Input
// GPIOA->CRL // MISO float
GPIOA->CRL &= ~GPIO_CRL_MODE7 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF7 ; // Mask
GPIOA->CRL |= GPIO_CRL_MODE7_1 ; // Output 2 MHz
GPIOA->CRL |= GPIO_CRL_CNF7_1 ; // MOSI (Alt Ftn) Pushpull
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN ;
SPI1->CR1 |= SPI_CR1_BR ; // f/256
SPI1->CR1 &= ~SPI_CR1_DFF ; // 8-bit
SPI1->CR1 &= ~SPI_CR1_CPOL ; // POL=0
SPI1->CR1 &= ~SPI_CR1_CPHA ; // Rising edge
SPI1->CR1 &= ~SPI_CR1_LSBFIRST ; // MSB first
SPI1->CR1 |= SPI_CR1_SSM ; // SSM=1
SPI1->CR1 |= SPI_CR1_SSI; // SSI=1
SPI1->CR1 |= SPI_CR1_MSTR ; // Master
SPI1->CR1 |= SPI_CR1_SPE ; // Enable SPI
while((SPI1->SR&SPI_SR_TXE)==0); // Wait till transmitter empty
SPI1->DR = 0x53 ; // Just show something
i = RCC->CFGR ;
while((SPI1->SR&SPI_SR_TXE)==0); // Wait till transmitter empty
SPI1->DR = i&0xFF ;
while(1) ;
// Timer 2
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN ;
TIM2->PSC = 7999 ; // 8000 1 ms
TIM2->ARR = 999 ; // 1000 1 s
TIM2->CR1 |= TIM_CR1_CEN ; // Enable Timer
TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Flag
TIM2->DIER |= TIM_DIER_UIE ; // Enable Timer Interrupt
NVIC->ISER[0] |= 1<<TIM2_IRQn ;
i = 0 ;
while(1){} // Wait for interrupt
}
void TIM2_IRQHandler(void){
TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Flag
while((SPI1->SR&SPI_SR_TXE)==0); // Wait till transmitter empty
SPI1->DR = i ;
i++ ;
if(i==200) i = 0 ; // 0 to 199
}
==========
// T42.c HSI 8-MHz
#include <stm32f10x.h>
int i ;
int main(void){
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN ;
GPIOC->CRH &= ~GPIO_CRH_MODE13 ; // Mask
GPIOC->CRH &= ~GPIO_CRH_CNF13 ; // Mask
GPIOC->CRH |= GPIO_CRH_MODE13_1 ; // 00 10 PushPull Output 2 MHz
GPIOC->ODR &= ~(1<<13) ; // Clear bit 13 LED on.
// SPI1
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN ;
GPIOA->CRL &= ~GPIO_CRL_MODE5 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF5 ; // Mask
GPIOA->CRL |= GPIO_CRL_MODE5_1 ; // Output 2 MHz
GPIOA->CRL |= GPIO_CRL_CNF5_1 ; // Sck (Alt Ftn) Pushpull
GPIOA->CRL &= ~GPIO_CRL_MODE6 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF6 ; // Mask
// GPIOA->CRL // Input
// GPIOA->CRL // MISO float
GPIOA->CRL &= ~GPIO_CRL_MODE7 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF7 ; // Mask
GPIOA->CRL |= GPIO_CRL_MODE7_1 ; // Output 2 MHz
GPIOA->CRL |= GPIO_CRL_CNF7_1 ; // MOSI (Alt Ftn) Pushpull
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN ;
SPI1->CR1 |= SPI_CR1_BR ; // f/256
SPI1->CR1 &= ~SPI_CR1_DFF ; // 8-bit
SPI1->CR1 &= ~SPI_CR1_CPOL ; // POL=0
SPI1->CR1 &= ~SPI_CR1_CPHA ; // Rising edge
SPI1->CR1 &= ~SPI_CR1_LSBFIRST ; // MSB first
SPI1->CR1 |= SPI_CR1_SSM ; // SSM=1
SPI1->CR1 |= SPI_CR1_SSI; // SSI=1
SPI1->CR1 |= SPI_CR1_MSTR ; // Master
SPI1->CR1 |= SPI_CR1_SPE ; // Enable SPI
while((SPI1->SR&SPI_SR_TXE)==0); // Wait till transmitter empty
SPI1->DR = 0x53 ; // Just show something
RCC->CR |= RCC_CR_HSION ; // Turn on HSI
RCC->CFGR &= ~RCC_CFGR_SW ; // Mask
// Use HSI
while( (RCC->CR&RCC_CR_HSIRDY)==0 ); // Wait till HSI ready
while( (RCC->CFGR&RCC_CFGR_SWS)!=0 ); // Wait till HSI used
// Timer 2
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN ;
TIM2->PSC = 7999 ; // 8000 1 ms
TIM2->ARR = 999 ; // 1000 1 s
TIM2->CR1 |= TIM_CR1_CEN ; // Enable Timer
TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Flag
TIM2->DIER |= TIM_DIER_UIE ; // Enable Timer Interrupt
NVIC->ISER[0] |= 1<<TIM2_IRQn ;
i = 0 ;
while(1){} // Wait for interrupt
}
void TIM2_IRQHandler(void){
TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Flag
while((SPI1->SR&SPI_SR_TXE)==0); // Wait till transmitter empty
SPI1->DR = i ;
i++ ;
if(i==200) i = 0 ; // 0 to 199
}
==========
// T43.c HSI 8-MHz PLL x4
#include <stm32f10x.h>
int i ;
int main(void){
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN ;
GPIOC->CRH &= ~GPIO_CRH_MODE13 ; // Mask
GPIOC->CRH &= ~GPIO_CRH_CNF13 ; // Mask
GPIOC->CRH |= GPIO_CRH_MODE13_1 ; // 00 10 PushPull Output 2 MHz
GPIOC->ODR &= ~(1<<13) ; // Clear bit 13 LED on.
// SPI1
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN ;
GPIOA->CRL &= ~GPIO_CRL_MODE5 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF5 ; // Mask
GPIOA->CRL |= GPIO_CRL_MODE5_1 ; // Output 2 MHz
GPIOA->CRL |= GPIO_CRL_CNF5_1 ; // Sck (Alt Ftn) Pushpull
GPIOA->CRL &= ~GPIO_CRL_MODE6 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF6 ; // Mask
// GPIOA->CRL // Input
// GPIOA->CRL // MISO float
GPIOA->CRL &= ~GPIO_CRL_MODE7 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF7 ; // Mask
GPIOA->CRL |= GPIO_CRL_MODE7_1 ; // Output 2 MHz
GPIOA->CRL |= GPIO_CRL_CNF7_1 ; // MOSI (Alt Ftn) Pushpull
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN ;
SPI1->CR1 |= SPI_CR1_BR ; // f/256
SPI1->CR1 &= ~SPI_CR1_DFF ; // 8-bit
SPI1->CR1 &= ~SPI_CR1_CPOL ; // POL=0
SPI1->CR1 &= ~SPI_CR1_CPHA ; // Rising edge
SPI1->CR1 &= ~SPI_CR1_LSBFIRST ; // MSB first
SPI1->CR1 |= SPI_CR1_SSM ; // SSM=1
SPI1->CR1 |= SPI_CR1_SSI; // SSI=1
SPI1->CR1 |= SPI_CR1_MSTR ; // Master
SPI1->CR1 |= SPI_CR1_SPE ; // Enable SPI
while((SPI1->SR&SPI_SR_TXE)==0); // Wait till transmitter empty
SPI1->DR = 0x53 ; // Just show something
RCC->CR |= RCC_CR_HSION ; // Turn on HSI
while( (RCC->CR&RCC_CR_HSIRDY)==0 ); // Wait till HSI ready
RCC->CFGR &= ~RCC_CFGR_SW ; // Mask
// Use HSI
while( (RCC->CFGR&RCC_CFGR_SWS)!=0 ); // Wait till HSI used
RCC->CR &= ~RCC_CR_PLLON ; // Turn off PLL
RCC->CFGR &= ~RCC_CFGR_PLLMULL ; // Mask
RCC->CFGR |= RCC_CFGR_PLLMULL_1 ; // x4
RCC->CFGR &= ~RCC_CFGR_PLLSRC ; // Mask
// Use HSI /2
RCC->CR |= RCC_CR_PLLON ; // Turn on PLL
while( (RCC->CR&RCC_CR_PLLRDY)==0 ); // Wait till PLL ready
RCC->CFGR &= ~RCC_CFGR_SW ; // Mask
RCC->CFGR |= RCC_CFGR_SW_PLL ; // Use PLL
while( (RCC->CFGR&RCC_CFGR_SWS_PLL)==0 ); // Wait till PLL used
// Timer 2
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN ;
TIM2->PSC = 7999 ; // 8000 1 ms
TIM2->ARR = 999 ; // 1000 1 s
TIM2->CR1 |= TIM_CR1_CEN ; // Enable Timer
TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Flag
TIM2->DIER |= TIM_DIER_UIE ; // Enable Timer Interrupt
NVIC->ISER[0] |= 1<<TIM2_IRQn ;
i = 0 ;
while(1){} // Wait for interrupt
}
void TIM2_IRQHandler(void){
TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Flag
while((SPI1->SR&SPI_SR_TXE)==0); // Wait till transmitter empty
SPI1->DR = i ;
i++ ;
if(i==200) i = 0 ; // 0 to 199
}
==========
// T44.c HSI 8-MHz /2 PLL x16 64 MHz
#include <stm32f10x.h>
int i ;
int main(void){
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN ;
GPIOC->CRH &= ~GPIO_CRH_MODE13 ; // Mask
GPIOC->CRH &= ~GPIO_CRH_CNF13 ; // Mask
GPIOC->CRH |= GPIO_CRH_MODE13_1 ; // 00 10 PushPull Output 2 MHz
GPIOC->ODR &= ~(1<<13) ; // Clear bit 13 LED on.
// SPI1
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN ;
GPIOA->CRL &= ~GPIO_CRL_MODE5 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF5 ; // Mask
GPIOA->CRL |= GPIO_CRL_MODE5_1 ; // Output 2 MHz
GPIOA->CRL |= GPIO_CRL_CNF5_1 ; // Sck (Alt Ftn) Pushpull
GPIOA->CRL &= ~GPIO_CRL_MODE6 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF6 ; // Mask
// GPIOA->CRL // Input
// GPIOA->CRL // MISO float
GPIOA->CRL &= ~GPIO_CRL_MODE7 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF7 ; // Mask
GPIOA->CRL |= GPIO_CRL_MODE7_1 ; // Output 2 MHz
GPIOA->CRL |= GPIO_CRL_CNF7_1 ; // MOSI (Alt Ftn) Pushpull
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN ;
SPI1->CR1 |= SPI_CR1_BR ; // f/256
SPI1->CR1 &= ~SPI_CR1_DFF ; // 8-bit
SPI1->CR1 &= ~SPI_CR1_CPOL ; // POL=0
SPI1->CR1 &= ~SPI_CR1_CPHA ; // Rising edge
SPI1->CR1 &= ~SPI_CR1_LSBFIRST ; // MSB first
SPI1->CR1 |= SPI_CR1_SSM ; // SSM=1
SPI1->CR1 |= SPI_CR1_SSI; // SSI=1
SPI1->CR1 |= SPI_CR1_MSTR ; // Master
SPI1->CR1 |= SPI_CR1_SPE ; // Enable SPI
while((SPI1->SR&SPI_SR_TXE)==0); // Wait till transmitter empty
SPI1->DR = 0x53 ; // Just show something
RCC->CR |= RCC_CR_HSION ; // Turn on HSI
while( (RCC->CR&RCC_CR_HSIRDY)==0 ); // Wait till HSI ready
RCC->CFGR &= ~RCC_CFGR_SW ; // Mask
// Use HSI
while( (RCC->CFGR&RCC_CFGR_SWS)!=0 ); // Wait till HSI used
RCC->CR &= ~RCC_CR_PLLON ; // Turn off PLL
RCC->CFGR &= ~RCC_CFGR_PLLMULL ; // Mask
RCC->CFGR |= RCC_CFGR_PLLMULL ; // x16
RCC->CFGR &= ~RCC_CFGR_PLLSRC ; // Mask
// Use HSI /2
RCC->CR |= RCC_CR_PLLON ; // Turn on PLL
while( (RCC->CR&RCC_CR_PLLRDY)==0 ); // Wait till PLL ready
RCC->CFGR &= ~RCC_CFGR_SW ; // Mask
RCC->CFGR |= RCC_CFGR_SW_PLL ; // Use PLL
while( (RCC->CFGR&RCC_CFGR_SWS_PLL)==0 ); // Wait till PLL used
// Timer 2
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN ;
TIM2->PSC = 7999 ; // 64000000 / 8000 8 kHz
TIM2->ARR = 7999 ; // 8000 / 8000 1 s
TIM2->CR1 |= TIM_CR1_CEN ; // Enable Timer
TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Flag
TIM2->DIER |= TIM_DIER_UIE ; // Enable Timer Interrupt
NVIC->ISER[0] |= 1<<TIM2_IRQn ;
i = 0 ;
while(1){} // Wait for interrupt
}
void TIM2_IRQHandler(void){
TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Flag
while((SPI1->SR&SPI_SR_TXE)==0); // Wait till transmitter empty
SPI1->DR = i ;
i++ ;
if(i==200) i = 0 ; // 0 to 199
}
==========
// T46.c Select HSE
#include <stm32f10x.h>
int i ;
int main(void){
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN ;
GPIOC->CRH &= ~GPIO_CRH_MODE13 ; // Mask
GPIOC->CRH &= ~GPIO_CRH_CNF13 ; // Mask
GPIOC->CRH |= GPIO_CRH_MODE13_1 ; // 00 10 PushPull Output 2 MHz
GPIOC->ODR &= ~(1<<13) ; // Clear bit 13 LED on.
// SPI1
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN ;
GPIOA->CRL &= ~GPIO_CRL_MODE5 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF5 ; // Mask
GPIOA->CRL |= GPIO_CRL_MODE5_1 ; // Output 2 MHz
GPIOA->CRL |= GPIO_CRL_CNF5_1 ; // Sck (Alt Ftn) Pushpull
GPIOA->CRL &= ~GPIO_CRL_MODE6 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF6 ; // Mask
// GPIOA->CRL // Input
// GPIOA->CRL // MISO float
GPIOA->CRL &= ~GPIO_CRL_MODE7 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF7 ; // Mask
GPIOA->CRL |= GPIO_CRL_MODE7_1 ; // Output 2 MHz
GPIOA->CRL |= GPIO_CRL_CNF7_1 ; // MOSI (Alt Ftn) Pushpull
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN ;
SPI1->CR1 |= SPI_CR1_BR ; // f/256
SPI1->CR1 &= ~SPI_CR1_DFF ; // 8-bit
SPI1->CR1 &= ~SPI_CR1_CPOL ; // POL=0
SPI1->CR1 &= ~SPI_CR1_CPHA ; // Rising edge
SPI1->CR1 &= ~SPI_CR1_LSBFIRST ; // MSB first
SPI1->CR1 |= SPI_CR1_SSM ; // SSM=1
SPI1->CR1 |= SPI_CR1_SSI; // SSI=1
SPI1->CR1 |= SPI_CR1_MSTR ; // Master
SPI1->CR1 |= SPI_CR1_SPE ; // Enable SPI
while((SPI1->SR&SPI_SR_TXE)==0); // Wait till transmitter empty
SPI1->DR = 0x53 ; // Just show something
RCC->CR &= ~RCC_CR_HSEBYP ; // HSE not bypassed
RCC->CR |= RCC_CR_HSEON ; // Turn on HSE
while( (RCC->CR&RCC_CR_HSERDY)==0 ); // Wait till HSE ready
RCC->CFGR &= ~RCC_CFGR_SW ; // Mask
RCC->CFGR |= RCC_CFGR_SW_HSE ; // Use HSE
while( (RCC->CFGR&RCC_CFGR_SWS_HSE)!=RCC_CFGR_SWS_HSE ); // Wait till HSE used
// Timer 2
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN ;
TIM2->PSC = 7999 ; // 8000 1 ms
TIM2->ARR = 999 ; // 1000 1 s
TIM2->CR1 |= TIM_CR1_CEN ; // Enable Timer
TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Flag
TIM2->DIER |= TIM_DIER_UIE ; // Enable Timer Interrupt
NVIC->ISER[0] |= 1<<TIM2_IRQn ;
i = 0 ;
while(1){} // Wait for interrupt
}
void TIM2_IRQHandler(void){
TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Flag
while((SPI1->SR&SPI_SR_TXE)==0); // Wait till transmitter empty
SPI1->DR = i ;
i++ ;
if(i==200) i = 0 ; // 0 to 199
}
==========
// T47.c HSE with PLL x9 72 MHz
#include <stm32f10x.h>
int i ;
int main(void){
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN ;
GPIOC->CRH &= ~GPIO_CRH_MODE13 ; // Mask
GPIOC->CRH &= ~GPIO_CRH_CNF13 ; // Mask
GPIOC->CRH |= GPIO_CRH_MODE13_1 ; // 00 10 PushPull Output 2 MHz
GPIOC->ODR &= ~(1<<13) ; // Clear bit 13 LED on.
// SPI1
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN ;
GPIOA->CRL &= ~GPIO_CRL_MODE5 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF5 ; // Mask
GPIOA->CRL |= GPIO_CRL_MODE5_1 ; // Output 2 MHz
GPIOA->CRL |= GPIO_CRL_CNF5_1 ; // Sck (Alt Ftn) Pushpull
GPIOA->CRL &= ~GPIO_CRL_MODE6 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF6 ; // Mask
// GPIOA->CRL // Input
// GPIOA->CRL // MISO float
GPIOA->CRL &= ~GPIO_CRL_MODE7 ; // Mask
GPIOA->CRL &= ~GPIO_CRL_CNF7 ; // Mask
GPIOA->CRL |= GPIO_CRL_MODE7_1 ; // Output 2 MHz
GPIOA->CRL |= GPIO_CRL_CNF7_1 ; // MOSI (Alt Ftn) Pushpull
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN ;
SPI1->CR1 |= SPI_CR1_BR ; // f/256
SPI1->CR1 &= ~SPI_CR1_DFF ; // 8-bit
SPI1->CR1 &= ~SPI_CR1_CPOL ; // POL=0
SPI1->CR1 &= ~SPI_CR1_CPHA ; // Rising edge
SPI1->CR1 &= ~SPI_CR1_LSBFIRST ; // MSB first
SPI1->CR1 |= SPI_CR1_SSM ; // SSM=1
SPI1->CR1 |= SPI_CR1_SSI; // SSI=1
SPI1->CR1 |= SPI_CR1_MSTR ; // Master
SPI1->CR1 |= SPI_CR1_SPE ; // Enable SPI
while((SPI1->SR&SPI_SR_TXE)==0); // Wait till transmitter empty
SPI1->DR = 0x53 ; // Just show something
RCC->CR &= ~RCC_CR_HSEBYP ; // HSE not bypassed
RCC->CR |= RCC_CR_HSEON ; // Turn on HSE
while( (RCC->CR&RCC_CR_HSERDY)==0 ); // Wait till HSE ready
RCC->CFGR &= ~RCC_CFGR_SW ; // Mask
RCC->CFGR |= RCC_CFGR_SW_HSE ; // Use HSE
while( (RCC->CFGR&RCC_CFGR_SWS_HSE)!=RCC_CFGR_SWS_HSE ); // Wait till HSE used
RCC->CR &= ~RCC_CR_PLLON ; // Turn off PLL
RCC->CFGR &= ~RCC_CFGR_PLLMULL ; // Mask
RCC->CFGR |= RCC_CFGR_PLLMULL_2 ;
RCC->CFGR |= RCC_CFGR_PLLMULL_1 ;
RCC->CFGR |= RCC_CFGR_PLLMULL_0 ; // x9
RCC->CFGR &= ~RCC_CFGR_PLLXTPRE ; // HSE not /2
RCC->CFGR |= RCC_CFGR_PLLSRC ; // Use HSE
RCC->CR |= RCC_CR_PLLON ; // Turn on PLL
while( (RCC->CR&RCC_CR_PLLRDY)==0 ); // Wait till PLL ready
RCC->CFGR &= ~RCC_CFGR_SW ; // Mask
RCC->CFGR |= RCC_CFGR_SW_PLL ; // Use PLL
while( (RCC->CFGR&RCC_CFGR_SWS_PLL)==0 ); // Wait till PLL used
// Timer 2
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN ;
TIM2->PSC = 8999 ; // 72 MHz / 9k = 8k
TIM2->ARR = 7999 ; // 8k/8000 1 s
TIM2->CR1 |= TIM_CR1_CEN ; // Enable Timer
TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Flag
TIM2->DIER |= TIM_DIER_UIE ; // Enable Timer Interrupt
NVIC->ISER[0] |= 1<<TIM2_IRQn ;
i = 0 ;
while(1){} // Wait for interrupt
}
void TIM2_IRQHandler(void){
TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Flag
while((SPI1->SR&SPI_SR_TXE)==0); // Wait till transmitter empty
SPI1->DR = i ;
i++ ;
if(i==200) i = 0 ; // 0 to 199
}
==========
==========