This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CCS/TMS320F28377S:TMS320F28377S 的延迟功能

Guru**** 2482225 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/594791/ccs-tms320f28377s-delay-function-for-tms320f28377s

器件型号:TMS320F28377S

工具/软件:Code Composer Studio

您好!

 我的代码中有一个延迟函数、最小步长仅为一微秒。请告诉我、我将如何为较小步长定义我自己的延迟函数。


//包含的文件
//
#include "F28x_Project.h"

//
//定义
//

#define Blinky_LED_GPIO 12.

中断空 XINT1_ISR (空);


void main (void)

//
//步骤1. 初始化系统控制:
// PLL、安全装置、启用外设时钟
//此示例函数位于 F2837xS_SYSCTRL.c 文件中。
//
InitSysCtrl();

//
//步骤2. 初始化 GPIO:
//此示例函数位于 F2837xS_GPIO.c 文件和中
//说明了如何将 GPIO 设置为其默认状态。
//
InitGpio();
GPIO_SetupPinMux (Blinky_LED_GPIO、GPIO_MUX_CPU1、0);
GPIO_SetupPinOptions (Blinky_LED_GPIO、GPIO_output、GPIO_PushPull);

//
//步骤3. 清除所有中断并初始化 PIE 矢量表:
//禁用 CPU 中断
//
Dint;

//
//将 PIE 控制寄存器初始化为默认状态。
//默认状态为禁用所有 PIE 中断和标志
//被清除。
//此函数位于 F2837xS_PIECTRL.c 文件中。
//
InitPieCtrl();

//
//禁用 CPU 中断并清除所有 CPU 中断标志:
//
IER = 0x0000;
IFR = 0x0000;

//
//使用指向 shell 中断的指针初始化 PIE 矢量表
//服务例程(ISR)。
//这将填充整个表,即使是中断也是如此
//在本例中未使用。 这对于调试很有用。
//可以在 F2837xS_DefaultIsr.c 中找到 shell ISR 例程
//此函数可在 F2837xS_PieVect.c 中找到
//
InitPieVectTable();

//
//此示例中使用的中断被重新映射到
//此文件中的 ISR 函数。
//
EALLOW;//这是写入 EALLOW 受保护寄存器所必需的
PieVectTable.XINT1_INT =&XINT1_ISR;
EDIS;//这是禁止写入 EALLOW 受保护寄存器所必需的

//


//
//在 PIE 中启用 XINT1和 XINT2:组1中断4和5
//启用连接到 WAKEINT 的 INT1:
//
PieCtrlRegs.PIECTRL.bit.ENPIE = 1;//启用 PIE 块
PieCtrlRegs.PIEIER1.bit.INTx4 = 1;//启用 PIE 组1 INT4
PieCtrlRegs.PIEIER1.bit.INTx5 = 1;//启用 PIE 组1 INT5
IER |= M_INT1;//启用 CPU INT1
EINT;//启用全局中断

// GPIO14是输入
//
EALLOW;
GpioCtrlRegs.GPAMUX1.bit.GPIO14 = 0;// GPIO
GpioCtrlRegs.GPADIR.bit.GPIO14 = 0;//输入
GpioCtrlRegs.GPAQSEL1.bit.GPIO14 = 0;// XINT1同步到 SYSCLKOUT

EDIS;

//
// GPIO14是 XINT1
//
GPIO_SetupXINT1Gpio (14);

//
//配置 XINT1
//
XintRegs.XINT1CR.bit.polarity = 1;//上升边沿中断1
//下降沿中断0

//
//启用 XINT1
//
XintRegs.XINT1CR.bit.ENABLE = 1;//启用 XINT1

//
//
//启用全局中断和更高优先级的实时调试事件:
//
EINT;//启用全局中断 INTM
ERTM;//启用全局实时中断 DBGM

//
//步骤6. 空闲循环。 只需坐下来循环(可选):
//
for (;;)



//
//我的内部
//
// XINT1_ISR -外部中断1 ISR
//

中断空 XINT1_ISR (空)

//
//打开 LED
//
GPIO_WritePin (Blinky_LED_GPIO、0);

//
//延迟一位。
//
DELAY_US (1000*500);

//
//关闭 LED
//
GPIO_WritePin (Blinky_LED_GPIO、1);

//
//延迟一位。
//
DELAY_US (1000*500);

//打开 LED
//
GPIO_WritePin (Blinky_LED_GPIO、0);

//
//延迟一位。
//
DELAY_US (1000*500);

//
//关闭 LED
//
GPIO_WritePin (Blinky_LED_GPIO、1);

//
//延迟一位。
//
DELAY_US (1000*500);

//

//确认此中断以从组1获取更多内容
//
PieCtrlRegs.PIEACX.ALL = PIEACK_Group1;


//
//文件结束
//

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    您的选项取决于您希望延迟的大小。 如果您希望延迟几个周期、可以使用__asm (" NOP)向代码中添加 NOP 指令。

    对于多个重复 NOP、您可以使用 RPT 指令、如_asm (" RPT #100 || NOP")。 您需要记住、重复是不可中断的。

    或者,您也可以研究 F2837xS_Example.h 文件中的 delay_US()宏并对其进行调整,使其在较小的时间单位内工作。 电流公式如下所示:((a us * 1000ns/us)/CPU 比率 ns/cycle)- 9 cycles)/ 5 cycles / loop。 由于 F28x_usDelay()函数的性质,9和5必须保持不变,但您可以调整一些其他变量。

    惠特尼
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    非常感谢 Whitney。 通过更改以下公式中的变量、我获得了以 ns 为单位的延迟。(a us * 1000ns/us)/CPU 比率 ns/cycle)- 9 cycles)/ 5 cycles / loop。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

     请告诉我、我可以从何处更改 CPU 速率。 您能否告诉我要放入以下公式(a us * 1000ns/us)/CPU 比率 ns/cycle)- 9 cycles)/5 cycles / loop)以获得5ns 延迟。我在200MHz 上工作、我需要5ns 的延迟(纳秒)。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    该宏的核心 F28x_usDelay()函数每个循环花费5个周期,开销为9个周期。 鉴于5ns 是单周期、即使您更改宏、也无法使用它。 请改用 NOP 指令。

    惠特尼

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!
    我正在使用此指令__asm (" RPT #100 || NOP")。 我还更改了值100 (从0到120)、但我得到的最小延迟为500ns。 频率是否有任何问题?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    _asm (" RPT #100 || NOP")为100 NOP。 您会看到100 * 5ns 的延迟、这是有道理的。 如果需要、可以在单个周期中使用单个_asm (" NOP")。

    惠特尼
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    通过使用此函数__asm (“NOP"),我将得到200ns。 我应该使用计时器吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您如何测量延迟? 您能否详细介绍一下为何需要如此小的延迟?

    惠特尼
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我正在通过示波器 HDO4104测量延迟。 我正在使用200MHz 进行双脉冲测试、为此我需要5ns 的延迟。 我正在使用以下程序。


    //
    //包含的文件
    //
    #include "F28x_Project.h"

    //
    //定义
    //

    #define Blinky_LED_GPIO 12.

    中断空 XINT1_ISR (空);
    //此示例的全局变量

    易失性 uint32 t1=(10*50);
    易失性 uint32 t2 =(10*50);
    易失性 uint32 T3 =(10*50);




    void main (void)

    //
    //步骤1. 初始化系统控制:
    // PLL、安全装置、启用外设时钟
    //此示例函数位于 F2837xS_SYSCTRL.c 文件中。
    //
    InitSysCtrl();

    //
    //步骤2. 初始化 GPIO:
    //此示例函数位于 F2837xS_GPIO.c 文件和中
    //说明了如何将 GPIO 设置为其默认状态。
    //
    InitGpio();
    GPIO_SetupPinMux (Blinky_LED_GPIO、GPIO_MUX_CPU1、0);
    GPIO_SetupPinOptions (Blinky_LED_GPIO、GPIO_output、GPIO_PushPull);

    //
    //步骤3. 清除所有中断并初始化 PIE 矢量表:
    //禁用 CPU 中断
    //
    Dint;

    //
    //将 PIE 控制寄存器初始化为默认状态。
    //默认状态为禁用所有 PIE 中断和标志
    //被清除。
    //此函数位于 F2837xS_PIECTRL.c 文件中。
    //
    InitPieCtrl();

    //
    //禁用 CPU 中断并清除所有 CPU 中断标志:
    //
    IER = 0x0000;
    IFR = 0x0000;

    //
    //使用指向 shell 中断的指针初始化 PIE 矢量表
    //服务例程(ISR)。
    //这将填充整个表,即使是中断也是如此
    //在本例中未使用。 这对于调试很有用。
    //可以在 F2837xS_DefaultIsr.c 中找到 shell ISR 例程
    //此函数可在 F2837xS_PieVect.c 中找到
    //
    InitPieVectTable();

    //
    //此示例中使用的中断被重新映射到
    //此文件中的 ISR 函数。
    //
    EALLOW;//这是写入 EALLOW 受保护寄存器所必需的
    PieVectTable.XINT1_INT =&XINT1_ISR;
    EDIS;//这是禁止写入 EALLOW 受保护寄存器所必需的

    //


    //
    //在 PIE 中启用 XINT1和 XINT2:组1中断4和5
    //启用连接到 WAKEINT 的 INT1:
    //
    PieCtrlRegs.PIECTRL.bit.ENPIE = 1; //启用 PIE 块
    PieCtrlRegs.PIEIER1.bit.INTx4 = 1; //启用 PIE 组1 int4
    PieCtrlRegs.PIEIER1.bit.INTx5 = 1; //启用 PIE 组1 INT5
    IER |= M_INT1; //启用 CPU INT1
    EINT; //启用全局中断

    // GPIO14是输入
    //
    EALLOW;
    GpioCtrlRegs.GPAMUX1.bit.GPIO14=0; // GPIO
    GpioCtrlRegs.GPADIR.bit.GPIO14 = 0; //输入
    GpioCtrlRegs.GPAQSEL1.bit.GPIO14=0; // XINT1同步到 SYSCLKOUT 只

    EDIS;

    //
    // GPIO14是 XINT1
    //
    GPIO_SetupXINT1Gpio (14);

    //
    //配置 XINT1
    //
    XintRegs.XINT1CR.bit.polarity = 1; //上升沿中断1
    //下降沿中断0

    //
    //启用 XINT1
    //
    XintRegs.XINT1CR.bit.ENABLE = 1; //启用 XINT1

    //
    //
    //启用全局中断和更高优先级的实时调试事件:
    //
    EINT;//启用全局中断 INTM
    ERTM;//启用全局实时中断 DBGM

    //
    //步骤6. 空闲循环。 只需坐下来循环(可选):
    //
    for (;;)


    PieCtrlRegs.PIECTRL.bit.ENPIE = 1; //启用 PIE 块
    PieCtrlRegs.PIEIER1.bit.INTx4 = 1; //启用 PIE 组1 int4
    PieCtrlRegs.PIEIER1.bit.INTx5 = 1; //启用 PIE 组1 INT5




    //
    //我的内部
    //
    // XINT1_ISR -外部中断1 ISR
    //

    中断空 XINT1_ISR (空)


    PieCtrlRegs.PIECTRL.bit.ENPIE = 0; //启用 PIE 块
    PieCtrlRegs.PIEIER1.bit.INTx4 = 0; //启用 PIE 组1 int4
    PieCtrlRegs.PIEIER1.bit.INTx5 = 0; //启用 PIE 组1 INT5

    //
    //打开 LED
    //
    GPIO_WritePin (Blinky_LED_GPIO、0);

    //
    //延迟一位。
    //
    _asm (" NOP");

    //
    //关闭 LED
    //
    GPIO_WritePin (Blinky_LED_GPIO、1);

    //
    //延迟一位。
    //
    _asm (" NOP");

    //打开 LED
    //
    GPIO_WritePin (Blinky_LED_GPIO、0);

    //
    //延迟一位。
    //
    _asm (" NOP");

    //
    //关闭 LED
    //
    GPIO_WritePin (Blinky_LED_GPIO、1);





    //确认此中断以从组1获取更多内容
    //
    PieCtrlRegs.PIEACX.ALL = PIEACK_Group1;


    //
    //文件结束
    //
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您看到的额外延迟不是因为 NOP 花费的时间太长。 我怀疑这是您写入 GPIO 的方式。 首先是函数调用的开销。 然后、如果您看一下函数本身、它会计算与引脚编号参数对应的寄存器和位、并根据您是写入0还是1而设置该设置寄存器或清除寄存器。

    此 wiki 页面列出了一些更快的方法:
    processors.wiki.ti.com/.../General_Purpose_IO_(GPIO)_FAQ_for_C2000

    惠特尼
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    请告诉我在 LaunchXL-F28377S 中、从何处可以将时钟频率更改为200MHz。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    查看 F2837xS_SYSCTRL.C.中的 InitSysCtrl()函数 有一个到 InitSysPll()的调用,在这里配置乘法器和除法器。

    惠特尼
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    如果我使用此函数__asm (" RPT #100 || NOP")。 我将如何将100声明为变量 T1。 我使用的语法是__asm (" RPT #T1 || NOP");
    //此示例的全局变量

    易失性 UINT32 T1 = 100;
    但它不起作用
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    你好
    我正在使用此函数__asm (" RPT #100 || NOP")。 但我想将100声明为变量。 我正在使用此语法、但它不起作用。
    _asm (" RPT #T1 || NOP");
    在 void main (void)之前、我将其定义为
    易失性 UINT32 T1 = 100;
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    不能使用__asm()语句引用局部变量:
    downloads.ti.com/.../index.html

    惠特尼