【华大测评】+华大HC32F460开发板之systick延时函数
最近经过各种国产MCU的摧残,一开始我还觉得代码风格不是很好的华大460开发板代码,在我眼里又好了起来。之前时间在调试HC32L130,用了之后我对华大的MCU开始有了好的印象。最近又有点空了,决定再全面整下F460。
老规矩,先看第一个DEMO,gpio输出控制LED的例程。在看到F460给出例程的us级别的延时函数:
void Ddl_Delay1us(uint32_t u32Cnt)
{
uint32_t u32Cyc = 1ul;
volatile uint32_t i = 0ul;
if(SystemCoreClock > 10000000ul)
{
u32Cyc = SystemCoreClock / 10000000ul;
while(u32Cnt-- > 0ul)
{
i = u32Cyc;
while (i-- > 0ul)
{
;
}
}
}
else
{
while(u32Cnt-- > 0ul)
{
;
}
}
}
这样只是大概的软件延时。如果仅仅做个大概调试,那没问题,但我觉得官方还是应该给出精确
时间的延时。毕竟是官方么,应该要更权威要更谨慎些。
为啥不直接读systick的值来做延时呢?查了下华大HC460的数据手册和参考手册,对systick都无详细的讲解,真是奇怪,难道这个定时器
不入华大的眼,直接几乎给忽略了,给的例程里面也没有。
systick定时器还是挺重要的,可以做OS系统的心跳节拍,也可以作为延时的定时器。下面用systick
做延时:
为了不和模拟的延时冲突,新建delay.h和delay.c。
具体函数如下:
我查了下,虽然华大的HC460相关DEMO没提到systick,但是它也是基于CM4内核的,在core_cm4.h的
面有该寄存器的定义和应该配置应用函数。
寄存器定义:
相关配置函数:
下面我们参照修改下:
初始化函数,配置1ms中断一次,留在这功能将来移植OS可能要用到:
目前中断函数里面不写。
void delay_init(void)
{
SysTick->LOAD = (uint32_t)(SystemCoreClock/1000); /* set reload register 1KHz */
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
}
//us延时
void delay_us(uint32_t u32Cnt)
{
uint32_t ticks;
uint32_t told,tnow,tcnt=0;
uint32_t reload=SysTick->LOAD; //sysTick load 1ms中断
ticks=u32Cnt*(SystemCoreClock/1000000);//转换成1us基本单位的节拍
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;
}
}
}
//ms延时
void delay_ms(uint32_t u32Cnt)
{
uint32_t ticks;
uint32_t told,tnow,tcnt=0;
uint32_t reload=SysTick->LOAD; //sysTick load 1ms中断
ticks=u32Cnt*(SystemCoreClock/1000);//转换成1ms基本单位的节拍
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;
}
}
}
在main函数的while循环里面检测10us,LED0引脚反转一次,截取示波器波形:
systick延时的抓起图片:
软件延时抓取的延时:
显然systick定时器更胜一筹。
再用串口助手简易测试下时间间隔:
测试程序:
printf("Begin。。。\r\n");
LED0_TOGGLE();
Ddl_Delay1ms(300);
//delay_ms(300);
LED1_TOGGLE();
Ddl_Delay1ms(300);
//delay_ms(300);
LED2_TOGGLE();
Ddl_Delay1ms(300);
//delay_ms(300);
LED3_TOGGLE();
Ddl_Delay1ms(300);
//delay_ms(300);
/* de-init if necessary */
//PORT_DeInit();
printf("End。。。\r\n");
用systick的延时函数delay_ms做延时:
能看出2次之间间隔几乎就是1.2ms
用软件延时Ddl_Delay1ms做延时:
能看出2次之间间隔几乎就是1.8ms
当然也可能是我自己把频率调到168M的缘故,导致SystemCoreClock / 10000000ul的商
为16.8,结果可能进位还是啥的。这里列出仅仅是参考对应,要求不严格,2种都可用。
PS:
可能是我自己没找到HC32F460关于systick的说明。
如果谁有麻烦上传一份。
好了,今天就到这。