1.通道结构
5744每个eTimer模块含有6个相同的计数通道,每个计数通道含有16位计数器、分频器、保持寄存器各一个,捕捉寄存器、比较寄存器、比较预加载寄存器各两个,还有四个控制寄存器,其通道结构如下图:
2、计数模式、
eTimer模块含有多种计数模式,可根据实际情况选择合适的计数模式
1、计数上升沿;
2、计数跳边沿(上升沿和下降沿均计数);
3、当二次输入为高时计数;
4、QUADRATURE-COUNT模式,该模式下计数器对一次和二次输入进行编码计数,模式图如下:
5、SIGNED-COUNT模式,该模式下计数器根据二次输入电平选择的计数方向(递增或递减)进行计数。
6、TRIGGERED-COUNT,该模式下计数器在二次输入上升沿后开始计数,在下一个二次输入上升沿或比较事件发生停止计数,示意图如下:
7、ONE-SHOT模式,该模式下二次输入触发通道开始计数,计数完成后OFLAG输出(输出模式为初始化时清空、比较时置位),示意图如下:
8、串联输出模式,即是一个通道的输出脉冲作为另一个通道的输入时钟源;
9、脉冲输出模式,该模式下分为输出固定频率和可变频率的可调占空比脉冲。
3、时钟配置
eTimer模块的时钟由MOTC_CLK提供,故在使用eTimer模块之前需要进行MOTC_CLK时钟的配置。MOTC_CLK模块时钟由MC_CGM模块配置,具体参考时钟模块。
4、功能配置
eTimer可进行比较、捕捉、脉冲产生等多种功能,本文主要介绍定时、脉冲产生和脉冲捕捉。在使用所有功能之前,都需要进行模块时钟的配置。
1、定时器功能
在已知模块时钟的情况下,选择模块内部时钟作为计数时钟源并选择持续计数,然后设置比较发生时自动加载计数初始值0,那么根据设置的分频因子和比较值可计算定时周期,计算公式为:comp_value/(Freq/freq_divisor)(秒)。
配置流程如下:
1)管脚复用配置并失能配置通道;
2)设置比较值;
3)配置计数器加载初值,一般为0;
4)设置计数模式;
5)设置计数时钟源和分频因子;
6)设置计数次数、计数初始化特性和计数方向;
7)设置比较模式;
8)使能对应中断并设置对应中断优先级;
9)设计中断函数;
2、可调占空比的脉冲输出功能
若选择计数源为模块内部时钟,配置通道引脚为输出且设置为比较置位和计数溢出清空,则可设置不同比较值来配置脉冲输出占空比,占空比计算公式为(65536-com_value)/65536.
配置流程如下:
可调占空比输出与定时器模式类型,可不使能比较中断,但是需要使能所选通道的输入功能并选择输出模式。
3、脉冲捕捉及占空比测量功能
选择一次时钟为模块内部时钟并计数,二次时钟为捕捉脉冲,然后设置CAP1、CAP2分别捕捉上下升沿,在CAP1捕捉发送时保存当前计数值为low_time然后重新加载计数初值为0,eTimer模块然后会捕捉二次输入时钟的下降沿,在CAP2捕捉发送时保存当前计数值为high_time然后重新加载计数初值为0,最后根据高电平占据的时间计数占空比,计算公式为:high_time/(high_time+low_time)。
配置流程如下:
1)管脚复用配置并失能配置通道;
2)配置加载初值;
3)设置计数模式;
4)设置一次时钟源并设置分频因子;
5)设置计数次数、计数初始化特性和计数方向;
6)配置捕捉模式和捕捉方式并启动捕捉;
7)使能对应捕捉中断并设计相应中断函数;
8)使能对应通道;
4、示例代码
1、宏定义
#define ETIMER_CHANNEL0 0
#define ETIMER_CHANNEL1 1
#define ETIMER_CHANNEL2 2
#define ETIMER_CHANNEL3 3
#define ETIMER_CHANNEL4 4
#define ETIMER_CHANNEL5 5
#define ETIMER_FREDV_1 0b000
#define ETIMER_FREDV_2 0b001
#define ETIMER_FREDV_4 0b010
#define ETIMER_FREDV_8 0b011
#define ETIMER_FREDV_16 0b100
#define ETIMER_FREDV_32 0b101
#define ETIMER_PREDV_62 0b110
#define ETIMER_FREDV_128 0b111
#define ETIMER_CHANNEL_CMP 0
#define ETIMER_CHANNEL_CAP 1
2、实现代码
/**********************************************************
* 函数名
* 说明 根据所选ETIMER0通道和功能进行管脚复用的设置
* 输入参数
* ETIMER_CHANNELx
* 所选ETIMER通道 x可为0~5
* ETIMRT_CHANNEL0 选择ETIMER0的通道0
* ETIMER_CHANNEL_TYPEx
* 所选ETIMER通道所选功能
* ETIMER_CHANNEL_CMP 比较输出功能
* ETIMER_CHANNEL_CAP 输入捕获功能
*/
void ETIMER_ETIMER0_Channel_Multi(uint8_t ETIMER_CHANNELx,uint8_t ETIMER_CHANNEL_TYPEx)
{
if(ETIMER_CHANNEL_CMP == ETIMER_CHANNEL_TYPEx)
{
if(ETIMER_CHANNELx<=4)
{
SIUL2.MSCR[ETIMER_CHANNELx].B.OBE=1; //使能输出
SIUL2.MSCR[ETIMER_CHANNELx].B.SRC=3;
SIUL2.MSCR[ETIMER_CHANNELx].B.SSS=1; //管脚复用为ETC0输出通道
}
else if(ETIMER_CHANNELx == 5)
{
SIUL2.MSCR[100].B.OBE=1;
SIUL2.MSCR[100].B.SRC=3;
SIUL2.MSCR[100].B.SSS=1;
}
}
else if(ETIMER_CHANNEL_CAP == ETIMER_CHANNEL_TYPEx)
{
if(ETIMER_CHANNELx <= 4)
{
SIUL2.MSCR[ETIMER_CHANNELx].B.IBE=1; //使能输入
}
else if(ETIMER_CHANNELx == 5)
{
SIUL2.MSCR[100].B.IBE=1;
}
SIUL2.IMCR[59+ETIMER_CHANNELx].B.SSS=2; //管脚复用为ETC0输入通道
}
}
/******************************************************************************************************
* 函数名 ETIMER_ETIMER0_Channel_Init
* 说明 对制定ETIMER0通道CHANNELx进行初始化
* 输入参数
* ETIMER_CHANNELx
* 所指定的ETIMER0通道 x可为0~5
* comp_value
* 比较值 当ETIMER_CHANNEL_TYPEx为ETIMER_CHANNEL_CMP时有效 否则无效
* ETIMER_FREDV_x
* 分频值 一次输入时钟的分频值
* ETIMER_CHANNEL_TYPEx
* 所选通道类型 可为ETIMER_CHANNEL_CMP(输入比较)和ETIMER_CHANNEL_CAP(输入捕捉)
* prio
* 所选通道中断优先级
* 返回值 无
* 示例 ETIMER_ETIMER0_Channel_Init(ETIMER_CHANNEL0,15000,ETIMER_FREDV_8,ETIMER_CHANNEL_CMP,0xC);
* //配置ETIMER0 CHANNEL0为输出比较类型 比较值为15000 一次输入脉冲分频值为8 中断优先级为12
******************************************************************************************************
*/
void ETIMER_ETIMER0_Channel_Init(uint8_t ETIMER_CHANNELx,uint8_t ETIMER_CHANNEL_TYPEx,uint32_t comp_value,uint8_t ETIMER_FREDV_x,uint8_t prio)
{
ETIMER_ETIMER0_Channel_Multi(ETIMER_CHANNELx,ETIMER_CHANNEL_TYPEx); //进行管脚复用和引脚输入、输出功能设置
ETIMER_0.ENBL.R &= (~(1<<ETIMER_CHANNELx)); //失能通道ETIMER_CHANNELx
if(ETIMER_CHANNEL_CMP == ETIMER_CHANNEL_TYPEx) //判断通道类型
{ //进行比较输出功能设置
ETIMER_0.CH[ETIMER_CHANNELx].COMP1.R=comp_value; //设置比较值
ETIMER_0.CH[ETIMER_CHANNELx].LOAD.R=0; //计数器初始加载值
ETIMER_0.CH[ETIMER_CHANNELx].CTRL1.B.CNTMODE=1; //计数上升沿
ETIMER_0.CH[ETIMER_CHANNELx].CTRL1.B.PRISRC=0b11000|ETIMER_FREDV_x;//选用IP BUS作为时钟源并进行分频因子设定
ETIMER_0.CH[ETIMER_CHANNELx].CTRL1.B.ONCE=0; //持续循环计数
ETIMER_0.CH[ETIMER_CHANNELx].CTRL1.B.LENGTH=0; //计数到计数器溢出再重新加载初值
ETIMER_0.CH[ETIMER_CHANNELx].CTRL1.B.DIR=0; //计数器递增计数
ETIMER_0.CH[ETIMER_CHANNELx].CTRL2.B.OEN=1; //使能OFLAG输出功能
ETIMER_0.CH[ETIMER_CHANNELx].CTRL2.B.OUTMODE=0b0111; //选择输出模式为计数器到的比较值时置OSFLAG 溢出时请零OFLAG
ETIMER_0.CH[ETIMER_CHANNELx].CCCTRL.B.CMPMODE=2; //选择COMP1为递增计数 COMP2为递减计数 因为COMP1和COMP2一直使能
//若选择0且COMP2未初始化,则计数到COMP2时会一直加载初始值0 无法计数到COMP1
ETIMER_0.CH[ETIMER_CHANNELx].INTDMA.B.TCF1IE=1; //打开TCF1IE即COMP1比较中断
}
else if(ETIMER_CHANNEL_CAP == ETIMER_CHANNEL_TYPEx)
{
//捕捉模式配置
ETIMER_0.CH[ETIMER_CHANNELx].LOAD.R=0;
//配置计数器
ETIMER_0.CH[ETIMER_CHANNELx].CTRL1.B.CNTMODE=1; //计数时钟上升沿
ETIMER_0.CH[ETIMER_CHANNELx].CTRL1.B.PRISRC=0b11000|ETIMER_FREDV_x; //选择IP BUS作为计数时钟源并设置分频因子
ETIMER_0.CH[ETIMER_CHANNELx].CTRL1.B.ONCE=0; //配置持续计数
ETIMER_0.CH[ETIMER_CHANNELx].CTRL1.B.DIR=0; //设置递增计数方向
ETIMER_0.CH[ETIMER_CHANNELx].CTRL1.B.SECSRC=ETIMER_CHANNELx; //选择进行信号捕捉的通道
ETIMER_0.CH[ETIMER_CHANNELx].CTRL2.B.OEN=0; //失能输出
ETIMER_0.CH[ETIMER_CHANNELx].CTRL3.B.ROC=3; //捕捉全部跳变沿(上升沿和下降沿)
ETIMER_0.CH[ETIMER_CHANNELx].CCCTRL.B.CPT1MODE=2; //CAP2捕捉下降沿
ETIMER_0.CH[ETIMER_CHANNELx].CCCTRL.B.CPT2MODE=1; //CAP1捕捉上升沿
ETIMER_0.CH[ETIMER_CHANNELx].CCCTRL.B.ARM=1; //装配捕捉
ETIMER_0.CH[ETIMER_CHANNELx].INTDMA.B.ICF1IE=1; //使能CAP1捕捉
ETIMER_0.CH[ETIMER_CHANNELx].INTDMA.B.ICF2IE=1; //使能CAP2捕捉
}
INTC_0.PSR[611+ETIMER_CHANNELx].R=0x8000|prio; //配置CHANNELx的中断优先级
ETIMER_0.ENBL.R |= (1<<ETIMER_CHANNELx); //使能CHANNELx
}