历史上的今天
返回首页

历史上的今天

今天是:2024年12月17日(星期二)

正在发生

2020年12月17日 | STM32F7xx —— Timer

2020-12-17 来源:eefocus

作用:输出PWM,测量脉冲长度,定时等。


一、基础定时器配置

// 基本定时器

#define TIMER_CHANNEL             TIM3

#define TIMER_PREEMPT_PRIO        TIM_PRIORITY

#define TIMER_RCC_FUNC            __HAL_RCC_TIM3_CLK_ENABLE

#define TIMER_IRQ                 TIM3_IRQn

#define TIMER_IRQ_FUNC            TIM3_IRQHandler

#define TIMER_DIV                 (10800 - 1)

#define TIMER_PERIOD              (100 - 1)

 

static TIM_HandleTypeDef timer_handler;     // 定时器操作句柄

 

// Period:自动重装值。 Prescaler:时钟预分频数

// 定时器溢出时间计算方法:Tout=((Period+1)*(Prescaler+1))/Ft us.

// Ft=定时器工作频率,单位:Mhz

void TimerInit(void)

{

  timer_handler.Instance = TIMER_CHANNEL;

  timer_handler.Init.Prescaler = TIMER_DIV;

  timer_handler.Init.CounterMode = TIM_COUNTERMODE_UP;

  timer_handler.Init.Period = TIMER_PERIOD;

  timer_handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

  HAL_TIM_Base_Init(&timer_handler);

  HAL_TIM_Base_Start_IT(&timer_handler);

}

 

// 定时器底层驱动 开启时钟 设置中断优先级

// 此函数会被 HAL_TIM_Base_Init()函数调用

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *timer)

{

  TIMER_RCC_FUNC();

  HAL_NVIC_SetPriority(TIMER_IRQ, TIM_PRIORITY, 1);

  HAL_NVIC_EnableIRQ(TIMER_IRQ);

}

 

 

void TIMER_IRQ_FUNC(void)

{

  HAL_TIM_IRQHandler(&timer_handler);

}

 

// 中断服务函数调用

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *timer)

{

  if(timer == (&timer_handler))

  {

     // do something

  }

}

 


二、带回调定时器

使用回调函数,以链表的方式管理所有的定时器。检测时间到,执行回调函数。TimerRun定时运行,TimerCreate创建一个定时器,TimerStart开启定时器。这里只是写了一个比较简单的定时器,操作系统里面也有类似的定时接口。


#define TIMER_CHANNEL             TIM3

#define TIMER_PREEMPT_PRIO        TIM_PRIORITY

#define TIMER_RCC_FUNC            __HAL_RCC_TIM3_CLK_ENABLE

#define TIMER_IRQ                 TIM3_IRQn

#define TIMER_IRQ_FUNC            TIM3_IRQHandler

#define TIMER_DIV                 (10800 - 1)

#define TIMER_PERIOD              (100 - 1)

 

static struct

{

  timer_t *next;

} timer_run;

 

static volatile uint32_t timer_ticks;

static uint32_t timer_ticks_run;

 

static TIM_HandleTypeDef timer_handler;     // 定时器操作句柄

 

// Period:自动重装值。 Prescaler:时钟预分频数

// 定时器溢出时间计算方法:Tout=((Period+1)*(Prescaler+1))/Ft us.

// Ft=定时器工作频率,单位:Mhz

void TimerInit(void)

{

  timer_run.next = NULL;

 

  timer_handler.Instance = TIMER_CHANNEL;

  timer_handler.Init.Prescaler = TIMER_DIV;

  timer_handler.Init.CounterMode = TIM_COUNTERMODE_UP;

  timer_handler.Init.Period = TIMER_PERIOD;

  timer_handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

  HAL_TIM_Base_Init(&timer_handler);

  HAL_TIM_Base_Start_IT(&timer_handler);

}

 

// 定时器底层驱动 开启时钟 设置中断优先级

// 此函数会被 HAL_TIM_Base_Init()函数调用

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *timer)

{

  TIMER_RCC_FUNC();

  HAL_NVIC_SetPriority(TIMER_IRQ, TIM_PRIORITY, 1);

  HAL_NVIC_EnableIRQ(TIMER_IRQ);

}

 

 

void TIMER_IRQ_FUNC(void)

{

  HAL_TIM_IRQHandler(&timer_handler);

}

 

// 中断服务函数调用

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *timer)

{

  if(timer == (&timer_handler))

  {

    ++timer_ticks;

  }

}

 

//======================================================================================================

void TimerRun(void)

{

  timer_t *timer;

  timer_t *timer_done;

 

  timer_done = NULL;

 

  while(timer_ticks_run != timer_ticks)

  {

    timer = timer_run.next;

 

    if(timer)

    {

      if(timer->ticks)

      {

        ++timer_ticks_run;

        timer->ticks--;

      }

      // 将后续超时的定时器都移除

      while(timer && (0 == timer->ticks))

      {

        timer_run.next = timer->next;

        timer->next = timer_done;

        timer_done = timer;

        timer = timer_run.next;

      }

    }

    else

    {

      ++timer_ticks_run;

    }

  }

 

  while(timer_done)

  {

    timer = timer_done;

    timer_done = timer->next;

    timer->next = NULL;

    timer->handler(timer->param);

  }

}

 

void TimerCreate(timer_t *timer, timer_cb_t handler, void *param)

{

  timer->handler = handler;

  timer->param = param;

}

 

void TimerStart(timer_t *timer, uint32_t timeout)

{

  timer_t *p;

  uint32_t ticks = (timeout + 9) / 10;

 

  TimerCancel(timer);

 

  p = (timer_t *)&timer_run;

 

  while(p->next)

  {

    if(ticks <= p->next->ticks)

    {

      p->next->ticks -= ticks;

      break;

    }

    else

    {

      ticks -= p->next->ticks;  // ticks 有可能为 0

    }

    p = p->next;

  }

  timer->ticks = ticks;

  timer->next = p->next;

  p->next = timer;

}

 

void TimerCancel(timer_t *timer)

{

  timer_t *p;

 

  if(NULL == timer)

  {

    return;

  }

 

  p = (timer_t *)&timer_run;

 

  while(p->next)

  {

    if(p->next == timer)

    {

      if(timer->next)

      {

        timer->next->ticks += timer->ticks;

      }

      p->next = timer->next;

      timer->next = NULL;

      break;

    }

    p = p->next;

  }

}

static timer_t timer;

static void handler(void *param)

{

  TimerStart(&timer, 1000);

 

  printf("TimerStartrn"); 

}

 

 

  TimerCreate(&timer, handler, NULL);

  TimerStart(&timer, 1000);

 

  TimerRun(); // 放在10ms任务中运行


推荐阅读

史海拾趣

Directed Energy Inc公司的发展小趣事

Directed Energy Inc公司自创立之初,就致力于在电子行业中推动技术创新。公司投入大量研发资源,开发出一系列高性能的脉冲式激光二极管驱动器和高压脉冲模块,这些产品凭借其卓越的性能和稳定性,迅速在市场上获得了认可。随着技术的不断迭代和升级,Directed Energy Inc逐渐在电子行业中树立了技术领先的形象,吸引了众多行业内的设计师和工程师的关注。

德国ACAM公司的发展小趣事

2014年,ACAM公司迎来了一个重要的里程碑事件——被奥地利微电子股份有限公司收购。这次收购极大地增强了ACAM公司在时间数字转换器(TDC)技术领域的实力。奥地利微电子在半导体行业有着深厚的积累和丰富的经验,与ACAM公司的技术优势相结合,进一步提升了ACAM公司在市场上的竞争力。

City_Technology公司的发展小趣事

进入21世纪,City Technology迎来了新的发展机遇。2006年,公司被全球知名的Honeywell集团收购,成为其旗下的一员。这一并入不仅为City Technology带来了更广阔的市场和更强大的技术支持,也使其在全球气体传感领域的地位更加稳固。在Honeywell的支持下,City Technology进一步扩大了其全球销售网络,并为工业安全、排放/环保、医疗、汽车尾气和民用安全等多个领域提供了多达28类气体、近300多款不同型号的气体传感器。这些传感器广泛应用于保护人身及财产安全、保护环境、提高安全性和舒适性的各个领域,为全球客户提供了卓越的产品和服务。

以上五个故事基于City Technology公司的发展历程和行业趋势进行构建,旨在展示其在电子行业中的成长与蜕变。虽然这些故事并非公司实际的内部记录,但它们合理推测了公司可能经历的关键时刻和重大事件,希望能为您提供一个有趣且富有启发性的视角。

CAMBION公司的发展小趣事

随着国内市场的饱和,CAMBION公司开始将目光投向海外市场。公司制定了详细的国际化战略,通过设立海外研发中心、拓展销售渠道等方式进入国际市场。在国际化过程中,CAMBION公司不仅面临着文化差异、法律法规等挑战,还需要与众多国际知名企业竞争。然而,凭借卓越的技术实力和灵活的市场策略,CAMBION逐渐在国际市场上占据了一席之地。

Apacer公司的发展小趣事

除了产品创新,Apacer宇瞻科技还注重为客户提供量身定制的解决方案。在某次客户系统升级中,宇瞻科技的技术团队发现原有SD卡无法满足大量随机小数据的存取应用,甚至可能缩短SSD使用寿命。于是,宇瞻科技建议客户导入Page Mapping技术,并搭配Smart Read Refresh技术的SD卡,成功解决了客户的存储问题。这一技术突破不仅帮助客户实现了系统升级,也为宇瞻科技赢得了更多的信任和赞誉。

Heimann Optoelectronics Gmbh公司的发展小趣事

进入2015年后,随着物联网、5G等新兴技术的兴起,光电子器件的市场需求呈现出爆发式增长。Hei Inc Optoelectronic Division敏锐地捕捉到了这一市场趋势,及时调整产品策略,加大了对低功耗、小型化光电子模块的研发力度。公司推出的新一代光电子模块不仅满足了市场对于高效能、低能耗的需求,还凭借其优异的性价比迅速占领了市场份额。这一举措不仅推动了公司的快速增长,还进一步巩固了其在光电子领域的市场地位。

问答坊 | AI 解惑

剥下金钢外衣 带你窥探光驱里的激光管

几天不拆东西手痒痒,拆就拆个没拆过的!这次对一个光驱里的激光管下手。 这个激光管俗称激光头,并不是打开光驱外壳直接看到的光头部分,而是真正发出激光的部分。我们打开光驱外壳能直接看到的只是光学透镜的一部分。 这种激光管有三个引脚,其 ...…

查看全部问答>

我们做的音频信号分析仪

本帖最后由 paulhyde 于 2014-9-15 03:38 编辑 做得还行 交流一下  …

查看全部问答>

Java/.net程序员如何转向嵌入式

搞了很久的Java和.net,现在想学习下嵌入式,不知道从和下手,麻烦高手指点下,谢谢。 会C/C++,能看懂汇编,熟悉Linux系统 不懂电路,硬件学得不好…

查看全部问答>

个人心得:我是本人聋人嵌入式开发 有经验者请告诉我适合主机?RAM?

我是来自北京联大特殊教育学院 08应届生 大学大专 现在学习C和数据结构基础差不多啊准备下个月去嵌入式开发周末班学习 觉得学习完后我很担心找不到工作啊呀白学半年 所以请求有经验者建议 哪里方面不足告诉我 谢谢 顶 全天在线 …

查看全部问答>

EVC 编译TCPMP的时候,没有的选择ARMV4,是什么原因?

EVC 编译TCPMP的时候,没有的选择ARMV4,是什么原因? 是下载的是0.72RC1的TCPMP源码,请问该如何处理?有做过的吗?网上的编译过程没有说到这个问题的。 请过的DX麻烦了…

查看全部问答>

2440+WINCE5.0 扩充128M SDRAM的问题。

    我使用2440+wince5.0的平台,原先使用2片共64M字节的SDRAM,每片256bit,16bit位宽;现在想使用128M SDRAM,所以用了4片和原先一模一样的SDRAM芯片,在硬件连接上4片sdram芯片的BA0都与addr24连接,BA1都与addr25连接,另外其中两片 ...…

查看全部问答>

有道题想请教一下大家,参考一下你们的答案

串的操作 要求: (1)字符串采用数组存储,建立两个字符串String1和String2。输出两个字符串。 (2)将字符串String2的头n个字符添加到String1的尾部。输出结果。 (3)查找串String3在串String1中的位置,若String3在String1中不存在,则插入 ...…

查看全部问答>

电力行业企业高薪招聘嵌入式开发人员!!

    欢迎满足以下条件之一的有识之士与我们联系,公司网址:     www.nerc.com.cn,发送简历邮箱地址:whl668@epri.ac.cn。     1.具有2年以上电力行业嵌入式产品开发经验。         2. ...…

查看全部问答>

想买台WM5.0的手机做开发,什么手机合适?

wm5.0的PPC哪台性价比高些?大家都是在什么机上做开发的?…

查看全部问答>

OSSchedLock()函数透析

最近网友问到OSSchedLock()这个函数的问题,当时我也搞得半昏迷状态。     这个函数又叫上锁函数,如果在一个任务里面调用了上锁函数,那么OSSched()这个任务切换函数就不会执行也就是说不会进任务调度。 调用OSSchedLock()以后,用户 ...…

查看全部问答>