概述
文章目录
- 前言
- 一、软件思路
- 二、代码
- 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脉冲版本的定时器单次脉冲触发前言一、软件思路二、代码总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复