在这个
论坛上用原子的
开发板也学习了许多,谢谢大家!
以下更改,如果有更好的实现方法,请指正!
更改的目的是为了将sys
tick计数器用于中断定时,作为一个系统时间,开机后不停运行,
将来可以作为一个多任务的时间节拍使用!
//Delay.c
//使用芯片的 SysTick 部件进行软件延时的操作
//
#include "delay.h"
#include "sys.h"
vu32 system_time =0u; //系统时间计数器,单位和节拍重装寄存器的设置值有关
static vu16 systick_reload_val; //系统节拍重装值
static vu16 systick_cnt_of_1us; //1us时间内的systick的计数值
//初始化延迟函数
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟(MHz)
void delay_init(u8 SYSCLK)
{
SysTick->CTRL = SysTick_Counter_Clear; //清除(停止)
SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; //选择外部时钟(bit2=0 HCLK/8)
systick_reload_val= (u16)((SYSCLK *CONST_SYSTICK_NUM_OF_US) >>3); //节拍定时 CONST_SYSTICK_NUM_OF_US(us)
SysTick->CTRL |= BIT(SYSTICK_CTRL_BIT_TICKINT); //使能中断
SysTick->LOAD = systick_reload_val;
SysTick->VAL = 0x00; //清空计数器
MY_NVIC_Init(CONST_NVIC_PP_SYSTEM_TASK, CONST_NVIC_SP_MID_MAX, WWDG_IRQChannel); //属于系统级中断,高于一般的应用中断优先级
SysTick->CTRL |= SysTick_Counter_Enable; //开始计数(倒数)
systick_cnt_of_1us =(SYSCLK >>3); //1us时间内的systick的计数值
system_time =0u;
}
//Systick 中断函数
void SysTick_Handler(void)
{
system_time ++;
//???
//这里增加任务切换
}
//得到系统时间,单位:1/8ms
u32 get_system_time(void)
{
return system_time;
}
//得到和指定时间thetime的差值,单位:1/8ms
u32 get_system_time_difference(u32 thetime)
{ //无符号数据减法, 0x0000 0001 - 0xffff fffa =0x0000 0007, 不会异常!
return(system_time -thetime);
}
//延时指定毫秒数时间
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*CONST_SYSTICK_NUM_OF_US/SYSCLK*1000
void delay_xms(u32 Xms)
{
u32 start;
start =system_time;
Xms <<= 3; //系统时间单位是1/8ms
while(get_system_time_difference(start)
}
//为了兼容开发板的程序
void delay_xus(u32 Xus)
{
u32 start_val;
u32 target_val;
u32 all_systick_cnt;
u16 systick_cnt;
if(Xus ==0) return;
all_systick_cnt =Xus *systick_cnt_of_1us;
start_val = SysTick->VAL; //得到当前计数器的值(!=0)
if(all_systick_cnt <=start_val)
{ //延时在剩余计数值内
target_val =start_val -(all_systick_cnt -1); //保证结束值非0![=0 进中断后重装,这里判不到==0的]
while((SysTick->VAL >target_val) && (SysTick->VAL <=start_val) );
}
else if(all_systick_cnt <=systick_reload_val)
{ //延时在剩余值之外,但是在一个节拍之内
target_val =start_val +(systick_reload_val -all_systick_cnt);
while(SysTick->VAL !=target_val);
}
else
{ //延时在一个节拍之外
systick_cnt =all_systick_cnt/systick_reload_val;
all_systick_cnt -= systick_cnt *systick_reload_val; //计数的余数,小于一个节拍
if(all_systick_cnt ==0)
{
do
{
if(SysTick->VAL ==start_val)
{
systick_cnt --;
while(SysTick->VAL ==start_val);
//因为在一个systick的计数值单位时间内,会多次执行while循环! 需要特殊处理!!【下同】
//离开的时候,已经不相等,则不要再 systick_cnt+1 了! 不能直接+1后再判断,因为可能瞬间不等而导致多计数一个节拍!
}
}while(systick_cnt !=0);
}
else if(all_systick_cnt <=start_val)
{
//延时余数在剩余计数值内
target_val =start_val -(all_systick_cnt -1); //保证结束值非0![=0 进中断后重装,这里判不到==0的]
if(target_val ==SysTick->VAL)
{
while(target_val ==SysTick->VAL);
//离开的时候,已经不相等,则不要再 systick_cnt+1 了!
}
else
{
systick_cnt++; //第一个判断点是延时的余数时间,节拍数要加1! 这里默认这里的语句操作时间小于一个systick的计数单位时间!
}
do
{
if(SysTick->VAL ==target_val)
{
systick_cnt --;
while(SysTick->VAL ==target_val);
//离开的时候,已经不相等,则不要再 systick_cnt+1 了!
}
}while(systick_cnt !=0);
}
else
{ //延时余数在剩余值之外
target_val = start_val + (systick_reload_val -all_systick_cnt);
do
{
if(SysTick->VAL ==target_val)
{
systick_cnt --;
while(SysTick->VAL ==target_val);
//离开的时候,已经不相等,则不要再 systick_cnt+1 了!
}
}while(systick_cnt !=0);
}
}
}
//End Of File
//Delay.h 文件
#ifndef _DELAY_H_
#define _DELAY_H_
#include <
STM32f10x_lib.h>
//常数的定义
#define CONST_SYSTICK_NUM_OF_US 125 //系统时间单位是1/8ms
#define CONST_SYSTICK_DELAY_MAX_MS (u32)( *CONST_SYSTICK_NUM_OF_US)
#define SYSTICK_CTRL_BIT_COUNTFLAG 16 //=1 倒计数为0发生过,读取时清除此位
#define SYSTICK_CTRL_BIT_CLKSOURCE 2 //=1 内核时钟
#define SYSTICK_CTRL_BIT_TICKINT 1 //=1 倒计数到0时挂起CPU(进入中断函数)
#define SYSTICK_CTRL_BIT_ENABLE 0 //=1 开始倒计数
extern vu32 system_time; //系统时间,单位:1/8ms
//函数的声明
extern void delay_init(u8 SYSCLK);
extern void delay_xms(u32 Xms);
extern void delay_xus(u32 Xus);
#endif
//End Of File
0