TMS320F28P550SJ9学习笔记9:CPUTimer定时器配置使用

CPUTimer定时器配置使用,CPUTimer定时器本身寄存器不多,用到的寄存器也不多,本文就不详细解释每个寄存器的作用了

请下载最后的修改后的最新测试工程!

文章提供测试代码讲解、完整工程下载、测试效果图

目录

CPUTimer 结构体:

CPUTimer定时器初始化预配置:

CPUTimer定时器初始化函数:

主函数初始化部分:

调用初始化函数:

链接 中断服务函数:

编写中断服务函数具体实现:

主函数文件整体代码:

TIMER.c与TIMER.h 整体代码:

 TIMER.c

TIMER.h

测试效果图:

测试工程下载:

问题记录:

有关于主函数的抵充声明:

有关于无法直接输出CpuTimer0.InterruptCount:

修改后的测试工程:


我的单片机平台是这个:

CPUTimer 结构体:

不论你在哪个文件初始化的 CPUTimer ,这三个用到的结构体都要冗余声明一下

没有就会报错,虽然在  f28p55x_cputimers.h 早有定义

我本人是不太明白为何这么做的,就是编译不通过,我就强加了

应该是empty工程没有合理包含它的.h文件的原因,但.c能正常编译

//这三个声明要有,没有就会报错,虽然在  f28p55x_cputimers.h 早有定义
struct CPUTIMER_VARS CpuTimer0;
struct CPUTIMER_VARS CpuTimer1;
struct CPUTIMER_VARS CpuTimer2;

CPUTimer定时器初始化预配置:

CPUTimer 一共有0~2,三个

初始化它们之前先预设定一下,防止芯片内部有残留寄存器配置


// 预配置 三个CPUtimer
void InitCpuTimers(void)
{
    // CPU Timer 0
    // Initialize address pointers to respective timer registers:
    CpuTimer0.RegsAddr = &CpuTimer0Regs;

    // 将CPU Timer 0的周期寄存器PRD设置为最大值0xFFFFFFFF,以便稍后根据需要的周期进行调整
    CpuTimer0Regs.PRD.all  = 0xFFFFFFFF;

    // 将预分频器寄存器TPR和TPRH设置为0,表示使用系统时钟SYSCLKOUT直接作为定时器的时钟源(即不分频)。
    CpuTimer0Regs.TPR.all  = 0;
    CpuTimer0Regs.TPRH.all = 0;

    // 设置定时器控制寄存器TCR的TSS位为1,停止CPU Timer 0。
    CpuTimer0Regs.TCR.bit.TSS = 1;

    // 设置TCR的TRB位为1,以重新加载周期寄存器PRD的值到计数器中。
    CpuTimer0Regs.TCR.bit.TRB = 1;

    // 将CPU Timer 0的中断计数器重置为0。
    CpuTimer0.InterruptCount = 0;

    // 接下来的代码重复了上述过程,但用于初始化CPU Timer 1和CPU Timer 2:
    CpuTimer1.RegsAddr = &CpuTimer1Regs;
    CpuTimer2.RegsAddr = &CpuTimer2Regs;

    //周期寄存器PRD设置为最大值0xFFFFFFFF,以便稍后根据需要的周期进行调整
    CpuTimer1Regs.PRD.all  = 0xFFFFFFFF;
    CpuTimer2Regs.PRD.all  = 0xFFFFFFFF;

    // 将预分频器寄存器TPR和TPRH设置为0,表示使用系统时钟SYSCLKOUT直接作为定时器的时钟源(即不分频)。
    CpuTimer1Regs.TPR.all  = 0;
    CpuTimer1Regs.TPRH.all = 0;
    CpuTimer2Regs.TPR.all  = 0;
    CpuTimer2Regs.TPRH.all = 0;

    // 设置定时器控制寄存器TCR的TSS位为1,停止CPU Timer 1 和 2。
    CpuTimer1Regs.TCR.bit.TSS = 1;
    CpuTimer2Regs.TCR.bit.TSS = 1;

    // 设置TCR的TRB位为1,以重新加载周期寄存器PRD的值到计数器中。
    CpuTimer1Regs.TCR.bit.TRB = 1;
    CpuTimer2Regs.TCR.bit.TRB = 1;

    // 将CPU Timer 1 和 2 的中断计数器重置为0。
    CpuTimer1.InterruptCount = 0;
    CpuTimer2.InterruptCount = 0;
}

CPUTimer定时器初始化函数:

传入三个参数:

1.CPUTimer 结构体     2.分频     3.重载值


void Init_CPU_TIMER(struct CPUTIMER_VARS *Timer, float Freq, float Period)
{
    Uint32 temp;

    //设定频率
    Timer->CPUFreqInMHz = Freq;
    Timer->PeriodInUSec = Period;
    temp = (Uint32) (Freq * Period);

    Timer->RegsAddr->PRD.all = temp - 1;

    Timer->RegsAddr->TPR.all  = 0;
    Timer->RegsAddr->TPRH.all  = 0;

    // Initialize timer control register:
     Timer->RegsAddr->TCR.bit.TSS = 1;     // 1 = Stop timer, 0 = Start/Restart
                                           // Timer
     Timer->RegsAddr->TCR.bit.TRB = 1;     // 1 = reload timer
     Timer->RegsAddr->TCR.bit.SOFT = 0;
     Timer->RegsAddr->TCR.bit.FREE = 0;    // Timer Free Run Disabled
     Timer->RegsAddr->TCR.bit.TIE = 1;     // 0 = Disable/ 1 = Enable Timer
                                           // Interrupt

     // Reset interrupt counter:
     Timer->InterruptCount = 0;

}

主函数初始化部分:

调用初始化函数:

调用之前写好的初始化函数:

链接 中断服务函数:

初始化完了就要链接它们的中断服务函数:

编写中断服务函数具体实现:

这个中断服务函数的具体实现写在主函数是正常的,我之前尝试放在TIMER.h文件过,但没法正常进入...

主函数文件整体代码:

/*  名称   : CPU 定时器 测试工程
 *  创建者 : NULL指向我
 *  日期   : 2025.3.11
 *  功能   : SCI打印 CPUtime 0 中断溢出次数
 *  平台   : LAUNCHXL-F28P55x
 *  型号   : TMS320F28P550SJ9
 *  备注   :
 *           主函数
 *
 * */

//头文件
#include "f28x_project.h"
#include "driverlib.h"
#include "device.h"
#include "sci.h"
#include "TIMER.h"
#include "string.h"
#include "stdio.h"

// 这个 CPU定时器的 中断服务函数貌似只能 定义在 主函数文件
__interrupt void cpuTimer0ISR(void);
__interrupt void cpuTimer1ISR(void);
__interrupt void cpuTimer2ISR(void);

// 抵充编译BUG (本来正常情况 无需声明这三个函数)
void Init_GPIO_LEDPort(void);                     //初始化LED端口
void Init_SCIA(uint32_t baund,uint32_t lspclk);   //初始化SCI @LSPCLK = 37.5 MHz (150 MHz SYSCLK)  HBAUD = 0x01 and LBAUD = 0xE7.
void SCIa_Printf(char *fmt,...);                  // 自定义printf函数


//主函数 main
void main(void)
{
  int temp=0;

  Device_init();         //初始化系统时钟
  Device_initGPIO();     //解锁GPIO端口

  Init_GPIO_LEDPort();   //初始化LED端口

  // @LSPCLK = 37.5 MHz (150 MHz SYSCLK)  HBAUD = 0x01 and LBAUD = 0xE7.
  Init_SCIA(9600,37500000);//初始化SCI

  InitCpuTimers();
  //初始化定时器CUPTIMER 0
  Init_CPU_TIMER(&CpuTimer0, 150, 1000000);//时钟来源 SYSCLKOUT 150Mhz / 150分频 /1000 000计数重载值 / 1000 ms溢出中断频率

  InitPieVectTable();
  Interrupt_initModule();
  Interrupt_initVectorTable();

  // 链接 中断服务函数 ISR functions
  EALLOW;
  PieVectTable.TIMER0_INT = &cpuTimer0ISR;
  PieVectTable.TIMER1_INT = &cpuTimer1ISR;
  PieVectTable.TIMER2_INT = &cpuTimer2ISR;
  EDIS;

  CpuTimer0Regs.TCR.all = 0x4000;
  CpuTimer1Regs.TCR.all = 0x4000;
  CpuTimer2Regs.TCR.all = 0x4000;

  IER |= M_INT1;
  IER |= M_INT13;
  IER |= M_INT14;

  // Enable TINT0 in the PIE: Group 1 interrupt 7
  PieCtrlRegs.PIEIER1.bit.INTx7 = 1;

  EINT;
  ERTM;

  while(1)
  {
      temp=CpuTimer0.InterruptCount; //需要用中间值复读寄存器,你无法直接输出 CpuTimer0.InterruptCount
      SCIa_Printf("CpuTimer0 InterruptCounts: %d \r\n",temp);  //计数

      DEVICE_DELAY_US(500000);
  }
}



// cpuTimer0ISR - CPU Timer0 ISR with interrupt counter
__interrupt void cpuTimer0ISR(void)
{
    CpuTimer0.InterruptCount++;

    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}

// cpuTimer1ISR - CPU Timer1 ISR with interrupt counter
__interrupt void cpuTimer1ISR(void)
{
    CpuTimer1.InterruptCount++;
}

// cpuTimer2ISR CPU Timer2 ISR with interrupt counter
__interrupt void cpuTimer2ISR(void)
{
    CpuTimer2.InterruptCount++;
}



//主文件结尾

TIMER.c与TIMER.h 整体代码:

 TIMER.c

/*
 * TIMER.c
 *
 *  Created on: 2025年3月11日
 *      Author: 30313
 */

#include "TIMER.h"

//这三个声明要有,没有就会报错,虽然在  f28p55x_cputimers.h 早有定义
struct CPUTIMER_VARS CpuTimer0;
struct CPUTIMER_VARS CpuTimer1;
struct CPUTIMER_VARS CpuTimer2;

// 预配置 三个CPUtimer
void InitCpuTimers(void)
{
    // CPU Timer 0
    // Initialize address pointers to respective timer registers:
    CpuTimer0.RegsAddr = &CpuTimer0Regs;

    // 将CPU Timer 0的周期寄存器PRD设置为最大值0xFFFFFFFF,以便稍后根据需要的周期进行调整
    CpuTimer0Regs.PRD.all  = 0xFFFFFFFF;

    // 将预分频器寄存器TPR和TPRH设置为0,表示使用系统时钟SYSCLKOUT直接作为定时器的时钟源(即不分频)。
    CpuTimer0Regs.TPR.all  = 0;
    CpuTimer0Regs.TPRH.all = 0;

    // 设置定时器控制寄存器TCR的TSS位为1,停止CPU Timer 0。
    CpuTimer0Regs.TCR.bit.TSS = 1;

    // 设置TCR的TRB位为1,以重新加载周期寄存器PRD的值到计数器中。
    CpuTimer0Regs.TCR.bit.TRB = 1;

    // 将CPU Timer 0的中断计数器重置为0。
    CpuTimer0.InterruptCount = 0;

    // 接下来的代码重复了上述过程,但用于初始化CPU Timer 1和CPU Timer 2:
    CpuTimer1.RegsAddr = &CpuTimer1Regs;
    CpuTimer2.RegsAddr = &CpuTimer2Regs;

    //周期寄存器PRD设置为最大值0xFFFFFFFF,以便稍后根据需要的周期进行调整
    CpuTimer1Regs.PRD.all  = 0xFFFFFFFF;
    CpuTimer2Regs.PRD.all  = 0xFFFFFFFF;

    // 将预分频器寄存器TPR和TPRH设置为0,表示使用系统时钟SYSCLKOUT直接作为定时器的时钟源(即不分频)。
    CpuTimer1Regs.TPR.all  = 0;
    CpuTimer1Regs.TPRH.all = 0;
    CpuTimer2Regs.TPR.all  = 0;
    CpuTimer2Regs.TPRH.all = 0;

    // 设置定时器控制寄存器TCR的TSS位为1,停止CPU Timer 1 和 2。
    CpuTimer1Regs.TCR.bit.TSS = 1;
    CpuTimer2Regs.TCR.bit.TSS = 1;

    // 设置TCR的TRB位为1,以重新加载周期寄存器PRD的值到计数器中。
    CpuTimer1Regs.TCR.bit.TRB = 1;
    CpuTimer2Regs.TCR.bit.TRB = 1;

    // 将CPU Timer 1 和 2 的中断计数器重置为0。
    CpuTimer1.InterruptCount = 0;
    CpuTimer2.InterruptCount = 0;
}


void Init_CPU_TIMER(struct CPUTIMER_VARS *Timer, float Freq, float Period)
{
    Uint32 temp;

    //设定频率
    Timer->CPUFreqInMHz = Freq;
    Timer->PeriodInUSec = Period;
    temp = (Uint32) (Freq * Period);

    Timer->RegsAddr->PRD.all = temp - 1;

    Timer->RegsAddr->TPR.all  = 0;
    Timer->RegsAddr->TPRH.all  = 0;

    // Initialize timer control register:
     Timer->RegsAddr->TCR.bit.TSS = 1;     // 1 = Stop timer, 0 = Start/Restart
                                           // Timer
     Timer->RegsAddr->TCR.bit.TRB = 1;     // 1 = reload timer
     Timer->RegsAddr->TCR.bit.SOFT = 0;
     Timer->RegsAddr->TCR.bit.FREE = 0;    // Timer Free Run Disabled
     Timer->RegsAddr->TCR.bit.TIE = 1;     // 0 = Disable/ 1 = Enable Timer
                                           // Interrupt

     // Reset interrupt counter:
     Timer->InterruptCount = 0;

}


TIMER.h

/*
 * TIMER.h
 *
 *  Created on: 2025年3月11日
 *      Author: 30313
 */

#ifndef USER_TIMER_H_
#define USER_TIMER_H_

#include "f28x_project.h"
#include "driverlib.h"
#include "device.h"


void InitCpuTimers(void);
void Init_CPU_TIMER(struct CPUTIMER_VARS *Timer, float Freq, float Period);


/*
__interrupt void cpuTimer0ISR(void);
__interrupt void cpuTimer1ISR(void);
__interrupt void cpuTimer2ISR(void);
*/


#endif /* USER_TIMER_H_ */

测试效果图:

通过打印可以看出,定时器在时序上是正常运行的

但测试结果中,数字打印是连续的,我主循环每500ms读取一次定时器中断次数寄存器的值

并打印,本应该每个数字出现2次,但总会偶尔出现某个数字只打印了一次的情况出现

这说明某次打印被打断了!

而且还貌似有点规律,4  8  13  17  21  26 ....基本这个规律

测试工程下载:

https://download.youkuaiyun.com/download/qq_64257614/90473931

问题记录:

有关于主函数的抵充声明:

发现原因是因为有俩个sci.h文件,冲突了:

但这样声明一下就没啥问题

 后续我修改自己俩个文件的名称就好了:

有关于无法直接输出CpuTimer0.InterruptCount:

这个问题在主函数中:

本质原因是我的打印函数没法正确处理Uint32位的数据,导致数据位丢失了

这里你只要把temp也定义为 Uint32 尝试输出就能看出

修改后的测试工程:

https://download.youkuaiyun.com/download/qq_64257614/90474100

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NULL指向我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值