1.定时器参数
1.1 基本定时器
typedef enum
{
TIMER_A0 ,
TIMER_A1 ,
TIMER_A2 ,
TIMER_B0 ,
TIMER_NUM ,
}TIMERn; //定时器模块
1.2 定时器通道引脚、时钟选择
const GPIO_PIN TIMER_CHANEL_PIN[TIMER_NUM][TIMER_CH_NUM]=
{// CH0 CH1 CH2 CH3 CH4 CH5 CH6
{{P1,1},{P1,2},{P1,3},{P1,4},{P1,5}}, //TIMER_A0
{{P1,7},{P2,0},{P2,1}}, //TIMER_A1
{{P2,3},{P2,4},{P2,5}}, //TIMER_A2
{{P5,6},{P5,7},{P7,4},{P7,5},{P7,6},{P3,5},{P3,6}} //TIMER_B0
};//通道引脚
const GPIO_PIN TIMER_CLK_PIN[TIMER_NUM] =
{
{P1,0},//TIMER_A0----ACLK----
{P1,6},//TIMER_A1----ACLK----
{P2,2},//TIMER_A2----SMCLK----
{P7,7} //TIMER_B0----MCLK----
};//外部时钟输入引脚
2.定时器功能
2.1 实现基本定时
extern STATUS TIMER_Interval_Us (TIMERn, uint32_t us); //初始化一个us级的定时中断
#define TIMER_Interval_Ms(timer,ms) TIMER_Interval_Us(timer,(uint32_t)ms*1000)
2.1.1 中断向量设置传参
/*******************************************************************************
* 函数名称:Set_Vector_Handler(VECTORn vector,__interrupt void pfunc_handler(void))
* 功能说明:设置中断向量地址
* 参数说明:
VECTORn vector :中断向量(枚举变量,见.h文件)
__interrupt void pfunc_handler(void) : 中断服务函数
* 函数返回:无
* 使用示例:Set_Vector_Handler(VECTOR_PORT1,GPIO_IRQ_Handler); //设置PPORT1中断服务函数为GPIO_IRQ_Handler,需要先定义中断服务函数,另外最好先设置中断向量,再开启中断
********************************************************************************/
void Set_Vector_Handler(VECTORn vector, __interrupt void pfunc_handler(void))
{
if(SYSX->RIVECT == DISABLE) //如果没有设置中断向量表到RAM,则设置
{
Set_VectorTable_To_RAM(); //设置中断向量表到RAM
}
//此处若有警告可忽略
__VECTOR_RAM[vector] = (ISR_TYPE)pfunc_handler; //设置该中断向量地址
}
2.1.2 定时中断
/*******************************************************************************
* 函数名称:TIMER_Interval_Us(TIMERn timer,uint32_t us)
* 功能说明:定时器定时初始化(单位:us)
* 参数说明:TIMERn timer :定时器模块
uint32_t us : 定时时间
* 函数返回:不成功则返回ERROR,成功则返回SUCCESS
* 使用例程:TIMER_Interval_Us(TIMER_B0,2500); //TB定时间隔2.5ms中断
********************************************************************************/
STATUS TIMER_Interval_Us(TIMERn timer,uint32_t us)
{
#ifdef DELAY_TIMER
ASSERT((timer != DELAY_TIMER),
"TIMER_Interval_Us",
"定时器已经设置为默认延时功能,不能再作为其他功能使用"); //不允许这种情况下还宏定义该定时器作为延时所用的定时器,请在system.h里修改DELAY_TIMER宏定义
#endif
TIMERX[timer]->CLR = BIT_SET;//置位
TIMERX[timer]->SSEL = TIMER_SSEL_SMCLK;
TIMERX[timer]->ID = 0u;//分频系数清零
//计数值
uint32_t Counter_Value = (uint32_t)(us * g_sClock.SMCLK.fMHZ);
while(Counter_Value > 65536)
{
TIMERX[timer]->ID ++;
Counter_Value >>= 1;
if((TIMERX[timer]->ID == 3u) && (Counter_Value > 65536)) //这个时候意味得选择更低频率的时钟了
{
if(TIMERX[timer]->SSEL == TIMER_SSEL_ACLK) //如果时钟已经是最低的ACLK了,那么意味着设置的频率太低了,失败返回ERROR
{
return ERROR;
}
//更换为更低的ACLK,从新配置
TIMERX[timer]->SSEL = TIMER_SSEL_ACLK;
TIMERX[timer]->ID = 0u;
Counter_Value = (uint32_t)(us * g_sClock.ACLK.fMHZ);
continue;
}
}
if(Counter_Value <= 1)//出现这种情况,说明频率不合适
{
return ERROR;
}
TIMERX[timer]->CCR[0] = (uint16_t)(Counter_Value - 1u);//为什么要减一??因为TAR/TBR计数器从CCR0变化到0还有一个计数周期
TIMERX[timer]->CCTL[0].CAPMODE = RESET;//比较模式
TIMERX[timer]->IE = RESET; //关闭溢出中断
TIMERX[timer]->CCTL[0].IE = RESET; //关闭通道中断
TIMERX[timer]->MC = TIMER_MC_UP; //增计数模式
return SUCCESS;
}
2.1.3 初始化实例
DisableInterrupts(); //禁止总中断
Set_Vector_Handler(VECTOR_TIMER0_A0,TIMER_TA0_IRQ_Handler); //设置中断向量,最好先设置中断向量,在开启中断
TIMER_Interval_Ms(TIMER_A0,200);//初始化一个200ms的定时中断
//TIMER_Interval_Us(TIMER_A0,1000000); //初始化一个1000ms的定时中断,不要写为1000*1000,否则会提示超出范围
TIMER_ITConfig (TIMER_A0,TIMER_CCR0_IRQn,ENABLE);
EnableInterrupts();
__interrupt void TIMER_TA0_IRQ_Handler()
{
LED_Turn(LED2); //黄灯
//FLAG_10MS=1;
}
2.2 PWM输出
2.2.1 PWM计数模式
#define TIMER_MC_STOP (0) /* Timer A mode control: 0 - Stop */
#define TIMER_MC_UP (1) /* Timer A mode control: 1 - Up to CCR0 */
#define TIMER_MC_CONTINUOUS (2) /* Timer A mode control: 2 - Continuous up */
#define TIMER_MC_CONTINOUS (2) /* Legacy define */
#define TIMER_MC_UPDOWN (3) /* Timer A mode control: 3 - Up/Down */
2.2.2 PWM输出模式
typedef enum
{
TIMER_PWM_OUTMOD0 ,
TIMER_PWM_OUTMOD1 ,
TIMER_PWM_OUTMOD2 ,
TIMER_PWM_OUTMOD3 ,
TIMER_PWM_OUTMOD4 ,
TIMER_PWM_OUTMOD5 ,
TIMER_PWM_OUTMOD6 ,
TIMER_PWM_OUTMOD7 ,
}TIMER_PWM_OUTMODn; //PWM波输出波形
各种计数情况下pwm输出模式
2.3 pwm输出
2.3.1 pwm初始化
/*******************************************************************************
* 函数名称:TIMER_PWM_MultiChannel_Init(TIMERn timer, uint32_t fre, uint8_t ChannelNum,...)
* 功能说明:定时器PWM输出初始化(可以多个通道同时初始化)
* 参数说明:TIMERn timer :定时器模块
uint32_t fre :频率
uint8_t ChannelNum :要初始化的通道数
... :初始化的通道
* 函数返回:不成功则返回ERROR,成功则返回SUCCESS
********************************************************************************/
STATUS TIMER_PWM_MultiChannel_Init(TIMERn timer, uint32_t fre, uint8_t ChannelNum,...)
{
#ifdef DELAY_TIMER
ASSERT((timer != DELAY_TIMER),
"TIMER_PWM_MultiChannel_Init",
"定时器已经设置为默认延时功能,不能再作为其他功能使用"); //不允许这种情况下还宏定义该定时器作为延时所用的定时器,请在system.h里修改DELAY_TIMER宏定义
#endif
ASSERT((timer==TIMER_A0&&ChannelNum<=TIMER_CH4)
||(timer==TIMER_A1&&ChannelNum<=TIMER_CH2)
||(timer==TIMER_A2&&ChannelNum<=TIMER_CH2)
||(timer==TIMER_B0&&ChannelNum<=TIMER_CH6),
"TIMER_PWM_MultiChannel_Init",
"定时器通道参数超出范围!"); //断言检测输入参数*/
va_list ap;
va_start(ap,ChanelNum);
for(int i=0;i < ChannelNum;i++) //根据初始化的通道数,逐一初始化通道
{
TIMER_CHn ch = va_arg(ap, TIMER_CHn); //读取要初始化的通道
if((ch == TIMER_CH0) || (ch >= TIMER_CH_NUM)) //判断通道值是否合理
{
return ERROR; //不合理返回ERROR
}
//初始化端口
GPIO_Init(TIMER_CHANEL_PIN[timer][ch].Port,TIMER_CHANEL_PIN[timer][ch].Pin,GPO|SEL);
//初始化占空比及输出波形
TIMERX[timer]->CCR[ch] = 0u;
TIMERX[timer]->CCTL[ch].IE = RESET; //关闭通道中断
TIMERX[timer]->CCTL[ch].OUTMOD = DEFAULT_PWM_OUTMOD; //输出波形设置
TIMERX[timer]->CCTL[ch].CAPMODE = RESET; //比较模式
}
va_end(ap);
return TIMER_PWM_SetFrequency(timer,fre);
}
设置频率函数
/*******************************************************************************
* 函数名称:TIMER_PWM_SetFrequency(TIMERn timer,uint32_t fre)
* 功能说明:定时器PWM频率设置(注意这里没有更改各个通道的占空比,所以修改频率后占空比变了,需要从新设置占空比)
* 参数说明:TIMERn timer :定时器模块
uint32_t fre :频率
* 函数返回:不成功则返回ERROR,成功则返回SUCCESS
* 使用例程:TIMER_PWM_SetFrequency(TIMER_B0,1000); //将定时器B输出频率修改为1000Hz
********************************************************************************/
STATUS TIMER_PWM_SetFrequency(TIMERn timer,uint32_t fre)
{
if(fre == 0u)
{
TIMERX[timer]->MC = TIMER_MC_STOP; //暂停输出PWM波
return SUCCESS;
}
TIMERX[timer]->CLR = BIT_SET;
TIMERX[timer]->SSEL = TIMER_SSEL_SMCLK; //先选择时钟源为SMCLK
TIMERX[timer]->ID = 0u; //分频系数清零
//时钟大小
uint32_t Counter_Value = g_sClock.SMCLK.nHZ/fre; //计算计数值
while(Counter_Value > 65536u) //这里不是0xffff,因为后面会-1,所以是(0xffff+1)=65536
{ //分频一次
TIMERX[timer]->ID ++;
Counter_Value >>= 1;
if((TIMERX[timer]->ID == 3u) && (Counter_Value > 65536)) //这个时候意味得选择更低频率的时钟了
{
if(TIMERX[timer]->SSEL == TIMER_SSEL_ACLK) //如果时钟已经是最低的ACLK了,那么意味着设置的频率太低了,失败返回ERROR
{
return ERROR;
}
//更换为更低的ACLK,从新配置
TIMERX[timer]->SSEL = TIMER_SSEL_ACLK;
TIMERX[timer]->ID = 0u;
Counter_Value = g_sClock.ACLK.nHZ/fre;
continue;
}
}
if(Counter_Value <= 1)//出现这种情况,说明频率不合适
{
return ERROR;
}
TIMERX[timer]->CCR[0] = (uint16_t)(Counter_Value - 1u);
//为什么要减一??因为TAR/TBR计数器从CCR0变化到0还有一个计数周期
TIMERX[timer]->IE = RESET; //关闭中断
//TIMERX[timer]->MC = TIMER_MC_UP; //增计数模式
TIMERX[timer]->MC = TIMER_MC_UPDOWN; //增减计数模式
return SUCCESS;
}
2.3.2 使用例程:
实例一:(使用函数初始化时需要输入初始化通道数,初始化通道数可以为0,如:
TIMER_PWM_MultiChannel_Init(TIMER_A0, 1000, 0);)
TIMER_PWM_MultiChannel_Init(TIMER_A0, 1000, 3, TIMER_CH1, TIMER_CH2, TIMER_CH4);
//定时器TIMER_A0初始化输出PWM波,频率为1000Hz,初始化3个通道,分别是:TIMER_CH1,TIMER_CH2,TIMER_CH4
实例二:(使用宏定义初始化时不需要输入初始化通道数)
TIMER_PWM_Init(TIMER_B0,1000,TIMER_CH1,TIMER_CH2,TIMER_CH3,TIMER_CH4,TIMER_CH5,TIMER_CH6);
//定时器TIMER_B0初始化输出PWM波,频率为1000Hz,初始化6个通道:TIMER_CH1,TIMER_CH2,TIMER_CH3,TIMER_CH4,TIMER_CH5,TIMER_CH6
2.3.3 初始化实例
TIMER_PWM_Init(TIMER_A0,66000, TIMER_CH1, TIMER_CH2, TIMER_CH3, TIMER_CH4);
TIMER_PWM_SetChannelDuty(TIMER_A0,TIMER_CH1,200);//设置某一个定时器某一个通道的占空比
TIMER_PWM_SetChannelDuty(TIMER_A0,TIMER_CH2,400);//设置某一个定时器某一个通道的占空比
TIMER_PWM_SetChannelDuty(TIMER_A0,TIMER_CH3,600);//设置某一个定时器某一个通道的占空比
TIMER_PWM_SetChannelDuty (TIMER_A0,TIMER_CH4,800);//设置某一个定时器某一个通道的占空比
TIMER_PWM_MultiChannel_Init(TIMER_B0, 33000, 1, TIMER_CH5);
//TIMER_PWM_Init(TIMER_B0, 1, TIMER_CH5);
TIMER_PWM_SetChannelDuty (TIMER_B0,TIMER_CH5,500); //设置某一个定时器某一个通道的占空比
GPIO_PinRemapConfig(P4,7,GPIO_Remap_TB0CCR5A); //GPIO端口重映射
2.4 互补pwm波形
//定时器A0,频率1K,占空比为0,初始化4个通道,分别是:TIMER_CH1(P1.2), TIMER_CH2(P1.3), TIMER_CH3(P1.4), TIMER_CH4(P1.5)
//TIMER_PWM_MultiChannel_Init(TIMER_A0,1000, 4, TIMER_CH1, TIMER_CH2, TIMER_CH3, TIMER_CH4);
TIMER_PWM_Init(TIMER_A0,66000, TIMER_CH1, TIMER_CH2, TIMER_CH3, TIMER_CH4);
TIMERX[TIMER_A0]->CCTL[2].OUTMOD = TIMER_PWM_OUTMOD2;
TIMERX[TIMER_A0]->CCTL[3].OUTMOD = TIMER_PWM_OUTMOD6;
TIMERX[TIMER_A0]->MC = TIMER_MC_UP;//增计数模式
TIMER_PWM_SetChannelDuty(TIMER_A0,TIMER_CH1,200);//设置某一个定时器某一个通道的占空比
TIMER_PWM_SetChannelDuty(TIMER_A0,TIMER_CH2,400);//设置某一个定时器某一个通道的占空比
TIMER_PWM_SetChannelDuty(TIMER_A0,TIMER_CH3,600);//设置某一个定时器某一个通道的占空比
TIMER_PWM_SetChannelDuty(TIMER_A0,TIMER_CH4,800);//设置某一个定时器某一个通道的占空比
2.5 带死区的pwm输出
//定时器A0,频率1K,占空比为0,初始化4个通道,分别是:TIMER_CH1(P1.2), TIMER_CH2(P1.3), TIMER_CH3(P1.4), TIMER_CH4(P1.5)
//TIMER_PWM_MultiChannel_Init(TIMER_A0,1000, 4, TIMER_CH1, TIMER_CH2, TIMER_CH3, TIMER_CH4);
TIMER_PWM_Init(TIMER_A0,66000, TIMER_CH1, TIMER_CH2, TIMER_CH3, TIMER_CH4);
TIMERX[TIMER_A0]->CCTL[2].OUTMOD = TIMER_PWM_OUTMOD2;
TIMERX[TIMER_A0]->CCTL[3].OUTMOD = TIMER_PWM_OUTMOD6;
TIMERX[TIMER_A0]->MC = TIMER_MC_UPDOWN; //增减计数模式
TIMER_PWM_SetChannelDuty (TIMER_A0,TIMER_CH1,200);//设置某一个定时器某一个通道的占空比
TIMER_PWM_SetChannelDuty (TIMER_A0,TIMER_CH2,400);//设置某一个定时器某一个通道的占空比
TIMER_PWM_SetChannelDuty (TIMER_A0,TIMER_CH3,600);//设置某一个定时器某一个通道的占空比
TIMER_PWM_SetChannelDuty (TIMER_A0,TIMER_CH4,800);//设置某一个定时器某一个通道的占空比
3.定时捕获
3.1 捕获过程
3.2 计数初始化
/*******************************************************************************
* 函数名称:TIMER_Pluse_Init (TIMERn timer)
* 功能说明:定时器脉冲计数初始化
* 参数说明:TIMERn timer :定时器模块
* 函数返回:不成功则返回ERROR,成功则返回SUCCESS
* 使用例程:TIMER_Pluse_Init (TIMER_A1); //定时器TA1初始化为脉冲计数功能
********************************************************************************/
STATUS TIMER_Pluse_Init (TIMERn timer)
{
#ifdef DELAY_TIMER
ASSERT((timer != DELAY_TIMER),
"TIMER_Pluse_Init",
"定时器已经设置为默认延时功能,不能再作为其他功能使用"); //不允许这种情况下还宏定义该定时器作为延时所用的定时器,请在system.h里修改DELAY_TIMER宏定义
#endif
//端口设置为输入方向//选择第二功能
GPIO_Init(TIMER_CLK_PIN[timer].Port,TIMER_CLK_PIN[timer].Pin,GPI|SEL);
TIMERX[timer]->CLR = BIT_SET;
TIMERX[timer]->SSEL = TIMER_SSEL_INCLK; //时钟源选择为外部输入
TIMERX[timer]->ID = 0u; //不分频
TIMERX[timer]->MC = TIMER_MC_CONTINOUS; //连续计数模式
TIMERX[timer]->IE = RESET; //禁止溢出中断
return SUCCESS;
}
3.3 中断处理函数
/*******************************************************************************
* 函数名称:TIMER_ITConfig (TIMERn timer,TIMER_IRQn irqn,STATUS ITState)
* 功能说明:设置是否使能TIMER的某一个中断
* 参数说明:TIMERn timer :定时器模块
TIMER_IRQn irqn :中断事件
STATUS ITState :是否使能中断
* 函数返回:无
* 使用例程:TIMER_ITConfig (TIMAER_A1,TIMER_CCR0_IRQn,ENABLE); //使能定时器1通道0中断,即定时中断
********************************************************************************/
void TIMER_ITConfig (TIMERn timer,TIMER_IRQn irqn,STATUS ITState)
{
if(irqn == TIMER_OverFlow_IRQn)
{
TIMERX[timer]->IE = ITState;
}
else
{
TIMERX[timer]->CCTL[irqn].IE = ITState;
}
}
3.4 计数值获取
/*******************************************************************************
* 函数名称:TIMER_Pluse_GetValue(TIMERn timer,uint16_t overflowTime)
* 功能说明:定时器脉冲计数值获取
* 参数说明:TIMERn timer :定时器模块
uint16_t overflowTime :计数器溢出次数
* 函数返回:定时器脉冲计数值
* 使用例程:
int32 pulse = TIMER_Pluse_GetValue(TIMER_A1,0); //在没有发生溢出的情况下读取脉冲个数
TIMER_Pluse_Clear (TIMER_A1); //读取后应该要清零
********************************************************************************/
float TIMER_Pluse_GetValue(TIMERn timer,uint16_t overflowTime)
{
return (TIMERX[timer]->R + (overflowTime*65536u));
}
3.5 初始化实例
//设置中断向量,最好先设置中断向量,在开启中断
Set_Vector_Handler(VECTOR_TIMER0_A0,TIMER_TA0_IRQ_Handler);
TIMER_Interval_Ms(TIMER_A0,1000); //初始化一个1000ms的定时中断 1s定时
TIMER_ITConfig (TIMER_A0,TIMER_CCR0_IRQn,ENABLE); //使能TIMER的某一个中断
__interrupt void TIMER_TA0_IRQ_Handler()
{
//读取脉冲数
PulseValue = TIMER_Pluse_GetValue(TIMER_A1,overflowTime);
overflowTime=0; //清除溢出次数
TIMER_Pluse_Clear (TIMER_A1);
}
//设置中断向量,最好先设置中断向量,在开启中断
Set_Vector_Handler(VECTOR_TIMER1_A1,TIMER_TA1_IRQ_Handler);
TIMER_Pluse_Init (TIMER_A1); //定时器A1用作脉冲计数,P1.6,默认以开启溢出中断
TIMER_ITConfig (TIMER_A1,TIMER_OverFlow_IRQn,ENABLE); //使能TIMER的某一个中断
__interrupt void TIMER_TA1_IRQ_Handler()
{
overflowTime++;
}
4.计时功能
Set_Vector_Handler(VECTOR_TIMER0_B1,TIMER_TB0_IRQ_Handler); //设置中断向量,最好先设置中断向量,在开启中断
TIMER_Timer_Init (TIMER_B0);//计时功能初始化
TIMER_ITConfig (TIMER_B0,TIMER_OverFlow_IRQn,TRUE);
TIMER_Timer_Start (TIMER_B0);//计时功能启动
TIMER_Delay_Ms (TIMER_A0,50); //延时500MS
TIMER_Timer_Stop (TIMER_B0); //计时功能停止,返回计数值
time = TIMER_Timer_GetTime_Us(TIMER_B0, overflowTime); //读取计时时间(单位:US)
__interrupt voidTIMER_TB0_IRQ_Handler()
{
LED_Turn(LED1); //指示灯闪烁
if(TIMER_GetITStatus(TIMER_B0,TIMER_OverFlow_IRQn) == TRUE)//如果溢出
{
overflowTime++; //溢出值加1
TIMER_ClearITPendingBit(TIMER_B0,TIMER_OverFlow_IRQn); //清除TIMER的某一个中断标志
}
}
上一篇:MSP430中断参数
下一篇:MSP430时钟定性分析
推荐阅读最新更新时间:2024-03-16 16:25
设计资源 培训 开发板 精华推荐
- 直播已结束|Molex 和 TTI 更小型、高速、可靠的连接器推动物联网应用的新发展
- 人人都爱易电源——转发有礼!
- 逛东芝电子在线展会,上百份礼品等您拿!
- 【EEWORLD第二十三届】2011年02月社区明星人物揭晓!
- 有奖直播|大唐恩智浦半导体 | 电池管理芯片方案设计和注意事项
- Maxim 有奖直播:支持工业系统的集成数字IO技术
- 直播已结束【使用 TI 低成本 MSPM0 MCU 快速开发 – 生态详解系列之二】(9:45开始入场)
- 阅读是德科技 Power Supply、汽车电子精彩专题,让您的设计更精准!参与答题赢好礼!
- phyBOARD-i.MX 8M Plus 开发板来袭 免费申请进行时!