概要
- CMS32L051的定时器搭载两个通用定时器单元,每个单元含有4个通道。每个通用定时器单元有4个16位定时器。各16位定时器称为“通道”,既能分别用作独立的定时器,也能组合多个通道用作高级的定时器功能。
- 定时器时钟选择寄存器m(TPSm)是16位寄存器,选择提供给各通道的2种或者4种公共运行时钟(CKm0、CKm1、CKm2、CKm3)。通过TPSm寄存器的bit3~0选择CKm0,通过TPSm寄存器的bit7~4选择CKm1。另外,只有通道1和通道3才能选择CKm2和CKm3,通过TPSm寄存器的bit9~8选择CKm2,通过TPSm寄存器的bit13和bit12选择CKm3。
- 官方提供的标准库函数全是使用CKm0作为运行时钟,这将导致使用同一个定时器单元下的通道时,时钟分频必须保持一直,否则将会使用最后一个分频系数,导致时钟错乱。
- 修改标准库函数中的定时器初始化,根据分频系数确定选择的运行时钟。
- 各通道的寄存器使用或的关系赋值,不能相互影响。
代码
- int TIM_Init(TIM_InitTypeDef *TIM_InitStruct)
int TIM_Init(TIM_InitTypeDef *TIM_InitStruct)
{
int ret = TIM_SUCC;
uint8_t i=0,j=0;
uint8_t chanPos =0,chanNum=0,pos=0,currentChan[8]={0};
uint8_t masterPos =0,masterNum=0,posm=0,currentMChan[4]={0};
uint16_t Ckm_Type = 0;
assert_param(IS_TIM(TIM_InitStruct->TIM));
assert_param(IS_TIM_CHANNEL(TIM_InitStruct->TIM_Channel));
Ckm_Type = TIM_InitStruct->TIM_ClkDivision;
if (Ckm_Type & 0x000f) {
Ckm_Type = _0000_TM_CLOCK_SELECT_CKM0;
} else if (Ckm_Type & 0x00f0) {
Ckm_Type = _8000_TM_CLOCK_SELECT_CKM1;
} else if (Ckm_Type & 0x0f00) {
Ckm_Type = _4000_TM_CLOCK_SELECT_CKM2;
} else if (Ckm_Type & 0xf000) {
Ckm_Type = _C000_TM_CLOCK_SELECT_CKM3;
} else if (Ckm_Type == 0){
Ckm_Type = _0000_TM_CLOCK_SELECT_CKM0;
}
if(TIM_InitStruct->TIM == TIM40)
{
CGC_PER0PeriphClockCmd(CGC_PER0Periph_TIM40,ENABLE);
}
else if(TIM_InitStruct->TIM == TIM41)
{
CGC_PER0PeriphClockCmd(CGC_PER0Periph_TIM41,ENABLE);
}
Tim_RegSetting(TIM_InitStruct->TIM);
#if 0
*TIM_reg.TPS = TIM_InitStruct->TIM_ClkDivision;
#else
*TIM_reg.TPS |= TIM_InitStruct->TIM_ClkDivision;
#endif
if(1==IS_TTM_Master_Chan(TIM_InitStruct->TIM_Selection_Master))
{
for(masterPos = 0; masterPos < 8; masterPos++)
{
posm = ((char)0x01) << masterPos;
masterNum = TIM_InitStruct->TIM_Selection_Master & posm;
if(masterNum == posm)
{
currentMChan[j]=masterPos;
if(masterPos == 0)
{
*TIM_reg.TMR[currentMChan[j]] = Ckm_Type | TIM_InitStruct->TIM_Trigger | TIM_InitStruct->TIM_Pulse_Edge | TIM_InitStruct->TIM_Mode | TIM_InitStruct->TIM_StartInt;
}
else
{
*TIM_reg.TMR[masterPos] = Ckm_Type |0x0800|TIM_InitStruct->TIM_Trigger | TIM_InitStruct->TIM_Pulse_Edge | TIM_InitStruct->TIM_Mode | TIM_InitStruct->TIM_StartInt;
}
*TIM_reg.TDR[currentMChan[j]] = TIM_InitStruct->TIM_Period[currentMChan[j]] -1;
*TIM_reg.TO &= ~(1 << masterPos);
*TIM_reg.TOE &= ~(1 << masterPos);
MISC->NFEN1 |= (1<<currentMChan[j]);
j++;
}
}
for(chanPos = 0; chanPos < 8; chanPos++)
{
pos = ((uint8_t)0x01) << chanPos;
chanNum = TIM_InitStruct->TIM_Channel & pos;
if(chanNum == pos)
{
*TIM_reg.TMR[chanPos] = Ckm_Type |TIM_Trigger_UseMaster_Int |TIM_Mode_PWM_Slave| TIM_InitStruct->TIM_Mode |TIM_InitStruct->TIM_StartInt;
*TIM_reg.TDR[chanPos] = TIM_InitStruct->TIM_Period[chanPos];
*TIM_reg.TO &= ~(1 << chanPos);
*TIM_reg.TOE |= (1 << chanPos);
*TIM_reg.TOM |= (1 << chanPos);
*TIM_reg.TOL &= ~(1 << chanPos);
}
}
*TIM_reg.TS |= TIM_InitStruct->TIM_Channel |TIM_InitStruct->TIM_Selection_Master;
}
else
{
for(chanPos = 0; chanPos < 8; chanPos++)
{
pos = ((uint8_t)0x01) << chanPos;
chanNum = TIM_InitStruct->TIM_Channel & pos;
if(chanNum == pos)
{
currentChan[i]=chanPos;
i++;
}
}
if(i == 1)
{
*TIM_reg.TDR[currentChan[0]] = TIM_InitStruct->TIM_Period[currentChan[0]] -1;
*TIM_reg.TT |= TIM_InitStruct->TIM_Channel;
*TIM_reg.TMR[currentChan[0]] = Ckm_Type | TIM_InitStruct->TIM_Trigger | TIM_InitStruct->TIM_Pulse_Edge | TIM_InitStruct->TIM_Mode | TIM_InitStruct->TIM_StartInt;
*TIM_reg.TO &= ~ TIM_InitStruct->TIM_Channel;
if(TIM_InitStruct->TIM_Mode == 0x0000)
{
*TIM_reg.TOE |= TIM_InitStruct->TIM_Channel;
}
else
{
*TIM_reg.TOE &= ~ TIM_InitStruct->TIM_Channel;
if(TIM_InitStruct->TIM_Mode == TIM_Mode_EventCount)
{
*TIM_reg.TMR[currentChan[0]] |= 0x1000;
}
if(TIM_InitStruct->TIM == TIM40)
{
MISC->NFEN1 |= TIM_InitStruct->TIM_Channel;
}
if(TIM_InitStruct->TIM == TIM41)
{
MISC->NFEN2 |= TIM_InitStruct->TIM_Channel;
}
if((TIM_InitStruct->TIM_Channel == 0x01 || TIM_InitStruct->TIM_Channel == 0x02) && (TIM_InitStruct->TIM == TIM40))
{
MISC->TIOS0 |= TIM_InitStruct->TIM4_Input;
if(TIM_InitStruct->TIM4_Input)
{
MISC->NFEN1 &= ~(TIM_InitStruct->TIM_Channel);
}
}
}
*TIM_reg.TS |= TIM_InitStruct->TIM_Channel;
}
else
{
return TIM_ERR;
}
}
return ret;
}
小结
- 当配置TIM41_CH1作为PWM输出时,再使用TIM41_CH0作为定时器时,PWM输出会受到影响,因此不能再使用TIM41_CH0,可以使用TIM41_CH2或者TIM41_CH3。