STM32G030 基于HAL库 使用TIM+EXTI 完成500ns窄脉冲

       因为是个刚接触单片机几个月的新手, 所以理解上可能有些不准确,在写这个贴子之前我有注意到关于单片机用定时器比较多的都是us级别的,有关ns级的很少,所以就只能自己摸索摸索,肯定有不合理的地方,欢迎大神友好指点。

        今天领导发了一个任务,做一个 0.5-3us 的窄脉冲,具体实现如下:

一、思路:

         PD3是外部上升沿中断,当检测到上升沿就拉高PD2,同时打开TIM3,TIM3溢出进入中断后拉低PD2同时关闭TIM3,这样TIM3的定时时间决定了脉冲宽度。想法是这样,但是在用STM30G030这块片子的时候还是遇到了很多棘手的问题,其中就有用HAL库死活定时不到5us以下的情况。今天就把我突发奇想的一个小招分享出来,希望能多多指点!

二、程序是基于HAL库的,外部EXTI和TIM3的中断函数如下:

void EXTI2_3_IRQHandler(void)
{
	HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
	HAL_GPIO_WritePin(TRIG_OUT_GPIO_Port,TRIG_OUT_Pin,GPIO_PIN_SET);  //拉高TGIR_OUT线
	HAL_TIM_Base_Start_IT(&htim3);     //开启TIM3
}


void TIM3_IRQHandler(void)
{
	HAL_TIM_IRQHandler(&htim3);   //这个函数内部就清除了中断标志位所以不需要额外的程序来清除
	HAL_GPIO_WritePin(TRIG_OUT_GPIO_Port,TRIG_OUT_Pin,GPIO_PIN_RESET);   //拉低
	HAL_TIM_Base_Stop_IT(&htim3);   //关闭TIM3,
}

TIM3的预分频系数和重加载值都是1的情况下的脉宽:

可以看出来有大约5us的延时,这个时候领导说HAL库一些程序会自带很多判断语句,导致延时(如果大家和我一样是个新手,好奇的话可以点开HAL库的一些函数比如:HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim) 这个函数,进去看看是有很多判断语句的),于是将不必要的语句删掉,将程序简至最短,这个时候修改后的函数如下:

void EXTI2_3_IRQHandler(void)
{
	__HAL_GPIO_EXTI_CLEAR_RISING_IT(GPIO_PIN_2);   //清楚上升沿挂起位
	htim3.Instance->DIER |= TIM_IT_UPDATE;  //开启更新中断
	htim3.Instance->CR1  |= TIM_CR1_CEN;    //TIM3开始计数,这个时候先开始计数再拉高TRIG会让计数器先走一点,这样就提前一些进入中断了
	GPIOD->BSRR = TRIG_OUT_Pin;    //拉高TRIG
	
}

void TIM3_IRQHandler(void)
{
	GPIOD->BRR = (uint32_t)GPIO_PIN_3;  //进入中断第一件事就是拉低TRIG,然后再关定时器
	__HAL_TIM_DISABLE(&htim3);  //关闭定时器
	__HAL_TIM_CLEAR_FLAG(&htim3,TIM_FLAG_UPDATE);   //清楚标志位
}

        首先要得到500ns的话,预分频系数psc假设1,那么加载值arr就应该是32,将数值带进去这个时候并没有得到我们想要的定时效果,所以得想办法啊,欸?!!

        我就想到定时器中断是通过计数来实现定时的,64MHZ的频率1s跳64M次,通过分屏系数和加载值才等到了我们想要的定时时间。也就是说以向上计数为例从0开始跳到我们设定的加载值再从0继续往上跳,那是不是可以每次重新设置一个起始加载数,这样就可以缩短一些定时时间以避免这些延时呢?

        就找啊找,找到了这样一个函数:

 __HAL_TIM_SET_COUNTER(__HANDLE__, __COUNTER__)

那就开始带进去吧,首先我们看到分频系数psc为1,加载值arr为32的脉宽图:

         这是大约0.8us吧,距离0.5us超了个0.3us左右,那我们就重新设置加载值吧!

        加载值的设定计算过程我简单的提一下,我的分频系数是1,代表着每1s要跳64m下,也就是每大约0.015625us跳一下,加载值32的话就是定时32*0.015625=0.5us。根据脉宽图我们需要给他提前0.3us左右,所以0.3/0.015625 = 23,然后修改TIM3的中断函数,程序如下:

void TIM3_IRQHandler(void)
{
	GPIOD->BRR = (uint32_t)GPIO_PIN_3;  //拉低TRIG
	__HAL_TIM_DISABLE(&htim3);  //关闭定时器
	__HAL_TIM_CLEAR_FLAG(&htim3,TIM_FLAG_UPDATE);   //清楚标志位
	__HAL_TIM_SET_COUNTER(&htim3,23);  //计数器设置成23
}

我们于是得到了一个最终的脉宽图:

        500ns近似乎是达成啦! 耶!

        其实这算是一个学艺不精而奇思妙想出来的旁门左道,分享出来完成一个KPI,在解决这个问题之后,我对于定时器算是了解深入一点了,如果和我一样也是初学者的话感兴趣大家可以试试。

        

  

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值