打印
[PIC32/SAM]

关于PIC32延时程序的问题

[复制链接]
1271|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
cawyai23|  楼主 | 2019-4-10 17:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 cawyai23 于 2019-4-16 15:34 编辑

各位大神老师好:
请教一个问题。据说PIC32单片机的延时,可以用内部计数器进行延时。我想延时2us,但是,死活都不能达到2us,示波器显示是40us。示波器用的是虚拟示波器。系统时钟是40Mhz
也就是说,当我用 delay_us(2) 的时候,虚拟示波器显示的时间是 40us。还是说,必须用定时器才能达到1us的延时?
请问,怎么才能如同STM32单片机那样,可以实现1uS啊?还恳请会的大神给出代码主控芯片是 芯片型号是PIC32MX795F512L ,晶振是8M。



#define SYSCLK_FREQUENCY       40000000     //* 200MHz,修改成你自己的系统时钟 
#define PBCLK7_FREQUENCY        SYSCLK_FREQUENCY
#define CORE_TIMER_FREQUENCY        (PBCLK7_FREQUENCY / 2)
#define CORE_TIMER_MILLISECONDS     (CORE_TIMER_FREQUENCY / 100)
#define CORE_TIMER_MICROSECONDS     (CORE_TIMER_FREQUENCY / 10000)

unsigned int __attribute__((nomips16)) ReadCoreTimer(void)
{
    unsigned int timer;

    asm volatile("mfc0   %0, $9" : "=r"(timer));

    return timer;
}

void delay_us(unsigned int delayUs)
{
    unsigned int delayStart;

    delayStart = ReadCoreTimer();
    while ((ReadCoreTimer() - delayStart) < (delayUs * CORE_TIMER_MICROSECONDS));
}

void delay_ms(unsigned int delayUs)
{
    unsigned int delayStart;

    delayStart = ReadCoreTimer();
    while ((ReadCoreTimer() - delayStart) < (delayUs * CORE_TIMER_MILLISECONDS));
}


以下是配置位设置

/******************* 配置位设置 ******************************/
// DEVCFG3
// USERID = No                                                           //Setting


#pragma config FSRSSEL = PRIORITY_7                 // SRS Select (SRS Priority 7)
#pragma config FMIIEN = OFF                                // Ethernet RMII/MII Enable (RMII Enabled)
#pragma config FETHIO = OFF                               // Ethernet I/O Pin Select (Alternate Ethernet I/O)
#pragma config FCANIO = OFF                               // CAN I/O Pin Select (Alternate CAN I/O)
#pragma config FUSBIDIO = ON                             // USB USID Selection (Controlled by the USB Module)
#pragma config FVBUSONIO = ON                         // USB VBUS ON Selection (Controlled by USB Module)

// DEVCFG2
#pragma config FPLLIDIV = DIV_2                       // PLL Input Divider (2x Divider)
#pragma config FPLLMUL = MUL_20                  // PLL Multiplier (20x Multiplier)
#pragma config UPLLIDIV = DIV_1                     // USB PLL Input Divider (12x Divider)
#pragma config UPLLEN = OFF                          // USB PLL Enable (Disabled and Bypassed)
#pragma config FPLLODIV = DIV_2                    // System PLL Output Clock Divider (PLL Divide by 1)
                                                                           // SYSCLK = (8MHz Crystal/ FPLLIDIV * FPLLMUL / FPLLODIV)=40M
// DEVCFG1
#pragma config FNOSC = PRIPLL                      // Oscillator Selection Bits (Fast RC Osc with PLL)
#pragma config FSOSCEN = ON                       // Secondary Oscillator Enable (Disabled)
#pragma config IESO = ON                              // Internal/External Switch Over (Disabled)
#pragma config POSCMOD = HS                      // Primary Oscillator Configuration (HS osc mode)
#pragma config OSCIOFNC = OFF                   // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_1                    // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/8)=5M
#pragma config FCKSM = CSDCMD                // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled)
#pragma config WDTPS = PS1                       // Watchdog Timer Postscaler (1:1)
#pragma config FWDTEN = OFF                    // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))

// DEVCFG0
#pragma config DEBUG = ON                         // Background Debugger Enable (Debugger is enabled)
#pragma config ICESEL = ICS_PGx1             // ICE/ICD Comm Channel Select (ICE EMUC1/EMUD1 pins shared with PGC1/PGD1)
#pragma config PWP = PWP512K                 // Program Flash Write Protect (First 512K)
#pragma config BWP = ON                           // Boot Flash Write Protect bit (Protection Enabled)
#pragma config CP = ON                             // Code Protect (Protection Enabled)

//*************** 宏定义 *******************************************************
如果配置位配置不正确,恳请各位大神明确指出,谢谢!

@麦小播@Superflash213 @ MCHPMPU  

使用特权

评论回复
沙发
请叫我树人| | 2019-4-11 08:37 | 只看该作者
好帖子啊!帮你顶住啊!感谢分享啊! 真是不错啊!

使用特权

评论回复
板凳
xuanhuanzi| | 2019-4-11 14:55 | 只看该作者
楼上是个**

使用特权

评论回复
地板
xuanhuanzi| | 2019-4-11 14:56 | 只看该作者
2us为何延时不了?
你心理没数啊?

使用特权

评论回复
5
xuanhuanzi| | 2019-4-11 14:56 | 只看该作者
你操作配置单时间都超过2us
这种直接用软延时就行了。

使用特权

评论回复
6
943614033| | 2019-4-12 09:01 | 只看该作者
飞机刚起飞,往地下一看,我KAO,过站了。。。

使用特权

评论回复
7
cawyai23|  楼主 | 2019-4-12 10:51 | 只看该作者
xuanhuanzi 发表于 2019-4-11 14:56
你操作配置单时间都超过2us
这种直接用软延时就行了。

大神,软延时怎么弄?求指教
能发个例程吗?

使用特权

评论回复
8
pic32fans| | 2019-4-15 10:19 | 只看该作者
cawyai23 发表于 2019-4-12 10:51
大神,软延时怎么弄?求指教
能发个例程吗?

问题贴里带有芯片完整型号、系统配置(尤其时钟),最好有完整工程,这样应该能更好的帮助你。

从你的信息看,40MHz系统频率,按Core timer为系统时钟除以2,那么1us就,20个core timer周期(40个指令周期),2us也就是80个指令周期;函数进出需要的时间需要剔除才能得到精准时间,所以应该输入参数需要微调才能准确。

不过你的测试相差太大,更多应该是时钟配置可能不对导致。

使用特权

评论回复
9
internally| | 2019-4-15 21:20 | 只看该作者
调一个库函数都超过这个时间了

使用特权

评论回复
10
cawyai23|  楼主 | 2019-4-16 15:31 | 只看该作者
pic32fans 发表于 2019-4-15 10:19
问题贴里带有芯片完整型号、系统配置(尤其时钟),最好有完整工程,这样应该能更好的帮助你。

从你的信 ...

芯片型号是PIC32MX795F512L ,晶振是8M。
/******************* 配置位设置 ******************************/
// DEVCFG3
// USERID = No //Setting


#pragma config FSRSSEL = PRIORITY_7     // SRS Select (SRS Priority 7)
#pragma config FMIIEN = OFF             // Ethernet RMII/MII Enable (RMII Enabled)
#pragma config FETHIO = OFF             // Ethernet I/O Pin Select (Alternate Ethernet I/O)
#pragma config FCANIO = OFF             // CAN I/O Pin Select (Alternate CAN I/O)
#pragma config FUSBIDIO = ON            // USB USID Selection (Controlled by the USB Module)
#pragma config FVBUSONIO = ON           // USB VBUS ON Selection (Controlled by USB Module)

// DEVCFG2
#pragma config FPLLIDIV = DIV_2         // PLL Input Divider (2x Divider)
#pragma config FPLLMUL = MUL_20         // PLL Multiplier (20x Multiplier)
#pragma config UPLLIDIV = DIV_1         // USB PLL Input Divider (12x Divider)
#pragma config UPLLEN = OFF             // USB PLL Enable (Disabled and Bypassed)
#pragma config FPLLODIV = DIV_2         // System PLL Output Clock Divider (PLL Divide by 1)
                                        // SYSCLK = (8MHz Crystal/ FPLLIDIV * FPLLMUL / FPLLODIV)=40M
// DEVCFG1
#pragma config FNOSC = PRIPLL             // Oscillator Selection Bits (Fast RC Osc with PLL)
#pragma config FSOSCEN = ON            // Secondary Oscillator Enable (Disabled)
#pragma config IESO = ON                // Internal/External Switch Over (Disabled)
#pragma config POSCMOD = HS             // Primary Oscillator Configuration (HS osc mode)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_1           // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/8)=5M
#pragma config FCKSM = CSDCMD           // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled)
#pragma config WDTPS = PS1              // Watchdog Timer Postscaler (1:1)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))

// DEVCFG0
#pragma config DEBUG = ON               // Background Debugger Enable (Debugger is enabled)
#pragma config ICESEL = ICS_PGx1        // ICE/ICD Comm Channel Select (ICE EMUC1/EMUD1 pins shared with PGC1/PGD1)
#pragma config PWP = PWP512K            // Program Flash Write Protect (First 512K)
#pragma config BWP = ON                 // Boot Flash Write Protect bit (Protection Enabled)
#pragma config CP = ON                  // Code Protect (Protection Enabled)

//*************** 宏定义 *******************************************************

使用特权

评论回复
11
cawyai23|  楼主 | 2019-4-16 15:36 | 只看该作者
pic32fans 发表于 2019-4-15 10:19
问题贴里带有芯片完整型号、系统配置(尤其时钟),最好有完整工程,这样应该能更好的帮助你。

从你的信 ...

谢谢大神指点提问方式,我已经重新编辑问题了。恳请大神看看

使用特权

评论回复
12
cawyai23|  楼主 | 2019-4-16 15:36 | 只看该作者
internally 发表于 2019-4-15 21:20
调一个库函数都超过这个时间了

哦哦!谢谢大神指点。请问大神,有没有其他方式能延时us级别的?

使用特权

评论回复
13
pic32fans| | 2019-4-19 11:43 | 只看该作者
cawyai23 发表于 2019-4-16 15:36
谢谢大神指点提问方式,我已经重新编辑问题了。恳请大神看看

你可以试试如下方法:
void sys40m_delay_1us(void)
{
    unsigned long t0 = _CP0_GET_COUNT();
    {
        while (_CP0_GET_COUNT() - t0 < (40/2)); // 为了补偿函数进出指令耗费的时间,这里数字需要微调一下去测量是否精确1us
    }   
}

使用特权

评论回复
14
Rock007| | 2019-4-19 14:28 | 只看该作者
如果是确定的2微秒,不需要调整时间,可以用固定个数的_nop

使用特权

评论回复
15
cawyai23|  楼主 | 2019-5-7 15:30 | 只看该作者
本帖最后由 cawyai23 于 2019-5-7 15:32 编辑
pic32fans 发表于 2019-4-19 11:43
你可以试试如下方法:
void sys40m_delay_1us(void)
{

谢谢大神指点,但在我现在配置的情况下,用这个函数,目前只能停留在5us,其中,我把 “40/2”这个直接改为1。虚拟示波器测得的波形是5us。
   while (_CP0_GET_COUNT()-t0 < 1);

是不是我要把晶振更换一下啊?我的晶振用的是8M的。晶振两脚上的电容用的是22pf。

使用特权

评论回复
16
cawyai23|  楼主 | 2019-5-7 15:34 | 只看该作者
Rock007 发表于 2019-4-19 14:28
如果是确定的2微秒,不需要调整时间,可以用固定个数的_nop

这个us级别延时,需要随时更改延时时间

使用特权

评论回复
17
scottmaxwell| | 2019-5-7 15:55 | 只看该作者
先关全局中断,在插入nop空操作,再开全局中断,微调里L面nop个数,应该可以完成实现,还有不要用函数,用宏实现,因为函数调用时间并不可控,每次可能有些差别。

使用特权

评论回复
18
cawyai23|  楼主 | 2019-5-8 12:46 | 只看该作者
scottmaxwell 发表于 2019-5-7 15:55
先关全局中断,在插入nop空操作,再开全局中断,微调里L面nop个数,应该可以完成实现,还有不要用函数,用 ...

谢谢大神的指点,但我这个,延时时间是可变的,也许这次是2us,下次就是20us,延时时间不定。

使用特权

评论回复
19
pic32fans| | 2019-5-10 15:39 | 只看该作者
cawyai23 发表于 2019-5-8 12:46
谢谢大神的指点,但我这个,延时时间是可变的,也许这次是2us,下次就是20us,延时时间不定。 ...

两个建议:
1,频率提高到80MHz去调整;
2,编译优化级别提高一下去测试;

使用特权

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

本版积分规则

12

主题

78

帖子

0

粉丝