DSP28335笔记 —— 定时器

DSP28335笔记 —— 定时器

相比于STM32,DSP28335的定时器好像真的简单了好多,从定时器个数来讲只有3个,时钟源只能是系统时钟,而且计数方向也只有向下计数。
单纯且善良的定时器,好不让人心生喜爱。

定时器介绍

TMS320F28335 的 CPU Time 有三个,分别为 Timer0,Timer1,Timer2,其中 Timer1和Timer2 是为操作系统 DSP/BIOS 保留的,当未移植操作系统时,可用来做普通的定时器。这三个定时器的中断信号分别为 TINT0, TINT1, TINT2,分别对应于中断向量 INT1,INT13,INT14。

定时器的功能如下图所示:
在这里插入图片描述
由图可以看出,TCR为0时定时器才可以开始工作;
TDDR(低位)和TDDRH(高位)组成16位寄存器,对系统时钟进行分频;
PRD(低位)和PRDH(高位)组成32位寄存器,储存每次重装载的值,相当于定时周期;
TIM(低位)和TIMH(高位)组成32位寄存器,用作定时器的当前计时的记录值。

对比STM32的时钟,DSP28335的定时器真的更单纯,DSP28335的定时器只能向下计数,而且不和PWM和CAP功能混在一起让人心烦。

中断方面,定时器0的中断信号通过PIE模块进入内核,定时器1、定时器2的中断信号则直接进入内核。
在这里插入图片描述

相关寄存器

三个定时器的基本设定是相同,具体了解其中一组即可
在这里插入图片描述

大部分寄存器都是写入一个数值,只需要注意TCR寄存器各个位的功能:

TCR寄存器功能介绍

TCR寄存器功能介绍

定时器代码实验

  • 实验内容: 利用定时器0中断,每秒钟改变一次数码管的显示值。为了验证程序是在中断中完成,主函数中设置一个LED的亮灭翻转。

首先完成主函数框架:

void main()
{
    InitSysCtrl();//系统时钟初始化

    InitPieCtrl();//初始化PIE模块
    InitPieVectTable();//初始化PIE中断矢量表
    IER = 0x0000;//清空CPU级中断使能
    IFR = 0x0000;//清空CPU级中断标志

    SEG_Init();//数码管初始化
    LED_Init();//LED初始化
    Seg_SetNum(0);//设置数码管初始显示0

    TIM0_Init(150, 1000000);//TIM0配置  150MHz时钟频率   周期1s

    while(1)
    {//如果程序执行正常,LED闪烁
        GpioDataRegs.GPBTOGGLE.bit.GPIO60 = 1;
        delay();
    }
}

今天主要内容是定时器的使用,下面只贴出TIM0_Init()功能函数的实现代码

void TIM0_Init(float Freq, float Period)
{
    long temp;
    DINT;//全局中断关闭
//第1步 打开TIM0时钟
    EALLOW;
    SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1;
    EDIS;
//第2步 设置中断入口地址
    EALLOW;
    PieVectTable.TINT0 = &TIM0_IRQ;
    EDIS;
//第3步 配置定时器基本
    EALLOW;
    // Initialize address pointers to respective timer registers:
    CpuTimer0.RegsAddr = &CpuTimer0Regs;
    // Initialize timer period:
    CpuTimer0.CPUFreqInMHz = Freq;
    CpuTimer0.PeriodInUSec = Period;
    temp = (long) (Freq * Period);
    CpuTimer0.RegsAddr->PRD.all = temp;
    // Set pre-scale counter to divide by 1 (SYSCLKOUT):
    CpuTimer0.RegsAddr->TPR.all  = 0;
    CpuTimer0.RegsAddr->TPRH.all  = 0;
    // Initialize timer control register:
    CpuTimer0.RegsAddr->TCR.bit.TSS = 1;   // 1 = Stop timer, 0 = Start/Restart Timer
    CpuTimer0.RegsAddr->TCR.bit.TRB = 1;   // 1 = reload timer 使能定时器重载功能
    CpuTimer0.RegsAddr->TCR.bit.SOFT = 0;
    CpuTimer0.RegsAddr->TCR.bit.FREE = 0;  // Timer Free Run Disabled
    CpuTimer0.RegsAddr->TCR.bit.TIE = 1;   // 0 = Disable/  1 = Enable Timer Interrupt
    // Reset interrupt counter:
    CpuTimer0.InterruptCount = 0;
//第4步 打开定时器
    CpuTimer0.RegsAddr->TCR.bit.TSS = 0;   // 1 = Stop timer, 0 = Start/Restart Timer
//第5步 打开PIE组对应中断
    PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
    EDIS;
//第6步 打开CPU中断
    IER |= M_INT1;
    EINT;//全局中断打开

    ERTM;

}

interrupt void TIM0_IRQ(void)
{
    static unsigned char i = 0;
    i++;
    if(i > 9) i = 0;
    Seg_SetNum(i);//更换显示数字
    
    EALLOW;
    CpuTimer0Regs.TCR.bit.TIF = 1;//清除外设级中断标志位
    PieCtrlRegs.PIEACK.bit.ACK1 = 1;//清除PIE级中断应答
    EDIS;
}

在TIM0_Init(float Freq, float Period) 中,第三步的代码是复制TI公司的代码(FILE: DSP2833x_CpuTimers.c)也可以简化成下面的样子。

void TIM0_Init(float Freq, float Period)
{
    long temp;
    DINT;
//第1步 打开TIM0时钟
    EALLOW;
    SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1;
    EDIS;
//第2步 设置中断入口地址
    EALLOW;
    PieVectTable.TINT0 = &TIM0_IRQ;
    EDIS;
//第3步 配置定时器基本
    // Initialize address pointers to respective timer registers:
    InitCpuTimers();
    // Initialize timer period:
    ConfigCpuTimer(&CpuTimer0,Freq,Period);
//第4步 打开定时器
    EALLOW;
    CpuTimer0.RegsAddr->TCR.bit.TSS = 0;
//第5步 打开PIE组对应中断
    PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
    EDIS;
//第6步 打开CPU中断
    IER |= M_INT1;
    EINT;

    ERTM;
}

PS: 可能有些朋友不太清楚 ConfigCpuTimer(&CpuTimer0,Freq,Period);的三个参数。这里简单注释一下,函数原型为

void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period)

	其中Timer的可选参数有三个,就是分别对应的三个定时器
	&CpuTimer0 、 &CpuTimer1 、 &CpuTimer2 ;

	Freq 为系统时钟单位MHZ,我用的系统时钟为150MHz,所以我在这里填 150;

	Period 为期望的定时周期,单位为us 。我的目标是1s,所以我这里填1000000

可能有朋友会像我一样疑惑为什么没有涉及到预分频的设置。通过阅读源文件,我发现TI公司直接是对系统时钟不分频CpuTimer0.RegsAddr->TPR.all = 0; CpuTimer0.RegsAddr->TPRH.all = 0; 凭借着自己是个32位的计数器,通过肆意改变定时周期的自动装载值来实现不同时间的定时,超霸气,超简便,超赞。

  • 16
    点赞
  • 96
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
DSP28335是一种广泛使用的数字信号处理器,它被广泛应用在各种领域,如电力电子、驱动控制、通讯等。其中,定时器DSP28335中非常关键的一部分,它可以用来产生各种不同类型的定时信号,在各种应用场景中具有非常重要的作用。 在DSP28335中,定时器主要包括三种类型:基于时钟的定时器、基于捕获/比较的定时器和基于PWM的定时器。这些定时器可以用来实现不同的功能,比如产生周期性的信号、捕获和比较外部信号、控制PWM输出等。 其中,基于时钟的定时器是最基本的一种,它通过配置定时器的时钟源和计数器的初始值来产生定时信号。在DSP28335中,每个定时器都有多个计数模式和计数范围可以选择,可以根据具体需求来配置。 基于捕获/比较的定时器可以用来捕获和比较外部信号,它可以在定时器计数过程中,根据外部信号的到来时间来记录相应的计数值。同时,它也可以将定时器的计数值和设定的比较值进行比较,用来产生各种不同的控制信号。 基于PWM的定时器则可以用来产生PWM输出信号,它可以通过配置计数周期、计数范围和PWM占空比等参数,来产生各种不同类型的PWM信号。 总之,DSP28335中的定时器功能非常强大,可以用来实现各种不同的功能。使用者可以根据具体的应用需求,选择不同类型的定时器,并根据手册提供的配置参数进行配置,来满足不同的控制需求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值