前言
事情是这样子的,自己用APM32E103CET6画了一个板子,然后白嫖正点原子APM32E103ZET6的程序搞点东西,中途发现延时函数貌似有一点点问题,然后顺便过来看一下是什么情况,后面发现问题还是蛮严重的,一个小小的delay.c文件里面有3个错误,只要有一个没有修好,延时功能都是错的。
重点来了,我是用标准库版本例程下面的,实验33 FreeRTOS移植实验,作为自己的工程框架,里面的延时函数功能跟其他小demo例程的写法是不一样的,后面会对比一下。
这里直接说结果:
- 延时函数初始化,时钟一定要当做8分频来用。
- us延时函数里面应该读取重载值的寄存器而不是计数值的寄存器。
- ms延时函数for循环里面应该用大于号。
😤除了第一点我还不是很明确之外,第二点和第三点是真的相当离谱。
延时函数功能初始化
先看一下问题代码。
void delay_init(uint16_t sysclk)
{
#if (SYS_SUPPORT_OS != 0)
uint32_t reload;
#endif
SysTick->CTRL = 0;
SysTick_ConfigCLKSource(SYSTICK_CLK_SOURCE_HCLK); /* 配置SysTick时钟源 */
g_fac_us = sysclk; /* 延时单位微秒需要的时钟节拍数 */
#if (SYS_SUPPORT_OS != 0)
/* 使用 configTICK_RATE_HZ 计算重装载值
* configTICK_RATE_HZ 在 FreeRTOSConfig.h 中定义
*/
reload = sysclk * (1000000 / configTICK_RATE_HZ);
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; /* 开启SysTick中断 */
SysTick->LOAD = reload - 1; /* 每1/delay_ostickspersec秒中断一次 */
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; /* 开启SysTick */
#endif
}
SysTick_ConfigCLKSource(SYSTICK_CLK_SOURCE_HCLK);
这个是APM32的库函数,配置M3内核里面的Systick时钟源,一般就是8分频或者不分频,但是我这边测试到的结果是,无论怎么选,都没有用,强制8分频,看一下手册的时钟树。
貌似没得选,不过具体内容其实不是看芯片的手册而是应该看M3内核的手册,这里我就不找了😏所以程序应该改成这样子。
手动给这两个变量赋值的时候8分频。
us延时
还是先看一下问题代码。
void delay_us(uint32_t nus)
{
uint32_t ticks;
uint32_t reload;
uint32_t told;
uint32_t tnow;
uint32_t tcnt = 0;
ticks = nus * g_fac_us; /* 计算需要延时的SysTick节拍数 */
reload = SysTick->VAL; /* 获取SysTick的重装载值 */
told = SysTick->VAL; /* 获取开始延时时的SysTick计数值 */
while (1)
{
tnow = SysTick->VAL;
if (tnow != told)
{
if (tnow < told)
{
tcnt += told - tnow; /* 需注意SysTick是一个递减计数器 */
}
else
{
tcnt += reload - tnow + told;
}
told = tnow;
if (tcnt >= ticks)
{
break;
}
}
}
}
就改一个地方,我也是服了,注释写的重装载值,怎么还填的计数值进去。
ms延时
void delay_ms(uint16_t nms)
{
uint32_t i;
for (i=0; i>nms; i++)
{
delay_us(1000);
}
}
修好us延时的时候测这个ms延时,每次都只有五六百us的延时,我传的参数进去貌似都没有生效,哎,还真的没有生效🤓谁这么缺德写成大于号的,相当于里面的delay_us(1000);
一次都没有执行到。
结束语
其他demo那些不带OS的延时函数,我测了一下是准的。甚至对比了一下,怎么文件还不一样的?
左边是那些小Demo带了OS宏才会开启调用的延时函数,我这个还没测,右边是移植FreeRTOS例程的文件,写法都不一样了,不过既然我已经发现了问题而且改好了就先这么用着吧,好像也没有必要改成左边的形式🥱
反正也是有一点点奇怪吧,网上没搜到类似的情况,延时函数不生效还有其他各种奇奇怪怪的现象。
关于白嫖
其实我已经买了一个APM32F407ZGT6的板子🤭不过我感觉不是很好用的样子,我最近一个小项目的需求,看了一下APM32E103CET6这一款应该也是可以的,正点原子刚好也有E103的教程,我顺便直接白嫖了😏没想到刚好出事了。
前面可能说得不够清楚,这里重申一下,我这边不会把所有工程测试一遍的,用之前自己写个IO翻转用逻辑分析仪看一下到底准不准,不然到后面,RTOS的工程里面调用这些延时函数,基本很难想到是这里的问题,我也只是提供其中一个参考的思路,正点原子的程序应该还有其他几个版本的,这种情况不一定适用。