打印

PIC32系列 定时器TMR-16位外部同步定时器的使用

[复制链接]
2409|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
1、PIC32参考资源

PIC32系列参考手册 中文版


使用特权

评论回复
沙发
guanjiaer|  楼主 | 2021-8-2 17:10 | 只看该作者
2、16位同步外部定时器方案说明

步骤1:TMR3产生固定频率的脉冲信号;

步骤2:TMR2设置为外部时钟输入;

步骤3:将TMR3产生的脉冲信号呈现到引脚电平变化上,并将引脚接入到TMR2的外部时钟输入引脚上;

步骤4:TMR2中断中设置为固定时间设置LED电平翻转;


使用特权

评论回复
板凳
guanjiaer|  楼主 | 2021-8-2 17:12 | 只看该作者
3、16位同步外部定时器Harmony3配置
1、定时器3配置分频系数为2,内部时钟源,定时时间为0.5ms,频率为1Khz;



2、定时器2配置分频系数为1,时钟源选择外部时钟源,时钟频率填写1000Hz,定时时间填写500ms;



3、组件配置完成后点击左侧的Generate Code按钮生成代码;



4、生成的代码与原始代码存在差异,需进行确认;



5、代码生成后需要的操作;

        1、添加定时器TMR3以及TMR2的启动;

        2、为TMR3中断服务函数中添加引脚电平翻转,产生脉冲信号用于提供外部时钟输入;

        3、在TMR2中断服务函数中添加LED电平翻转;

        4、外部接口中将TMR3输出引脚接入的TMR2时钟外部输入引脚;

6、编译运行将代码烧录到开发板中;

点击编译按钮,编译提示BUILD SUCCESSFUL,点击烧录,提示Programming/Verify complete,开发板上的LED灯闪烁。


使用特权

评论回复
地板
guanjiaer|  楼主 | 2021-8-2 17:13 | 只看该作者
4、工程配置分析
1、TMR3定时器工程配置



定时器TMR3主要用于产生外部时钟,我们将分频系数修改为2,时钟源选择内部时钟,那么定时器的时钟频率为40MhHz,我们使定时时间为0.5ms,也就是周期为1kHz。

我们在中断中将某个IO口电平翻转,用于产生TMR2需要的外部时钟,通过波形抓取如下所示,时间为0.5ms,频率为1kHz;



2、TMR2工程配置



定时器TMR2主要是以外部频率为基准,进行计数。我们设置分频系数为1,时钟源选择外部时钟,外部时钟频率填写1000Hz,定时时间我们设置为500ms。

也就是说以1ms的频率,计数500次为500ms。这个时候在TMR2的中断服务函数中设置LED灯翻转,那么翻转的时间就是500ms。


使用特权

评论回复
5
guanjiaer|  楼主 | 2021-8-2 17:14 | 只看该作者
5、具体代码分析
定时器TMR3

//定时器TMR3初始化
void TMR3_Initialize(void)
{
    /* Disable Timer */
    T3CONCLR = _T3CON_ON_MASK; //禁止定时器,清零ON控制位

    /*
    SIDL = 0 //空闲模式停止位
    TCKPS =1 //预分频设置
    T32   = 0 //32定时器
    TCS = 0 //时钟源选择,内部时钟源或外部时钟源
    */
    T3CONSET = 0x10;  //TxCON与定时器相关的 16 位控制寄存器

    /* Clear counter */
    TMR3 = 0x0; //TMRx 16位定时器计数器寄存器

    /*Set period */
    PR3 = 19999U; //PRx与定时器相关的 16 位周期寄存器

    /* Enable TMR Interrupt */
    IEC0SET = _IEC0_T3IE_MASK; //TxIE中断允许控制位在IEC0中断寄存器中
}

//开启定时器TMR3
void TMR3_Start(void)
{
    T3CONSET = _T3CON_ON_MASK; //TxIF中断标志状态位在IFS0 中断寄存器中;
}

//关闭定时器TMR3
void TMR3_Stop (void)
{
    T3CONCLR = _T3CON_ON_MASK; //TxIF中断标志状态位在IFS0 中断寄存器中;
}

//设置周期寄存器
void TMR3_PeriodSet(uint16_t period)
{
    PR3  = period; //PRx与定时器相关的16位周期寄存器
}

//获取周期寄存器
uint16_t TMR3_PeriodGet(void)
{
    return (uint16_t)PR3; //PRx与定时器相关的16位周期寄存器
}

//获取计数值
uint16_t TMR3_CounterGet(void)
{
    return (uint16_t)(TMR3); //TMRx 16位定时器计数器寄存器
}

//获取定时器频率
uint32_t TMR3_FrequencyGet(void)
{
    return (40000000); //返回定时器的时钟频率
}

//定时器3中断服务函数
void TIMER_3_InterruptHandler (void)
{
    uint32_t status  = 0U;
    status = IFS0bits.T3IF;
    IFS0CLR = _IFS0_T3IF_MASK;

    /*可在这添加中断处理内容*/
    GPIO_RB1_Toggle();

    if((tmr3Obj.callback_fn != NULL))
    {
        tmr3Obj.callback_fn(status, tmr3Obj.context);
    }
}

//中断使能
void TMR3_InterruptEnable(void)
{
    IEC0SET = _IEC0_T3IE_MASK; //TxIE中断允许控制位在IEC0中断寄存器
}

//禁止中断
void TMR3_InterruptDisable(void)
{
    IEC0CLR = _IEC0_T3IE_MASK; //TxIE中断允许控制位在IEC0中断寄存器
}

//
void TMR3_CallbackRegister(TMR_CALLBACK callback_fn, uintptr_t context)
{
    /* Save callback_fn and context in local memory */
    tmr3Obj.callback_fn = callback_fn;
    tmr3Obj.context = context;
}

//中断服务函数,在interrupts.c中,调用TIMER_3_InterruptHandler
void __ISR(_TIMER_3_VECTOR, ipl1SOFT) TIMER_3_Handler (void)
{
    TIMER_3_InterruptHandler();
}


使用特权

评论回复
6
guanjiaer|  楼主 | 2021-8-2 17:15 | 只看该作者
定时器TMR2

//定时器TMR2初始化
void TMR2_Initialize(void)
{
    /* Disable Timer */
    T2CONCLR = _T2CON_ON_MASK; //禁止定时器,清零ON控制位

    /*
    SIDL = 0 //空闲模式停止位
    TCKPS =0 //预分频设置
    T32   = 0 //32定时器
    TCS = 1 //时钟源选择,内部时钟源或外部时钟源
    */
    T2CONSET = 0x2;  //TxCON与定时器相关的 16 位控制寄存器

    /* Clear counter */
    TMR2 = 0x0; //TMRx 16位定时器计数器寄存器

    /*Set period */
    PR2 = 499U; //PRx与定时器相关的 16 位周期寄存器

    /* Enable TMR Interrupt */
    IEC0SET = _IEC0_T2IE_MASK; //TxIE中断允许控制位在IEC0中断寄存器中
}

//开启定时器TMR2
void TMR2_Start(void)
{
    T2CONSET = _T2CON_ON_MASK; //TxIF中断标志状态位在IFS0 中断寄存器中;
}

//关闭定时器
void TMR2_Stop (void)
{
    T2CONCLR = _T2CON_ON_MASK; //TxIF中断标志状态位在IFS0 中断寄存器中;
}

//设置周期寄存器
void TMR2_PeriodSet(uint16_t period)
{
    PR2  = period; //PRx与定时器相关的16位周期寄存器
}

//获取周期寄存器
uint16_t TMR2_PeriodGet(void)
{
    return (uint16_t)PR2;  //PRx与定时器相关的16位周期寄存器
}

//获取计数值
uint16_t TMR2_CounterGet(void)
{
    return (uint16_t)(TMR2); //TMRx 16位定时器计数器寄存器
}

//获取定时器频率
uint32_t TMR2_FrequencyGet(void)
{
    return (1000); //返回定时器的时钟频率
}

//定时器中断服务函数
void TIMER_2_InterruptHandler (void)
{
    uint32_t status  = 0U;
    status = IFS0bits.T2IF;
    IFS0CLR = _IFS0_T2IF_MASK;

/*可在这添加中断处理内容*/
GPIO_RB0_Toggle();

    if((tmr2Obj.callback_fn != NULL))
    {
        tmr2Obj.callback_fn(status, tmr2Obj.context);
    }
}

//中断使能
void TMR2_InterruptEnable(void)
{
    IEC0SET = _IEC0_T2IE_MASK; //TxIE中断允许控制位在IEC0中断寄存器
}

//禁止中断
void TMR2_InterruptDisable(void)
{
    IEC0CLR = _IEC0_T2IE_MASK; //TxIE中断允许控制位在IEC0中断寄存器
}

//
void TMR2_CallbackRegister(TMR_CALLBACK callback_fn, uintptr_t context)
{
    /* Save callback_fn and context in local memory */
    tmr2Obj.callback_fn = callback_fn;
    tmr2Obj.context = context;
}

//中断服务函数,在interrupts.c中,调用TIMER_2_InterruptHandler
void __ISR(_TIMER_2_VECTOR, ipl1SOFT) TIMER_2_Handler (void)
{
    TIMER_2_InterruptHandler();
}


使用特权

评论回复
7
guanjiaer|  楼主 | 2021-8-2 17:16 | 只看该作者
中断优先级配置

//中断优先级设置,设置TMR2以及TMR3优先级
void EVIC_Initialize( void )
{
    INTCONSET = _INTCON_MVEC_MASK;
    /* Set up priority and subpriority of enabled interrupts */
    IPC2SET = 0x4 | 0x0;  /* TIMER_2:  Priority 1 / Subpriority 0 */
    IPC3SET = 0x4 | 0x0;  /* TIMER_3:  Priority 1 / Subpriority 0 */
}


使用特权

评论回复
8
guanjiaer|  楼主 | 2021-8-2 17:18 | 只看该作者
6、16位同步外部时钟计数器说明
同步外部时钟计数器操作提供了以下功能:

• 对周期性或非周期性脉冲进行计数

• 使用外部时钟作为定时器的时基

A 类和 B 类定时器都可工作于同步外部时钟计数器模式。在该模式下,定时器的输入时钟源是施加于 TxCK 引脚上的外部时钟。选择它的方法是将时钟源控制位 TCS 置 1 (TxCON<1> = 1)。B 类定时器会自动提供外部时钟源同步;但是,A 类定时器不会,并要求外部时钟同步位 TSYNC(T1CON<2>)置 1 (= 1)。

依靠同步外部时钟源工作的 A 类或 B 类定时器在 Sleep(休眠)模式下不工作,因为同步电路在Sleep(休眠)模式下被禁止。

TCLK引脚分别为RC1、RC2、RC3、RC4、RC14,需要注意。




使用特权

评论回复
9
guanjiaer|  楼主 | 2021-8-2 17:19 | 只看该作者
7、16位同步外部时钟计数器初始化步骤
1. 清零 ON 控制位 (TxCON<15> = 0)以禁止定时器。

2. 将 TCS 控制位置 1 (TxCON<1> = 1)以选择外部时钟源。

3. 如果使用了 A 类定时器,则将 TSYNC 控制位置 1 (T1CON<2> = 1)以使能时钟同步。

4. 选择所需的定时器输入时钟预分频比。

5. 装载 / 清零定时器寄存器 TMRx。

6. 如果使用周期匹配:

        a) 将所需的 16 位匹配值装入周期寄存器 PRx。

7. 如果使用了中断:

        a) 清零 IFSx 寄存器中的 TxIF 中断标志位。

        b) 在 IPCx 寄存器中配置中断优先级和子优先级。

        c) 将 IECx 寄存器中的 TxIE 中断允许位置 1。

8. 将 ON 控制位置 1 (TxCON<15> = 1)以使能定时器。


使用特权

评论回复
10
guanjiaer|  楼主 | 2021-8-2 17:20 | 只看该作者
8、实验验证

点击编译按钮,编译提示BUILD SUCCESSFUL,点击烧录,提示Programming/Verify complete,开发板上的LED灯闪烁。


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

77

主题

4116

帖子

2

粉丝