分享一个我常用的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;
}
纠正:几处相等应改成大于或等于,如 if((get_delay_cont() - delay_start) == 10000),应该改为if((get_delay_cont() - delay_start) >= 10000). 不错,不错。
肯分享就相当好!
有bug慢慢修改 贴中代码存在很多逻辑错误之处.本来打算早上自己把贴删了.结果删不了,误导大家了见谅. 感谢分享,非阻塞延时是好东西,代码错误可以编辑帖子修改的。 本帖最后由 zpwang 于 2024-9-1 17:49 编辑
感谢 jobszheng 和 万能的互联网 的理解和支持! 发贴代码BUG多误导人,凡事应有始有终,重新整理以将码打包重新发.开发环境使用的是VSCode+CMake,调试器是最廉价的DAP-LINK. 代码基于at32f423. 非阻塞延时精度较低,大多数场合应该是够用.
页:
[1]