SmartFusion片上MUC有两个32位的定时器,可以分别独立使用,也可以两个合并成一个64位定时器来使用。
驱动库只有一个mss_timer.h文件,库函数也比较简单。之前几篇文章,我们介绍了MSS_GPIO的使用和SysTick定时器的使用,使用SysTick内核定时器可以精确控制延时,使用外设定时器也能实现定时。
本篇文章介绍MSS_TIMER定时器的使用和配置,演示定时器周期溢出中断,单次溢出中断,自定义波形功能。
固件库下载地址:Firmware_MSS_Timer_Driver_v2.3.102
官方使用文档路径:X:\Microsemi\common\vault\Components\Actel\Firmware\MSS_Timer_Driver\2.3.102\fs\p2f0\docs
示例代码可以参考:
MSS_TIMER库函数整体可分为三种:初始化,定时器配置和中断控制。
其中TIMx可为TIM1、TIM2或TIM64,其中TIM64是把TIM1和TIM2合成一个64位的定时来使用。
初始化函数,初始化完成之后,定时器将会停止,禁止中断,并设置工作模式。
/* 配置定时器的工作方式,单次中断还是周期性中断 */ void MSS_TIMx_init( mss_timer_mode_t mode )mode支持的取值:
/* 周期性溢出中断模式 */ MSS_TIMER_PERIODIC_MODE /* 单次溢出中断模式 */ MSS_TIMER_ONE_SHOT_MODE配置函数:
/* 设置溢出值,立即生效 */ void MSS_TIMx_load_immediate(uint32_t load_value); /* 指定下次计时的溢出值 */ void MSS_TIMx_load_background(uint32_t load_value); /* 获取当前计数值 */ uint32_t MSS_TIMx_get_current_value(); /* 获取64位定时器的当前值,高32位和低32位 */ void MSS_TIM64_get_current_value(uint32_t * load_value_u, uint32_t * load_value_l) /* 启动定时器 */ void MSS_TIMx_start(void); /* 停止计数器 */ void MSS_TIMx_stop(void);中断控制函数
/* 使能中断 */ void MSS_TIMx_enable_irq(void); /* 禁止中断 */ void MSS_TIMx_disable_irq(void); /* 清除中断 */ void MSS_TIMx_clear_irq(void);了解了定时器操作的相关函数,下面来演示几个定时器的使用方法。
GPIO每隔250ms翻转一次。
/* TIM1配置成周期中断,中断时间250ms */ MSS_TIM1_init(MSS_TIMER_PERIODIC_MODE); MSS_TIM1_load_immediate(SystemCoreClock/4); MSS_TIM1_start(); MSS_TIM1_enable_irq(); /* 定时器中断服务函数 */ void Timer1_IRQHandler(void) { static uint8_t status = 0; status = !status; MSS_IO_OUT(1) = status; MSS_TIM1_clear_irq(); }产生20ms、40ms、60ms、80ms、100ms高低电平相间的波形。
#define SEQUENCE_LENGTH 5 static const uint32_t g_delays_list[SEQUENCE_LENGTH] = { 20, 40, 60, 80, 100 }; int main() { 。。。。。。。。。。。。。。 /* TIM1配置成周期中断,中断时间250ms */ MSS_TIM1_init(MSS_TIMER_PERIODIC_MODE); MSS_TIM1_load_immediate(g_delays_list[0]); MSS_TIM1_start(); MSS_TIM1_enable_irq(); while(1) { 。。。。。。 } } void Timer1_IRQHandler(void) { static uint8_t idx = 0; static uint8_t status = 0; status = !status; MSS_IO_OUT(1) = status; /* 指定下次计时溢出值 */ MSS_TIM1_load_background( g_delays_list[idx] * (SystemCoreClock/1000)); if(idx < SEQUENCE_LENGTH) idx++; else idx = 0; MSS_TIM1_clear_irq(); }最终生成的波形:
两个32位的定时器可以组成1个64位的定时器,64位定时器和TIM1共用一个中断服务函数。按键按下时,LED停止闪烁,松开继续闪烁。
#include "main.h" int main() { uint8_t key; delay_init(); /* 更新系统时钟 */ MSS_WD_disable(); MSS_GPIO_init(); /* GPIO_0 & GPIO_1 配置成输出模式 */ MSS_GPIO_config(MSS_GPIO_0, MSS_GPIO_OUTPUT_MODE); MSS_GPIO_config(MSS_GPIO_1, MSS_GPIO_OUTPUT_MODE); /* GPIO_2配置成输入模式 */ MSS_GPIO_config(MSS_GPIO_2, MSS_GPIO_INPUT_MODE); /* TIM64配置成周期中断,中断时间250ms */ MSS_TIM64_init(MSS_TIMER_PERIODIC_MODE); MSS_TIM64_load_immediate(0, SystemCoreClock/4); MSS_TIM64_start(); MSS_TIM64_enable_irq(); while(1) { key = MSS_IO_IN(2); if(key == 1) /* 按键按下暂停 */ { MSS_TIM64_stop(); while(MSS_IO_IN(2) == 1); /* 等待释放 */ MSS_TIM64_start(); /* 释放继续计时 */ } } } /* TIM64与TIM1共用一个中断服务函数 */ void Timer1_IRQHandler(void) { static uint8_t status = 0; status = !status; MSS_IO_OUT(1) = status; MSS_TIM64_clear_irq(); }使用ONE_SHOT模式,可以配置只产生一次溢出中断。按键每按下启动一次定时器,产生一次中断,4s之后LED状态翻转,即按键控制LED时,延时4s。
#include "main.h" int main() { uint8_t key; delay_init(); /* 更新系统时钟 */ MSS_WD_disable(); MSS_GPIO_init(); /* GPIO_0 & GPIO_1 配置成输出模式 */ MSS_GPIO_config(MSS_GPIO_0, MSS_GPIO_OUTPUT_MODE); MSS_GPIO_config(MSS_GPIO_1, MSS_GPIO_OUTPUT_MODE); /* GPIO_2配置成输入模式 */ MSS_GPIO_config(MSS_GPIO_2, MSS_GPIO_INPUT_MODE); /* TIM1配置成单次中断模式 */ MSS_TIM1_init(MSS_TIMER_ONE_SHOT_MODE); while(1) { key = MSS_IO_IN(2); if(key == 1) /* 按键按下中断一次 */ { MSS_TIM1_load_immediate(SystemCoreClock*4); MSS_TIM1_enable_irq(); MSS_TIM1_start(); while(MSS_IO_IN(2) == 1); /* 等待释放 */ } } } /* TIM1中断服务函数 */ void Timer1_IRQHandler(void) { static uint8_t status = 0; status = !status; MSS_IO_OUT(1) = status; MSS_TIM1_clear_irq(); }