历史上的今天
今天是:2025年02月09日(星期日)
2020年02月09日 | MSP430定时器介绍
2020-02-09 来源:eefocus
MSP430定时器笔记
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
下一篇:msp430 学习经验总结
史海拾趣
|
IGBT负载短路下的几种后果 (1) 超过热极限:半导体的本征温度极限为250℃,当结温超过本征温度,器件将丧失阻断能力,IGBT负载短路时,由于短路电流时结温升高,一旦超过其热极限时,门级保护也相应失效. (2) 电流擎住效应:正常工作电流下,IGBT由于薄 ...… 查看全部问答> |
|
条码手持终端应用程序开发!!! 本人在条码行业有多年的工作经验,一直从事条码手持终端应用程序的开发 开发过多种设备: CASIO DT900,DT300,DTX10; Cipher 711 ; SYMBOL MC50,MC1000,PPT8800; Intermec 700系列 有需要的请联系本人 QQ:6 ...… 查看全部问答> |
|
急!!!如何在PC机上实现对单片机的控制(用VC++6.0编程) 小弟正在想弄一个在PC机上实现对单片机的控制,但不知道从哪个方面入手? 希望各位达人给予小弟一些指点.发个程序给小弟参考参考(用C语言编写的)… 查看全部问答> |
|
经历了很多推销的宣传,今天买了10片样品,准备把以前ATMEL8的东西都移植过来. 有几个问题,一直没搞明白: 1. STM8S103K3会不会象ATMEL那样,1000元就能把代码都读出来?STM8S103K3的 解密难度有多大? 2. 以前一直用ICC和KEIL开 ...… 查看全部问答> |
|
2812程序烧到片内flash中运行,能否用CCS和仿真器观察内部变量 2812程序烧到片内flash中运行,能否用CCS和仿真器观察内部变量, 调试电机程序,使用仿真器容易跑飞,希望能烧到flash中运行,同时也希望能像在ccs里仿真一样观察几个关键变量,听有的工程师说是能实现的,希望有能得到指点?… 查看全部问答> |
|
这是个试验程序,就是把整页写入同一个数据,,另外ID什么都可以读出来,,个人感觉数据是可以读出来的,,但读出来的全是FF,2112个FF后是64个0x15,我把读命令改错的话,读出来的是那个输入的数据,说明内部没把数据读出来,这是不是说明FF读出来 ...… 查看全部问答> |
|
在整个APF中基准电流的产生方法是核心环节,只有产生正确的基准电流信号才能很好的补偿谐波和无功电流。当只是补偿谐波电流时只需获取负载电流中的谐波分量即可,当补偿谐波及无功时除了要获取谐波电流信号外还需获取基波电流中的无功分量。基准电 ...… 查看全部问答> |




