STM32学习之普通定时器是否能定时1us?

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jiqimao1970/article/details/72834564

对于STM32F10x系列使用普通定时器能否能定时1us,笔者一直抱有怀疑态度。

于是笔者做了下述实验:

代码:

主函数:

int main(void)
{
SystemClock_Config();
LED_Init();//LED初始化
NVIC_Config();
Timer2_Config();
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
while(1)
{
}

}

GPIO设置

void LED_Init(void)
{
GPIO_InitTypeDef  GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE); //使能PB,PE时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;            //端口PC0配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //配置推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO速度50MHz
GPIO_Init(GPIOC, &GPIO_InitStructure);     //初始化GPIOC.0
GPIO_SetBits(GPIOC,GPIO_Pin_0);                      //PC.0输出高


GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;              //端口PD3配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //配置推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO速度50MHz
GPIO_Init(GPIOD, &GPIO_InitStructure);     //初始化GPIOD.3
GPIO_SetBits(GPIOD,GPIO_Pin_3);                      //PD.3输出高

}

NVIC设置:

void NVIC_Config(void)  
{  
NVIC_InitTypeDef NVIC_InitStructure;  

//选择中断分组0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);  


//选择TIM2的中断通道  
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;       

//抢占式中断优先级设置为0  
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  

//响应式中断优先级设置为0  
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  

//使能中断  
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  

NVIC_Init(&NVIC_InitStructure);  

扫描二维码关注公众号,回复: 3840659 查看本文章

TIM2设置:

void Timer2_Config(void)  
{   
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;


RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);   

TIM_DeInit(TIM2);  

//定时公式:(TIM_Period + 1) * (TIM_Prescaler + 1) / TIM2 Clock,向上
//TIM2时钟设置72MHz  
TIM_TimeBaseStructure.TIM_Period=10-1;  //自动重装载寄存器的值  

TIM_TimeBaseStructure.TIM_Prescaler=(36-1);         //时钟预分频数  

TIM_TimeBaseStructure.TIM_ClockDivision=0;  //采样分频(捕获)普通定时不需要这个设置 ,无论怎么改变不影响输出频率

TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式  

TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);  

TIM_ClearFlag(TIM2,TIM_FLAG_Update);               //清除溢出中断标志  

TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);  //使能更新中断

TIM_Cmd(TIM2,ENABLE);                              //开启时钟  

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , DISABLE); /*先关闭等待使用*/    
}   


中断函数:

void TIM2_IRQHandler(void)   
{  
u8 i;
u8 ReadValue;  
if(TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET)    //检测是否发生溢出更新事件  
{  
TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);//清除TIM2的中断待处理位  

                /************************************************/

                /***********************重点********************/
/*
for(i=0;i<10;i++)
{
GPIO_ResetBits(GPIOD,GPIO_Pin_3);
}
 */

                /***********************重点********************/

                /*************************************************/
ReadValue = GPIO_ReadOutputDataBit(GPIOC,GPIO_Pin_0);  

if(ReadValue == 0)                   //若该端口当前为低电平,  
{  
GPIO_SetBits(GPIOC,GPIO_Pin_0);//将其改为高电平输出 ;  
}      
else                            //若该端口当前为高电平,  
{  
GPIO_ResetBits(GPIOC,GPIO_Pin_0);   //将其改为低电平输出;  
}  
}          
}  

上述代码下载到单片机里面,输出100KHz的方波(5us定时),但是,笔者欲1us定时,简单认为:

TIM_TimeBaseStructure.TIM_Period=2-1;  //自动重装载寄存器的值  

TIM_TimeBaseStructure.TIM_Prescaler=(36-1);         //时钟预分频数  

后来发现,输出方波最高频率为250KHz,在网上查阅各类博客,发现并不能解决问题。

当随手在中断函数中加了几句话(Period,Prescaler值不变),发现波形改变,于是就开始怀疑1us定时寄存器那样设置,是不是中断函数还未执行完毕,又发生了中断,导致一直在中断函数中。

为验证猜想,笔者做了一个实验,在中断函数中执行了10个:

for(i=0;i<10;i++)
{
GPIO_ResetBits(GPIOD,GPIO_Pin_3);
}

输出波形是这样的:


正常100KHz波形是这样的(上面那个函数屏蔽):


10个多余的周期会导致波形频率差这么多,欲定时1us(前提中断函数比较复杂),采用普通定时器这样的办法是不可以的。

如果中断函数代码时一句或者两句,定时1us还有可能,普通定时器否则定时1us不可能实现。

猜你喜欢

转载自blog.csdn.net/jiqimao1970/article/details/72834564
今日推荐