我是靠谱客的博主 诚心白开水,最近开发中收集的这篇文章主要介绍非PWM脉冲版本的定时器单次脉冲触发前言一、软件思路二、代码总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

  • 前言
  • 一、软件思路
  • 二、代码
    • 1.主函数代码
    • 2.定时器代码
  • 总结


前言

最近接了一个单子,关于单次脉冲触发的。具体的要求在于,按键按下产生一个7ms脉宽的方波。基于这个需求,看了网上一些代码,最后觉得自己用定时器写一个代码也挺便捷的,加上单片机的GPIO口翻转速度还是不错的,在ms级别完全可以胜任,因此选用纯逻辑思路去实现单次脉冲的触发。


一、软件思路

需求很简单,解决方法的话也很简单。明确需求后可以得知用到的模块有按键控制模块,判断按键按下从而控制脉冲的触发。定时器模块,通过周期扫描判断触发信号是否为高电平,若为高电平则开始进行计数,同时拉高对应的GPIO口输出。当计数完成以后,再拉低GPIO口的输出,这样就能够实现按键触发一次对应生成一次7ms脉冲波的效果。在这个过程中需要注意的是,因为是在while循环里面进行扫描,所以key的扫描速度非常快,如果按键触发是支持连续按的话,很有可能就会生成多个单次脉冲波,因此需要设置key_scan为松开再置位的模式,这样只有当按键松开后才会进行第二次的判断。

二、代码

1.主函数代码

代码如下:主函数的代码比较简洁。可见在我们的初始化函数中初始化了按键和定时器,此处我们定时器中断的时间为72000000/72/10也就是100KHz,那么每进入一次中断的时间即为10us。设计目标是7ms的脉冲,即需要定时器中断大概700次即可得到理想的脉冲触发效果。定义的status变量含义为脉冲开始触发信号,一旦这个信号被拉高,定时器中断判断这个信号为高电平以后会执行下一步的操作。

#include "led.h"
#include "key.h"
#include "sys.h"
#include "timer.h"
#include "delay.h" 

int main(void)
{
 	vu8 key=0;	
	delay_init();	    	     //延时函数初始化	  
 	LED_Init();			         //输出脉冲接口
	KEY_Init();              //初始化与按键连接的硬件接口
	TIM3_Int_Init(9,71);     //100Khz的计数频率 
	while(1)
	{
 		key=KEY_Scan(0);	//得到键值
	  if(key==WKUP_PRES)
		{						   		
			status=1;
			delay_ms(10);
		}else delay_ms(10); 
	}	 
}

2.定时器代码

代码如下:用到的定时器是定时器三,选择任意一个合适的定时器都能够实现相同的效果。在定时器中断三里面,首先判断status变量的状态,如果高电平则定时器定义的time则会自加,不是高电平则停止自加。当time处于0-700的状态之间时,OUTPUT定义为高电平,当超出了700或者time为0的时候,则定义为低电平。根据这个逻辑,定义的暂态变量time会在status为高电平期间不断累积自加。当累积到了700以后,通过if判断语句将status变量复位到0,为下一次的触发做准备。

#include "timer.h"
#include "led.h"
static u16 time=0;
u8 status=0;
void TIM3_Int_Init(u16 arr,u16 psc)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
	
	//定时器TIM3初始化
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

	//中断优先级NVIC设置
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器


	TIM_Cmd(TIM3, ENABLE);  //使能TIMx					 
}
//定时器3中断服务程序
void TIM3_IRQHandler(void)   //TIM3中断
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
	{
		 TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志 
		 if(status==1)time++;
     else time=time;
		
     if(time>0&&time<700)OUTPUT=1;
     else OUTPUT=0;		
		
		 if(time>=700)
		 {
			 status=0;
			 time=0;
			 OUTPUT=0;
		 }
	}
}

总结

经过实际验证,输出的脉冲可行,也并不存在着触发误差。

最后

以上就是诚心白开水为你收集整理的非PWM脉冲版本的定时器单次脉冲触发前言一、软件思路二、代码总结的全部内容,希望文章能够帮你解决非PWM脉冲版本的定时器单次脉冲触发前言一、软件思路二、代码总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(58)

评论列表共有 0 条评论

立即
投稿
返回
顶部