历史上的今天
今天是:2024年09月30日(星期一)
2021年09月30日 | stm8s 定时器1 延时_STM8L1xx利用定时器实现毫秒和微妙延时
2021-09-30 来源:eefocus
采用单片机的定时计数器进行毫秒和微妙级延时,精度较准。检测溢出时产生的标志位来判断延时到达。下面以STM8L101芯片为例及配合代码说明。
一、实现原理:
1、初始化Timer2时钟源(附上相应代码)
void TIM2Init (void)
{
TIM2_DeInit ();
CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, ENABLE);
TIM2->CR1 &= ((uint8_t)(~TIM_CR1_CMS)) & ((uint8_t)(~TIM_CR1_DIR));
TIM2->CR1 |= ( (TIM2_CounterMode_Up) | (TIM_CR1_ARPE) ); /*counter up, enable Auto-Reload*/
TIM2_SetCounter(0x00);
TIM2->IER &= (~TIM2_IT_Update); /*disable timer2 interrupt*/
TIM2->CR1 &= (~TIM_CR1_CEN); /*disable timer2*/
}
打开外设时钟源;
选择向上计数模式和打开自动重加载功能;
填装计数器的初始值;
关闭Timer2中断功能;
关闭Timer2;
2、毫秒延时代码示例
void DelayMs (uint16_t timeVal)
{
uint16_t i = 0;
TIM2_TimeBaseInit(TIM2_Prescaler_64, TIM2_CounterMode_Up, 124); /*AutoReload Value = 124, 1ms*/
TIM2->CNTRH = (uint8_t)0; /*counter value = 0*/
TIM2->CNTRL = (uint8_t)0;
TIM2->CR1 |= (TIM_CR1_CEN); /*enable timner2*/
for(i = 0; i < timeVal; i++)
{
TIM2->SR1 &= (~TIM2_FLAG_Update); /*clear timer2 update flag*/
while( ((TIM2->SR1) & TIM2_FLAG_Update) != TIM2_FLAG_Update ); /**/
}
TIM2->CR1 &= (~TIM_CR1_CEN); /*disable timer2*/
}
设置Timer2分频,向上加1计数模式,填装自动重载寄存器目标值。这里每经过8us计数器加1,从0一直到124,共延时1ms,这时Timer2产生溢出标志位。通过检查寄存器TIM2->SR1的位[0]判断。
for(i = 0; i < timeVal; i++)
{
TIM2->SR1 &= (~TIM2_FLAG_Update); /*clear timer2 update flag*/
while( ((TIM2->SR1) & TIM2_FLAG_Update) != TIM2_FLAG_Update ); /**/
}
先软件清除TIM2->SR1位[0],再等待判断TIM2->SR1位[0]。这里加上for循环,表示延时多少毫秒。
关闭Timer2。
3、微妙延时代码示例
void DelayUs (uint16_t timeVal)
{
TIM2->PSCR = (uint8_t)(TIM2_Prescaler_8);
TIM2->CR1 |= (uint8_t)(TIM2_CounterMode_Up);
TIM2->EGR = TIM2_EventSource_Update;
TIM2->CNTRH = (uint8_t)0;
TIM2->CNTRL = (uint8_t)0;
TIM2->ARRH = (uint8_t)0xff;
TIM2->ARRL = (uint8_t)0xff;
TIM2->SR1 &= (~TIM2_FLAG_Update); /*clear timer update flag*/
TIM2->CR1 |= (TIM_CR1_CEN); /*enable timner*/
while(1)
{
if( (TIM2->CNTRH == (uint8_t)((timeVal - 1) >> 8)) &&
(TIM2->CNTRL == ((uint8_t)(timeVal - 1) & 0x00ff)) )
{
break;
}
}
TIM2->CR1 &= (~TIM_CR1_CEN); /*disable timer*/
}
设置Timer2分频系数,向上加1计数模式,计数器初始值和自动重装载目标值。这里计数器每经过1us自动做加1计数。
清除溢出标志位,并打开Timer2;
while(1)
{
if( (TIM2->CNTRH == (uint8_t)((timeVal - 1) >> 8)) &&
(TIM2->CNTRL == ((uint8_t)(timeVal - 1) & 0x00ff)) )
{
break;
}
}
这里不是检测溢出标志位,而是检测计数器当前的计数值。比较是否等于预定设置值。
关闭Timer2。
史海拾趣
|
我正在做一个基于ATmega16单片机的直流调速系统 要用到PID控制 第一个问题是 怎么用ATmega16实现PID控制 第二个问题 怎么将PID的输出与PWM波的占空比联系起来… 查看全部问答> |
|
数字转模拟(D/A) 隔离转换器485/232转4-20MA 数字转模拟(D/A) 隔离转换器:ISO DAO系列 RS232/RS485信号转模拟信号 隔离D/A转换器 产品概述: ISO DAO系列产品实现主机RS-485/232接口信号隔离转换成标准模拟信号,用以控制远程设备。ISODA系列产品可应用在 RS-232/RS-4 ...… 查看全部问答> |
|
二个程序它们各有静态变量或静态区。它们的静态区和操作系统的静态区有什么不同? 二个程序它们各有静态变量或静态区。它们的静态区和操作系统的静态区(事件EVENT,互斥体Mutex存放的地方)有什么不同?… 查看全部问答> |
|
我使用evc开发一个应用程序,使用了timer,当timer里面没有任何人为添加的代码的时候,查看程序内存中正在使用的内存,没有变化。当我添加这样两行代码: CWnd* pWnd = GetDlgItem(IDC_COORD); ...… 查看全部问答> |
|
本人去年7月份左右买了友善之臂的micro2440sdk开发板,现在将其转让,并且我愿意回答bootloader以及wince驱动的问题,其余不懂的我也会给一些意见。开发板网址http://www.arm9.net/micro2440sdk.asp就是这 ...… 查看全部问答> |
|
求解答,工具是ccs2.2,读写flash空间和Clist问题 1.目前要把VC的程序刻录到板子上,请问原程序中用的是CList, c里面有替代的或差不多的吗?如果有,头文件是什么?刚接触这个,挺迷糊,刚 从一个辞职的同事上接手个半成品程序。 2. 请问怎么往板子里的flash空间写数据? typedef struct & ...… 查看全部问答> |
|
第一次碰见这种情况,shit是我生气打上的,但还是通过不了ELUOSI.C(25): error C244: \'shit\': can\'t initialize, bad type or classELUOSI.C(25): error C132: \'shit\': not in formal parameter list#include<reg52.h>#include\"anjian.h\ ...… 查看全部问答> |




