在准备电赛时计划移植代码到MSP432P401R上,并用SysTick同时实现一个全局时钟、微秒延时delay_us和毫秒延时delay_us。
一开始计划通过配置微秒级的时钟周期来实现delay_us,但是很快发现这种方式很容易阻塞主程序,并且SysTick确实一般只用于毫秒计时器……因为我需要用到微秒延时的地方并不要求微秒延时特别精确(在线性CCD中发SI信号),因此我的方案是,先配一个精确的毫秒计时器,然后通过校正每微秒计算次数,来实现微秒延时。
最后发现效果还不错,相对比较精确,串口输出看看,跑了几分钟,一分钟误差差不多3毫秒,已经达到我需要的精度。
代码:SysTick.h
#ifndef SYSTICK_H #define SYSTICK_H #include "sysinit.h" void SysTick_Init(); void microsecond_check(); extern volatile uint32_t time_ms; void delay_ms(uint32_t time_ms); void delay_us(uint32_t time_us); #endif
SysTick.c
#include "systick.h" #include "usart.h" uint32_t fac_us; void SysTick_Handler(){ time_ms++; } void SysTick_Init(){ SysTick->LOAD=CS_getMCLK()/1000-1; SysTick->VAL=0; SysTick->CTRL=SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; microsecond_check(); } #define MICROCHECK_INTERVAL (100) void microsecond_check(){ fac_us=0; uint32_t final_time=time_ms+MICROCHECK_INTERVAL; while (time_ms<=final_time) fac_us++; fac_us=fac_us/MICROCHECK_INTERVAL/1000; printf("fac_us = %u\n",fac_us); } void delay_ms(uint32_t ms){ static uint32_t end_time; end_time=ms+time_ms; while (time_ms<end_time); } void delay_us(uint32_t time_us){ static int i; i=0; while (time_us>0){ for (i=0;i<fac_us;i++); time_us--; } }