APM32 | 正点原子 | 带OS的延时函数功能异常

前言

事情是这样子的,自己用APM32E103CET6画了一个板子,然后白嫖正点原子APM32E103ZET6的程序搞点东西,中途发现延时函数貌似有一点点问题,然后顺便过来看一下是什么情况,后面发现问题还是蛮严重的,一个小小的delay.c文件里面有3个错误,只要有一个没有修好,延时功能都是错的。
重点来了,我是用标准库版本例程下面的,实验33 FreeRTOS移植实验,作为自己的工程框架,里面的延时函数功能跟其他小demo例程的写法是不一样的,后面会对比一下。
这里直接说结果:

  1. 延时函数初始化,时钟一定要当做8分频来用。
  2. us延时函数里面应该读取重载值的寄存器而不是计数值的寄存器。
  3. 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的工程里面调用这些延时函数,基本很难想到是这里的问题,我也只是提供其中一个参考的思路,正点原子的程序应该还有其他几个版本的,这种情况不一定适用。

  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值