1、PIC32参考资源

PIC32系列参考手册 中文版  链接地址:PIC32系列参考手册 第14章 定时器(https://download.csdn.net/download/Huangtop/20299476?spm=1001.2014.3001.5503)

image.png

2、使用Harmony3配置定时器生成代码

1、启动MPLAB Harmony3 Configurator组件;

image.png

 2、选择Harmony路径,不用管,按照给定的就可以,点击Launch;

image.png

3、选择器件库和CMSIS组件,按照给定的就可以,点击Launch;

image.png

4、启动后界面组件内容如下,左侧为可用的功能组件,右侧为项目功能图形显示;

image.png

5、在左侧的列表中打开Peripherals,选择TMR下的TMR2,也就是定时器2,将其拖入右侧的界面中;

image.png

6、拖入后右侧界面显示如下,可以看到右侧多了一个TMR2组件;

image.png

7、点击组件,右侧Configuration Options显示组件信息,此时可按照需求进行组件配置,图中的配置为,分频系数为2,16位定时器模式,时钟源使用内部时钟,定时时间为1ms,在空闲模式下继续工作;

image.png

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

image.png

9、点击后会有生成的信息需要确认,是否需要修改;

image.png

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

        1、启动定时器;

在初始化完成后启动定时器;

TMR2_Start();

        2、添加中断任务内容;

        在plib_tmr2.c的TIMER_2_InterruptHandler函数中添加内容

uint16_t u16Counter=0;
void TIMER_2_InterruptHandler (void)
{
    uint32_t status  = 0U;
    status = IFS0bits.T2IF;
    IFS0CLR = _IFS0_T2IF_MASK;
 
    if(u16Counter<500)
    {
        u16Counter++;
    }
    else
    {
        u16Counter=0;
        GPIO_RB0_Toggle();
    }
 
    if((tmr2Obj.callback_fn != NULL))
    {
        tmr2Obj.callback_fn(status, tmr2Obj.context);
    }
}

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

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

image.png

3、工程代码分析

1、TMR2 Configuration Options配置分析

image.png

Enable Interrupts?

使能中断服务,勾选该项后,会生成中断相关的代码及函数;

在plib_tmr2.c文件中

初始化完成后使能中断:IEC0SET = _IEC0_T2IE_MASK;

void TIMER_2_InterruptHandler (void)

void TMR2_InterruptEnable(void)

void TMR2_InterruptDisable(void)

void TMR2_CallbackRegister(TMR_CALLBACK callback_fn, uintptr_t context)

在interrupt.c文件中生成中断服务函数

void __ISR(_TIMER_2_VECTOR, ipl1SOFT) TIMER_2_Handler (void)

在plib_evic.c文件中的void EVIC_Initialize( void )函数增加中断优先级设置

IPC2SET = 0x4 | 0x0; /* TIMER_2: Priority 1 / Subpriority 0 */

Select Prescaler

选择分频系数,分频系数修改后会影响计时时间

在初始化时,TCKPS会变化,即T2CONSET;PR2也会变化;

uint32_t TMR2_FrequencyGet(void)函数会返回计时频率;

32-Bit Timer Mode Select Bit

可选Odd numbered and even numbered timers form separate 16-bit timers奇数和偶数定时器形成单独的16位定时器

以及Odd numbered and even numbered timers form a 32-bit timer奇数和偶数定时器组成一个32位定时器

T32位为32位定时器判断,32位定时器中断控制在Slave定时器中

image.png

Select Timer Clock Frequency选择时钟源;

可选择Internal peripheral clock或External clock from TxCK pin

选择外部时钟源时需要指定时钟频率

TCS 位为时钟选择位

Timer Clock Frequency 时钟频率,计算得到,是分频后得到的值,定时器时钟;

Timer Period Unit 为定时器时间单位,可选millisecond、microsecond、nanosecond;也就是毫秒、微秒以及纳秒;

image.png

Time为计时时间,与上面的单位结合使用,Period Register为周期寄存器数值,通过时间计算得到;

Stop in Idle Mode bit停止在空闲模式位,可选Continue operation even in Idle mode(空闲模式下继续)或Discontinue operation when device enters Idle mode(当设备进入空闲模式时停止)

image.png

该位影响SIDL位

SIDL :空闲模式停止位

1 = 在器件进入 Idle (空闲)模式时停止工作;0 = 即使在 Idle (空闲)模式下仍继续工作

2、具体代码分析

//定时器初始化函数
void TMR2_Initialize(void)
{
    /* Disable Timer */
    T2CONCLR = _T2CON_ON_MASK; //禁止定时器,清零ON控制位
 
    /*
    SIDL = 0 //空闲模式停止位
    TCKPS =1 //预分频设置
    T32   = 0 //32定时器
    TCS = 0 //时钟源选择,内部时钟源或外部时钟源
    */
    T2CONSET = 0x10;  //TxCON与定时器相关的 16 位控制寄存器
 
    /* Clear counter */
    TMR2 = 0x0; //TMRx 16位定时器计数器寄存器
 
    /*Set period */
    PR2 = 39999U; //PRx与定时器相关的 16 位周期寄存器
 
    /* Enable TMR Interrupt */
    IEC0SET = _IEC0_T2IE_MASK; //TxIE中断允许控制位在IEC0中断寄存器中
}
 
//开启定时器
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 (40000000); //返回定时器的时钟频率
}
 
//定时器中断服务函数
void TIMER_2_InterruptHandler (void)
{
    uint32_t status  = 0U;
    status = IFS0bits.T2IF;
    IFS0CLR = _IFS0_T2IF_MASK; //清零IFSx寄存器中的TxIF中断标志位
 
/*可在这添加中断处理内容*/
 
    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();
}

4、16 位同步计数器的初始化步骤

1. 清零 ON 控制位 (TxCON<15> = 0)以禁止定时器。

2. 清零 TCS 控制位 (TxCON<1> = 0)以选择内部 PBCLK 源。

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

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

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

6. 如果使用了中断:

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

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

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

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

4、定时器定时时间计算

T=(P+1)*N/F

其中T为定时时间,单位为s;P为周期数,16位定时器最大值为65535;N为分频数;F为时钟频率;内部时钟频率为80MHz;

5、实验验证

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

image.png

————————————————

版权声明:本文为CSDN博主「Huangtop」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/Huangtop/article/details/119274909