为了兼容FreeRTOS,所以将延时函数统一规范,后续使用方便移植。此延时针对无晶振,示例为系统倍频64MHz,型号:STM32F103C8T6。
新建SYSTEM文件夹,新增两个文件,delay.c和delay.h
以下为delay.c内容:其中系统已倍频为64M
#include "stm32f10x.h"
double fac_us=0;
static RCC_ClocksTypeDef RCC_Clocks;
void delay_init()
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); //64M-->1us:64
RCC_GetClocksFreq(&RCC_Clocks);
fac_us=RCC_Clocks.SYSCLK_Frequency/1000000;//fac_us=64;
}
void delay_us(unsigned int nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD;
ticks=nus*fac_us;
tcnt=0;
told=SysTick->VAL;
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow;
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break;
}
};
}
void delay_ms(unsigned short nms)
{
delay_us((u32)(nms*1000));
}
以下为delay.h内容
#ifndef _DELAY_H_
#define _DELAY_H_
void delay_us(unsigned int nus);
void delay_ms(unsigned short nms);
void delay_init(void);
#endif
以下大体解释:
1.对于delay_init函数,SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);这句主要设置Systick时钟源,对于为什么不能8分频,主要是为了和FreeRTOS统一。
2.RTOS统一节拍为1ms,所以延时函数里没有额外增加RTOS支持,对于ms级延时,直接调用操作系统的系统延时。
对于无操作系统调用:
void main()
{
SystemClk_Init();//系统倍频64M
...
while(SysTick_Config(64000)!=0);//1ms中断
delay_init();
...
while(1)
{
...
}
}
其中SysTick_Config()函数,主要是设置装载值,设置Systick时钟为系统主时钟,开启systick中断。delay_init()函数再次设置了systick时钟源为主时钟源。
对于FreeRTOS系统调用:
void main()
{
SystemClk_Init();//系统倍频64M
...
//while(SysTick_Config(64000)!=0);//1ms中断,此处可不加
delay_init();
...
xTaskCreate(...);
vTaskStartScheduler();
}
测试:
针对FreeRTOS,分别建立两个任务,分别延时1S来翻转两个LED,其中任务一,用delay_us(1000000);任务二,用vTaskDelay(1000);测试结果正常,LED灯翻转时间相同。