开发环境
我目前是在如下开发环境下操作的,
软件
- iar for arm开发工具
- STM32F0xx_StdPeriph_Lib_V1.5.0库
硬件
- STM32F030F4P6最小系统板
- ST Link V2调试工具
- TTL转USB串口工具
创建iar for arm工程
拷贝库文件到工程
把STM32F0xx_StdPeriph_Lib_V1.5.0
库中Libraries
放到工程目录中。同时拷贝库中Projects\STM32F0xx_StdPeriph_Templates
路径下以下三个文件到工程目录中
stm32f0xx_conf.h
stm32f0xx_it.c
stm32f0xx_it.h
system_stm32f0xx.c
工程options...
配置
C++ Compiler -> Preprocessor -> Additional include directiries:(one per line)
配置如下,要注意的是CMSIS库头文件搜索路径设置为iar安装路径中最新的头文件,这是因为 iar 版本升级后,使用STM32F0xx_StdPeriph_Lib_V1.5.0
中CMSIS老的库头文件编译会出错。
$PROJ_DIR$\
$TOOLKIT_DIR$\CMSIS\Include
$PROJ_DIR$\..\..\Libraries\CMSIS\Device\ST\STM32F0xx\Include
$PROJ_DIR$\..\..\Libraries\STM32F0xx_StdPeriph_Driver\inc
C++ Compiler -> Preprocessor -> Defined symbols:(one per line)
添加如下宏定义
USE_STDPERIPH_DRIVER
STM32F030
Debugger -> Setup -> Driver
中,选择ST-LINK
,
Debugger -> Setup -> Download
中,复选框,选中Verify download
以及Use flash loader(s)
组织工程文件
在工程中添加system_stm32f0xx.c
,startup_stm32f030.s
文件,在main.c
文件中,添加#include "stm32f0xx_conf.h"
,如下图所示,
工程创建完毕。
工程中如果需要使用某个驱动库,直接添加进图示STM32F0xx_StdPeriph_Driver
组中,
如果需要使用到中断添加stm32f0xx_it.c
到工程中即可。
接下来才正式进入主题。这里会从时钟管理,接口技术一步步建立库使用例程。在实际开发中,只需要拷贝+修改就可以快速完成功能模块开发。
STM32F0——时钟管理
概述
这一部分主要是配置系统时钟(CPU主频)及各总线时钟,包括了AHB,APB,IIC,USART,RTC等。在工程组织文件system_stm32f0xx.c
中提供了1个变量3个函数,如下所示
SystemCoreClock变量为系统时钟(CPU主频),单位Hz
void SystemInit(void)函数
static void SetSysClock(void)函数
void SystemCoreClockUpdate(void)函数
在启动文件startup_stm32f030.s
中,程序在进入main
函数之前调用SystemInit(void)
函数,对时钟进行配置,SystemInit(void)
函数首先复位各时钟寄存器,然后调用SetSysClock(void)
函数对时钟进行配置。
而在用户app中,如果重新初始化配置了系统时钟,配置完成后,可以运行一次SystemCoreClockUpdate(void)
函数,它会更新SystemCoreClock
变量,用户可以获取该变量的值确定当前系统时钟。毕竟,该值是有用的,可以依据此配置sys定时器,通信接口速率等。
代码实操
时钟配置代码只需在SetSysClock(void)
函数修改即可定制以适应各种需求。见STM32F0寄存器配置参考文件90页clock配置图。芯片默认CPU主频(SYSCLK)时钟源为HSI(高速内部时钟8MHz),本例中,外部时钟(HSE)晶振8MHz,
- 配置HCLK,PCLK=CPU主频
- 配置PLL输入,选择外部时钟HSE(分频为1)作为PLL时钟源,8MHz
- 配置PLL输出,6倍频,PLL输出48MHz
- 配置CPU主频时钟源为PLL时钟:48MHz
static void SetSysClock(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK configuration ----------------------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)//HSERDY: HSE 时钟就绪标志 1: HSE 振荡器就绪
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer and set Flash Latency */
FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;//位 7:4 HPRE: HCLK 预分频(HCLK prescaler)
/* PCLK = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;//位 10:8 PPRE: PCLK 预分频(PCLK prescaler)
/* PLL configuration = HSE * 6 = 48 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
//位 16 PLLSRC: PLL 输入时钟源 1:HSE/PREDIV 作为PLL 输入时钟
//位 17 PLLXTPRE: HSE 分频器作为PLL 输入 0: HSE 不分频
//位 21:18 PLLMUL: PLL 倍频系数 0100: PLL 输入时钟的6 倍频
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL6);
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}