在stm32f10xx的启动文件中(startup_stm32f10x_xx.s),我们可以找到SystemInit
跳转之后在函数最下发有一个 SetSysClock();
再次跳转之后,选择对应的函数,默认为SetSysClockTo72(),因为定义了宏SYSCLK_FREQ_72MHz
再次跳转之后:
在此函数中,我们需要选择时钟源,stm32f10xx默认选择外部时钟(HSE)作为时钟源,如果没有外部时钟可以根据需求修改这里
时钟源选择(公司板子没有外部晶振,所以此截图中,我选择了RCC_CR_HSION作为时钟源)
设置片上外设的时钟:
AHB不分频,APB1进行2分频,APB2进行4分频
stm3部分时钟系统:
最后设置:
对高速内部时钟进行2分频,然后9倍频得到36MHZ的时钟,因此需要修改宏#define SYSCLK_FREQ_72MHz 36000000
以上即为对stm32时钟源的设置和选择
================================================================================
SYSTEM下的delay相关函数介绍:
函数SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8)例程中介绍是选择外部时钟,个人理解为选择时钟源进行8分频,并没有什么外部时钟,从时钟系统图中可以看出,我们有两种选择,可以进行8分频也可以不进行分频 。因此我们需要进行除以8000000来得到1us的时间需要多个计数,因为我设置了36MHZ,所以/8只是取模,因此delay时间也是不准确的,如果一定要准确的delay延时,可以将时钟倍频到8的整数倍,比如40MHZ,48MHZ,之前我倍频的只有9,所有只有36MHZ,倍频的倍数从时钟系统图可以看出最大也就16倍
如果你不想分频,可以如下做(不含系统):
void delay_init()
{
u32 reload;
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择外部时钟 HCLK
fac_us=SystemCoreClock/1000000; //不论是否使用OS,fac_us都需要使用
fac_ms=fac_us*1000;
//此时fac_us=36;fac_ms=36000;
//当使用delay_ms时,传入参数最大值为:0xFFFFFF/36000=466,如果需要更长延时,需要多次调用
//如果时钟频率更大,能传入的参数的值就更小
}
以上对delay_init的初始化中,都是不带系统的,所以delay时间都是直接使用SysTick,但是如果我们使用了系统的话,系统的时钟节拍也是用SysTick,那么就会导致SysTick错乱,所以在存在系统的时候,SysTick中计数器值前后两次相减的值最终大于等于我们传入的参数,即得到我们需要的延时时间,因此不对SysTick进行操作,SysTick不会错乱
其中这个几个函数意思大概如下:
#define configTICK_RATE_HZ (1000)
//fac_us:36 1us需要36个计数
//fac_ms:1
//reload:36000000/1000=36000,也就是1ms,下方开启SYSTICK中断,reload是36000
//所以SYSTICK是一直以1ms为单位无限的循环下去,同时1ms也是作为系统的时钟节拍
//systick中断服务函数,使用ucos时用到
//开启了SYSTICK中断,这个是中断函数,在xPortSysTickHandler函数中有xTaskIncrementTick
//系统的时钟节拍变量就是一直在这个函数中累加的
void SysTick_Handler(void)
{
if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
{
xPortSysTickHandler();
}
}
void delay_init()
{
u32 reload;
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择外部时钟 HCLK
fac_us=SystemCoreClock/1000000; //不论是否使用OS,fac_us都需要使用
reload=SystemCoreClock/1000000; //每秒钟的计数次数 单位为M
reload*=1000000/configTICK_RATE_HZ; //根据configTICK_RATE_HZ设定溢出时间
fac_ms=1000/configTICK_RATE_HZ; //代表OS可以延时的最少单位
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断
SysTick->LOAD=reload; //每1/configTICK_RATE_HZ秒中断一次
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
}
//当前这样设置,系统用1ms作为最小单位,也是时钟节拍这样运行
//如果我们修改了宏configTICK_RATE_HZ 100
//那么时钟节拍就变成了10ms,也是最小单位,因为进入SYSTICK中断变成了10ms才会产生
//那么在使用delay_ms(9)等小于10的参数的时候,就不会产生任务调度