DSP_TMS320F28377D_CPU Timer学习笔记

本文介绍了如何使用DSP的CPUTimer实现软分频功能,通过配置CPUTimer和中断服务函数,生成不同频率的分频信号。文章详细讲解了CPUTimerConfig()函数的配置过程,包括计数周期设置、中断启用和中断服务程序指定。此外,还展示了如何在主循环中利用分频信号执行特定任务。
摘要由CSDN通过智能技术生成

前言

本文主要讲一下DSP CPU Timer的学习笔记,主要内容是用CPU Timer实现软分频功能。本文主要的作用是对于一个知识点的备份,另外呢,也是作为文章基于DSP的三相开关霍尔永磁同步电机控制_江湖上都叫我秋博的博客-CSDN博客知识框架中的一部分。

正文

定时器的原理好像没什么可讲的,所以下面将直接贴代码,然后对代码进行解释。

main.h的代码如下:

#ifndef PROGRAM_MAIN_H_
#define PROGRAM_MAIN_H_

#include <F28x_Project.h>
#include <F2837xD_Ipc_drivers.h>

void CPUTimerConfig(void);
interrupt void CpuTimer0ISR(void);
void DivideFreq(void);


#define SYS_BASIC_FREQUENCY 20000
extern  int16   iFreqCnt;
extern  int16   iFreq1Hz;
extern  int16   iFreq2Hz;
extern  int16   iFreq20Hz;
extern  int16   iFreq40Hz;
extern  int16   iFreq50Hz;
extern  int16   iFreq100Hz;
extern  int16   iFreq200Hz;
extern  int16   iFreq250Hz;
extern  int16   iFreq500Hz;
extern  int16   iFreq1000Hz;
extern  int16   iFreq2500Hz;
extern  int16   iFreq5000Hz;
extern  int16   iFreq10000Hz;
extern  int16   iFreq20000Hz;

#define CNT1HZ      20000
#define CNT2HZ      10000
#define CNT20HZ     1000
#define CNT40HZ     400
#define CNT50HZ     400
#define CNT100HZ    200
#define CNT200HZ    100
#define CNT250HZ    80
#define CNT500HZ    40
#define CNT1000HZ   20
#define CNT2500HZ   8
#define CNT5000HZ   4
#define CNT10000HZ  2
#define CNT20000HZ  1

#endif /* PROGRAM_MAIN_H_ */

main.c的代码如下

#include <main.h>

int16   iFreqCnt    = 0;
int16   iFreq1Hz    = 0;
int16   iFreq2Hz    = 0;
int16   iFreq20Hz   = 0;
int16   iFreq40Hz   = 0;
int16   iFreq50Hz   = 0;
int16   iFreq100Hz  = 0;
int16   iFreq200Hz  = 0;
int16   iFreq250Hz  = 0;
int16   iFreq500Hz  = 0;
int16   iFreq1000Hz = 0;
int16   iFreq2000Hz = 0;
int16   iFreq2500Hz = 0;
int16   iFreq5000Hz = 0;
int16   iFreq10000Hz = 0;
int16   iFreq20000Hz = 0;

void main(void)
{
    InitSysCtrl();
    DINT;
    InitPieCtrl();
    IER     = 0x0000;
    IFR     = 0x0000;
    InitPieVectTable();
    InitCpuTimers();        //  Initialize CPU Timers

    CPUTimerConfig();		//  ▲

    PieCtrlRegs.PIECTRL.bit.ENPIE = 1; //  使能PIE
    EINT;  // 使能全局中断
    ERTM;  // 使能实时仿真中断

    CpuTimer0Regs.TCR.bit.TSS   = 0; // 使能CPUTimer0

    while(1){

        if(iFreq5000Hz==1){
         // do something
			iFreq5000Hz = 0;
		}
	}
}

void CPUTimerConfig (void){
    // CPU Timer0
    ConfigCpuTimer(&CpuTimer0, 200, 1000000/SYS_BASIC_FREQUENCY);
    CpuTimer0Regs.TCR.bit.TIE   = 1;        //  1: The CPU-Timer interrupt is enabled
    // TIMER0 INT1.7 [Page102: Table 3-2.PIE Channel Mapping]
    EALLOW;
        PieVectTable.TIMER0_INT = &CpuTimer0ISR;  //  Specify the interrupt service routine
    EDIS;

    IER |= M_INT1;                           //  Enable CPU Level interrupt
    PieCtrlRegs.PIEIER1.bit.INTx7   = 1;    //  Enable PIE Level interrupt

}

//  Generate frequency division signal
interrupt void CpuTimer0ISR(void){

    DivideFreq();

    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}




void DivideFreq(void){

    if(iFreqCnt >= CNT1HZ){
        iFreq1Hz    = 1;
        iFreqCnt    = 0;
    }else{
        iFreq1Hz    = 0;
    }

    if((iFreqCnt%CNT2HZ)==0){
        iFreq2Hz    = 1;
    }else{
        iFreq2Hz    = 0;
    }

    if((iFreqCnt%CNT20HZ)==0){
        iFreq20Hz    = 1;
    }else{
        iFreq20Hz    = 0;
    }

    if((iFreqCnt%CNT40HZ)==0){
        iFreq40Hz    = 1;
    }else{
        iFreq40Hz    = 0;
    }


    if((iFreqCnt%CNT50HZ)==0){
        iFreq50Hz    = 1;
    }else{
        iFreq50Hz    = 0;
    }

    if((iFreqCnt%CNT100HZ)==0){
        iFreq100Hz    = 1;
    }else{
        iFreq100Hz    = 0;
    }

    if((iFreqCnt%CNT200HZ)==0){
        iFreq200Hz    = 1;
    }else{
        iFreq200Hz    = 0;
    }

    if((iFreqCnt%CNT250HZ)==0){
        iFreq250Hz    = 1;
    }else{
        iFreq250Hz    = 0;
    }

    if((iFreqCnt%CNT500HZ)==0){
        iFreq500Hz    = 1;
    }else{
        iFreq500Hz    = 0;
    }

    if((iFreqCnt%CNT1000HZ)==0){
        iFreq1000Hz    = 1;
    }else{
        iFreq1000Hz    = 0;
    }

/*
    if((iFreqCnt%CNT2000HZ)==0){
        iFreq2000Hz    = 1;
    }else{
        iFreq2000Hz    = 0;
    }
*/
    if((iFreqCnt%CNT2500HZ)==0){
        iFreq2500Hz    = 1;
    }else{
        iFreq2500Hz    = 0;
    }

    if((iFreqCnt%CNT5000HZ)==0){
        iFreq5000Hz    = 1;
    }else{
        iFreq5000Hz    = 0;
    }

    if((iFreqCnt%CNT10000HZ)==0){
        iFreq10000Hz    = 1;
    }else{
        iFreq10000Hz    = 0;
    }

    if((iFreqCnt%CNT20000HZ)==0){
        iFreq20000Hz    = 1;
    }else{
        iFreq20000Hz    = 0;
    }


    iFreqCnt++;

}

main函数重点关注下面这几行代码

    CPUTimerConfig();		//  ▲

    PieCtrlRegs.PIECTRL.bit.ENPIE = 1; //  使能PIE
    EINT;  // 使能全局中断
    ERTM;  // 使能实时仿真中断

    CpuTimer0Regs.TCR.bit.TSS   = 0; // 使能CPUTimer0

    while(1){

        if(iFreq5000Hz==1){
         // do something
			iFreq5000Hz = 0;
		}
	}

CPUTimerConfig();的定义如下。

void CPUTimerConfig (void){
    // CPU Timer0
    ConfigCpuTimer(&CpuTimer0, 200, 1000000/SYS_BASIC_FREQUENCY);
    CpuTimer0Regs.TCR.bit.TIE   = 1;        //  1: The CPU-Timer interrupt is enabled
    // TIMER0 INT1.7 [Page102: Table 3-2.PIE Channel Mapping]
    EALLOW;
        PieVectTable.TIMER0_INT = &CpuTimer0ISR;  //  Specify the interrupt service routine
    EDIS;

    IER |= M_INT1;                           //  Enable CPU Level interrupt
    PieCtrlRegs.PIEIER1.bit.INTx7   = 1;    //  Enable PIE Level interrupt

}

重点关注系统自带的函数:ConfigCpuTimer(&CpuTimer0, 200, 1000000/SYS_BASIC_FREQUENCY);

ConfigCpuTimer函数的作用是配置CPU Timer的一个计数周期,说白了是你CPU Timer计多少个数,我产生一次中断。

第一个参数是指定我们要配置的CPU Timer

第二个参数是指定我们系统的主频是多少MHzTMS320F28377D的主频是200MHz,因此第二个参数我们设置的是200

第三个参数是配合第二个参数一同作用配置计数周期的,第二个参数如果设置成CPU主频200MHz,那么现在第三个参数,则是在假设1MHz的主频下,你要计多少个数,才产生中断了。假设我们想要分频得到基本频率 20kHz,那么你就需要计 1MHz/20kHz个数,而我代码的第三个参数也是用这样的写法, 1000000/SYS_BASIC_FREQUENCY,你翻看main.hSYS_BASIC_FREQUENCY定义,你会发现SYS_BASIC_FREQUENCY定义的就是20000.

CpuTimer0Regs.TCR.bit.TIE   = 1; 这行代码则是打开CPU Timer0的计数溢出中断。也就是说CPU Timer0模块每20kHz就会产生一个中断信号。

EALLOW;

    PieVectTable.TIMER0_INT = &CpuTimer0ISR;  //  Specify the interrupt

EDIS;

这个三行代码则是指定CPU Timer0的计数溢出中断的中断处理函数是CpuTimer0ISR

IER |= M_INT1;                                           //  Enable CPU Level interrupt

PieCtrlRegs.PIEIER1.bit.INTx7   = 1;        //  Enable PIE Level interrupt

这两行的作用则是如它们的注释所说,打开CPU Timer0的计数溢出的PIE级中断和打开CPU级中断。关于中断部分,我会在另一篇文章里面详细讲,这里不赘述。CPUTimerConfig();函数的定义讲完了,下面接着往后讲。

PieCtrlRegs.PIECTRL.bit.ENPIE = 1; //  使能PIE

EINT;  // 使能全局中断

ERTM;  // 使能实时仿真中断

3行代码也如注释所言,咱们外设(CPU Timer0也视为外设)的中断信号 是连接到 PIE模块的 然后PIE模块的信号会连接到 全局/CPU级中断。 因此要让CPU Timer0的计数溢出中断最终生效,要层层打开PIE模块和使能全局中断。

CpuTimer0Regs.TCR.bit.TSS   = 0;则是让CPU Timer0开始不停的计数,溢出产生中断,再计数,再溢出产生中断…。 说溢出也有可能不恰当哈,我搞混了DSP和STM32了,反正它们有一个是从0开始向上递增计数,这个可以说是溢出,另一个是从你设置的计数值向下递减计数,当计数值=0时产生中断,下次计数则是重新装载你之前写到计数周期寄存器的计数值,重新向下递减计数。

while(1){

        if(iFreq5000Hz==1){

                 // do something

                iFreq5000Hz = 0;

        }

 } // 这些代码则是举例如何去使用分频好的信号,比如实现一个5k的离散控制器。

另外,关于中断处理函数interrupt void CpuTimer0ISR(void)和软分频函数void DivideFreq(void)是很容易理解,应该一看就懂了,也就不赘述了。

愿我们共同进步! 感谢您的阅读,欢迎留言讨论、收藏、点赞、分享。

好的,下面是在CCS中创建新工程并移植到TMS320F28377S的步骤: 步骤一:创建新工程 1. 打开CCS件,选择File -> New -> CCS Project,弹出新建工程的窗口。 2. 选择合适的工作空间,输入工程名称和描述,选择TMS320F28377S芯片型号和编译器版本。 3. 点击Finish按钮,创建工程。 步骤二:设置工程属性 1. 右键点击工程名称,选择Properties,打开工程属性设置窗口。 2. 在左侧菜单栏中选择General -> Project References,添加需要的库文件,如DSP库、BIOS库等。 3. 在左侧菜单栏中选择CCS Build -> ARM Compiler -> Include Options,添加头文件路径,如DSP库、BIOS库等的头文件路径。 4. 在左侧菜单栏中选择CCS Build -> ARM Linker -> File Search Path,添加库文件路径,如DSP库、BIOS库等的库文件路径。 步骤三:添加源文件 1. 右键点击工程名称,在弹出的菜单中选择New -> Source File,创建新的源文件。 2. 将需要的源文件添加到工程中。 步骤四:配置连接器文件 1. 在工程目录下创建cmd文件夹,将TMS320F28377S芯片的连接器文件放入其中。 2. 在工程属性设置窗口中,选择CCS Build -> ARM Linker -> Basic Options,将cmd文件夹路径添加到Command file search path中。 步骤五:编译工程 1. 右键点击工程名称,选择Build Project,编译工程。 2. 检查编译过程中是否有错误或者警告信息。 步骤六:下载程序 1. 将开发板与PC机连接,选择合适的下载方式。 2. 点击Debug按钮,下载程序到开发板中。 以上就是在CCS中创建新工程并移植到TMS320F28377S的步骤,希望对你有所帮助。如果你有其他问题,可以继续问我。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

江湖上都叫我秋博

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

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

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

打赏作者

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

抵扣说明:

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

余额充值