zpwang 发表于 2023-12-25 22:54

分享一个我常用的at32定时延时程序

本帖最后由 zpwang 于 2023-12-26 20:10 编辑

#include "timer_delay.h"

/* **************************************************************            
函数功能: 通用定时器6初始化/定时中断,提供 systick 以外的定时延时

说明:               
      定时器没有使能定时中断,杜绝了非阻塞延时频繁的中断抢占CPU资源
      120MHz APB1时钟分频12分频后为定时器时钟10MHz
      定时没计数一次为0.1uS.以提高非阻塞us级定时响应速度而减少误差
      TMR6 为16位定时器,其最大计数值 0xFFFF      
*************************************************************** */
void Delay_tmr_init(void)
{
          crm_periph_clock_enable(CRM_TMR6_PERIPH_CLOCK, ENABLE);
         
          tmr_base_init(TMR6, 0xFFFF, 11);
          tmr_cnt_dir_set(TMR6, TMR_COUNT_UP);
         
         tmr_counter_enable(TMR6, ENABLE);
}

uint16_t get_delay_cont(void)
{
      return(tmr_counter_value_get(TMR6));
}

void tmr_delay_us(uint16_t xus)
{
      uin616_t delay_us = 0;      
      uint16_t delay_start= get_delay_cont();
      while(delay_us < xus)
      {
                if(get_delay_cont() > delay_start)
                {
                        delay_us = (get_delay_cont() - delay_start)/10;
                }
                else
                {
                        delay_us = (MAX_DEAY - delay_start + get_delay_cont())/10;
                }
      }
               
      return;
}

void tmr_delay_ms(uint16_t xms)            
{
      uint16_t delay_ms = 0;                        
      uint16_t delay_start= get_delay_cont();
      
      while(delay_ms < xms)
      {
                if(get_delay_cont() > delay_start)
                {
                        if((get_delay_cont() - delay_start) == 10000)
                        {
                              delay_ms ++;                               delay_start= get_delay_cont();
                        }
                }
                else
                {
                        if((MAX_DEAY - delay_start + get_delay_cont()) == 10000)
                        {
                              delay_ms ++;
                                 delay_start= get_delay_cont();
                        }
                }               
      }
}

void tmr_delay_s(uint16_t xs)            
{
      uint16_t delay_s = 0;                        
      uint16_t delay_start= get_delay_cont();
      
      while(delay_s < xs)
      {
                if(get_delay_cont() > delay_start)
                {
                        if((get_delay_cont() - delay_start) == 10000)
                        {
                              delay_ms ++;
                              delay_start= get_delay_cont();
                        }
                }
                else
                {
                        if((MAX_DEAY - delay_start + get_delay_cont()) == 10000)
                        {
                              delay_ms ++;
                              delay_start= get_delay_cont();
                        }
                }      
                if(delay_ms == 1000)
                {
                        delay_ms = 0;
                        delay_s ++;
                }      
      }
}

/* ******************************************************************************
//非阻塞型定时延时,以达到延时不独占CPU资源目的.
调用延时前需先调用起始函数初始化,再根据延时函数是否返回set判断定时到期.
******************************************************************************* */
uint16_t ub_delay_us = 0;

void ub_delay_us_start(void)
{
      ub_delay_us = 0;      
      delay_start= get_delay_cont();
}

FlagStatus ub_delay_us(uin16_t nus)
{
      if(ub_delay_us < xus)
      {
                if(get_delay_cont() > delay_start)
                {
                        ub_delay_us = (get_delay_cont() - delay_start)/10;
                }
                else
                {
                        ub_delay_us = (MAX_DEAY - delay_start + get_delay_cont())/10;
                }
      }
      else
      {
                return SET;
      }      
      
      return RESET;
}

uint16_t ub_delay_ms = 0;

void ub_delay_ms_start(void)
{
      ub_delay_ms = 0;      
      delay_start= get_delay_cont();
}

FlagStatus ub_delay_ms(uin16_t nms)
{
      if(ub_delay_ms < xms)
      {
                if(get_delay_cont() > delay_start)
                {
                        if((get_delay_cont() - delay_start) >= 10000)
                        {
                              ub_delay_ms ++;
                              delay_start= get_delay_cont();
                        }
                }
                else
                {
                        if((MAX_DEAY - delay_start + get_delay_cont()) >= 10000)
                        {
                              ub_delay_ms ++;
                              delay_start= get_delay_cont();
                        }
                }               
      }
      else
      {
                return SET;
      }      
      
      return RESET;
}

zpwang 发表于 2023-12-25 23:19

纠正:几处相等应改成大于或等于,如 if((get_delay_cont() - delay_start) == 10000),应该改为if((get_delay_cont() - delay_start) >= 10000).

jobszheng 发表于 2023-12-26 16:49

不错,不错。
肯分享就相当好!
有bug慢慢修改

zpwang 发表于 2023-12-26 19:46

贴中代码存在很多逻辑错误之处.本来打算早上自己把贴删了.结果删不了,误导大家了见谅.

万能的互联网 发表于 2023-12-26 23:12

感谢分享,非阻塞延时是好东西,代码错误可以编辑帖子修改的。

zpwang 发表于 2024-9-1 00:13

本帖最后由 zpwang 于 2024-9-1 17:49 编辑

感谢 jobszheng 和 万能的互联网 的理解和支持! 发贴代码BUG多误导人,凡事应有始有终,重新整理以将码打包重新发.开发环境使用的是VSCode+CMake,调试器是最廉价的DAP-LINK. 代码基于at32f423. 非阻塞延时精度较低,大多数场合应该是够用.







页: [1]
查看完整版本: 分享一个我常用的at32定时延时程序