【原创】TIVA 关于SysCtlDelay()准确延时的测试

[复制链接]
3084|19
手机看帖
扫描二维码
随时随地手机跟帖
xyz549040622|  楼主 | 2015-11-25 16:25 | 显示全部楼层 |阅读模式
本帖最后由 xyz549040622 于 2015-11-25 17:23 编辑

上一篇帖子中分析,SysCtlDelay(SysCtlClockGet() / M / 3)的延时时间都为1/M(s).帖子链接如下
https://bbs.21ic.com/icview-1203016-1-1.html

可是实际测试却不是这么一回事的

设置系统主时钟为50MHZ,直接用SysCtlDelay(5000000 / 3000);延时,延时时间为很准确的2ms
代码如下
//*****************************************************************************
//
// hello.c - Simple hello world example.
//
// Copyright (c) 2012-2014 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 2.1.0.12573 of the EK-TM4C123GXL Firmware Package.
//
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
//#include "utils/uartstdio.h"

//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>Hello World (hello)</h1>
//!
//! A very simple ``hello world'' example.  It simply displays ``Hello World!''
//! on the UART and is a starting point for more complicated applications.
//!
//! UART0, connected to the Virtual Serial Port and running at
//! 115,200, 8-N-1, is used to display messages from this application.
//
//*****************************************************************************

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

////*****************************************************************************
////
//// Configure the UART and its pins.  This must be called before UARTprintf().
////
////*****************************************************************************
//void
ConfigureUART(void)
{
//    //
//    // Enable the GPIO Peripheral used by the UART.
//    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

//    //
//    // Enable UART0
//    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

//    //
//    // Configure GPIO Pins for UART mode.
//    //
    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
   ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

//    //
//    // Use the internal 16MHz oscillator as the UART clock source.
//    //
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);

//    //
//    // Initialize the UART for console I/O.
//    //
    UARTStdioConfig(0, 115200, 16000000);
}

//*****************************************************************************
//
// Print "Hello World!" to the UART on the evaluation board.
//
//*****************************************************************************
int
main(void)
{
    volatile uint32_t ui32Loop;

    //
    // Enable lazy stacking for interrupt handlers.  This allows floating-point
    // instructions to be used within interrupt handlers, but at the expense of
    // extra stack usage.
    //
    ROM_FPULazyStackingEnable();

    //
    // Set the clocking to run directly from the crystal.
    //
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
                       SYSCTL_OSC_MAIN);

    //
    // Enable the GPIO port that is used for the on-board LED.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    //
    // Enable the GPIO pins for the LED (PF2 & PF3).
    //
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);

    //
    // Initialize the UART.
    //
    ConfigureUART();

//    //
//    // Hello!
//    //
/*    UARTprintf("Hello, world!\n");
    ui32Loop=0;
    ui32Loop=ROM_SysCtlClockGet();
    UARTprintf("%d\n",ui32Loop);
    ui32Loop=0;
    ui32Loop=SysCtlClockGet();
    UARTprintf("%d\n",ui32Loop);*/
    //
    // We are finished.  Hang around doing nothing.
    //
    while(1)
    {
        //
        // Turn on the BLUE LED.

        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);

        //
        // Delay for a bit.
        //
        SysCtlDelay(50000000 / 3000);

        //
        // Turn off the BLUE LED.
        //
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);

        //
        // Delay for a bit.
        //
        SysCtlDelay(50000000 / 3000);
/*                    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);

                    //
                    // Delay for a bit.
                    //
                    SysCtlDelay(ROM_SysCtlClockGet() / 3000);

                    //
                    // Turn off the BLUE LED.
                    //
                    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);

                    //
                    // Delay for a bit.
                    //
                    SysCtlDelay(ROM_SysCtlClockGet() / 3000);*/
    }
}
时间截图如下:
360截图20151125162013545.jpg

相关帖子

xyz549040622|  楼主 | 2015-11-25 16:30 | 显示全部楼层
本帖最后由 xyz549040622 于 2015-11-25 16:32 编辑

使用 SysCtlDelay(ROM_SysCtlClockGet() / 3000);延时,并加入了测试ROM_SysCtlClockGet()值的代码,延时时间为1.1ms

    UARTprintf("Hello, world!\n");
    ui32Loop=0;
    ui32Loop=ROM_SysCtlClockGet();
    UARTprintf("%d\n",ui32Loop);
    ui32Loop=0;
    ui32Loop=SysCtlClockGet();
    UARTprintf("%d\n",ui32Loop);


整个源代码如下:
//*****************************************************************************
//
// hello.c - Simple hello world example.
//
// Copyright (c) 2012-2014 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 2.1.0.12573 of the EK-TM4C123GXL Firmware Package.
//
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
//#include "utils/uartstdio.h"

//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>Hello World (hello)</h1>
//!
//! A very simple ``hello world'' example.  It simply displays ``Hello World!''
//! on the UART and is a starting point for more complicated applications.
//!
//! UART0, connected to the Virtual Serial Port and running at
//! 115,200, 8-N-1, is used to display messages from this application.
//
//*****************************************************************************

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

////*****************************************************************************
////
//// Configure the UART and its pins.  This must be called before UARTprintf().
////
////*****************************************************************************
//void
ConfigureUART(void)
{
//    //
//    // Enable the GPIO Peripheral used by the UART.
//    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

//    //
//    // Enable UART0
//    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

//    //
//    // Configure GPIO Pins for UART mode.
//    //
    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
   ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

//    //
//    // Use the internal 16MHz oscillator as the UART clock source.
//    //
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);

//    //
//    // Initialize the UART for console I/O.
//    //
    UARTStdioConfig(0, 115200, 16000000);
}

//*****************************************************************************
//
// Print "Hello World!" to the UART on the evaluation board.
//
//*****************************************************************************
int
main(void)
{
    volatile uint32_t ui32Loop;

    //
    // Enable lazy stacking for interrupt handlers.  This allows floating-point
    // instructions to be used within interrupt handlers, but at the expense of
    // extra stack usage.
    //
  //  ROM_FPULazyStackingEnable();

    //
    // Set the clocking to run directly from the crystal.
    //
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
                       SYSCTL_OSC_MAIN);

    //
    // Enable the GPIO port that is used for the on-board LED.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    //
    // Enable the GPIO pins for the LED (PF2 & PF3).
    //
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);

    //
    // Initialize the UART.
    //
    ConfigureUART();

//    //
//    // Hello!
//    //
    UARTprintf("Hello, world!\n");
    ui32Loop=0;
    ui32Loop=ROM_SysCtlClockGet();
    UARTprintf("%d\n",ui32Loop);
    ui32Loop=0;
    ui32Loop=SysCtlClockGet();
    UARTprintf("%d\n",ui32Loop);
    //
    // We are finished.  Hang around doing nothing.
    //
    while(1)
    {
        //
        // Turn on the BLUE LED.

/*        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);

        //
        // Delay for a bit.
        //
        SysCtlDelay(50000000 / 3000);

        //
        // Turn off the BLUE LED.
        //
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);

        //
        // Delay for a bit.
        //
        SysCtlDelay(50000000 / 3000);*/
                    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);

                    //
                    // Delay for a bit.
                    //
                    SysCtlDelay(ROM_SysCtlClockGet() / 3000);

                    //
                    // Turn off the BLUE LED.
                    //
                    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);

                    //
                    // Delay for a bit.
                    //
                    SysCtlDelay(ROM_SysCtlClockGet() / 3000);
    }
}
可以看到,系统主时钟为50000000
360截图20151125162809330.jpg
延时时间如下:
360截图20151125162601813.jpg

使用特权

评论回复
xyz549040622|  楼主 | 2015-11-25 16:50 | 显示全部楼层
本帖最后由 xyz549040622 于 2015-11-25 17:23 编辑

找到问题了终于,一定要开启FPU的,因为在计算50000000/3时浪费了一部分时间。下面进行准确延时的计算

使用特权

评论回复
dirtwillfly| | 2015-11-25 17:10 | 显示全部楼层

使用特权

评论回复
xyz549040622|  楼主 | 2015-11-25 17:22 | 显示全部楼层
本帖最后由 xyz549040622 于 2015-11-25 17:35 编辑

再次说明,这个延时确实要精确计算的,毕竟只是粗略延时,us级别,ms级别,s级别的参数都是不同的,现在做到主频率是80MHz的时候,SysCtlDelay(ROM_SysCtlClockGet()/3000)准确延时为2ms。

使用特权

评论回复
stalker张| | 2015-11-26 09:49 | 显示全部楼层
楼主,可有tiva板的资料,能否共享?

使用特权

评论回复
smilingangel| | 2015-11-26 14:40 | 显示全部楼层
这个延时程序很不错的,其他程序中俄可采用。

使用特权

评论回复
xyz549040622|  楼主 | 2015-11-26 14:49 | 显示全部楼层
stalker张 发表于 2015-11-26 09:49
楼主,可有tiva板的资料,能否共享?

官网就有的呀。

使用特权

评论回复
yyj8902| | 2015-11-28 15:53 | 显示全部楼层
stalker张 发表于 2015-11-26 09:49
楼主,可有tiva板的资料,能否共享?

去TI的官网下载,每种评估板的资料都有的。

使用特权

评论回复
stalker张| | 2015-11-28 17:32 | 显示全部楼层
yyj8902 发表于 2015-11-28 15:53
去TI的官网下载,每种评估板的资料都有的。

谢谢

使用特权

评论回复
309030| | 2015-11-28 20:25 | 显示全部楼层
版主的哪个截图使用什么仿真出来的

使用特权

评论回复
10299823| | 2015-11-29 22:25 | 显示全部楼层
最好使用定时器的。

使用特权

评论回复
10299823| | 2015-11-29 22:26 | 显示全部楼层
其他的准确率不如定时器。

使用特权

评论回复
10299823| | 2015-11-29 22:29 | 显示全部楼层
使用延时不好控制。

使用特权

评论回复
cemaj| | 2015-11-29 22:31 | 显示全部楼层
这个精确吗

使用特权

评论回复
pmp| | 2015-11-30 06:10 | 显示全部楼层
用示波器测量过?

使用特权

评论回复
haolaishi| | 2015-11-30 11:58 | 显示全部楼层
xyz549040622 发表于 2015-11-25 17:22
再次说明,这个延时确实要精确计算的,毕竟只是粗略延时,us级别,ms级别,s级别的参数都是不同的,现在做 ...

我试了试,只有这个2ms准确点,其他的误差就很大了,不知道为什么

使用特权

评论回复
linlovelife| | 2016-1-15 13:41 | 显示全部楼层
学习了!

使用特权

评论回复
vivilzb1985| | 2016-1-15 22:32 | 显示全部楼层
弱弱的问一句的,这个时钟的采用哪一个的?

使用特权

评论回复
lzyyoumuren| | 2016-1-26 16:55 | 显示全部楼层
用定时器定时一般比较准确

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:qq群: 嵌入式系统arm初学者 224636155←← +→→点击-->小 i 精品课全集,21ic公开课~~←←→→点击-->小 i 精品课全集,给你全方位的技能策划~~←←

2650

主题

19066

帖子

102

粉丝