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();
}