[PIC32/SAM] 关于PIC32延时程序的问题

[复制链接]
2363|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。



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

  6. unsigned int __attribute__((nomips16)) ReadCoreTimer(void)
  7. {
  8.     unsigned int timer;

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

  10.     return timer;
  11. }

  12. void delay_us(unsigned int delayUs)
  13. {
  14.     unsigned int delayStart;

  15.     delayStart = ReadCoreTimer();
  16.     while ((ReadCoreTimer() - delayStart) < (delayUs * CORE_TIMER_MICROSECONDS));
  17. }

  18. void delay_ms(unsigned int delayUs)
  19. {
  20.     unsigned int delayStart;

  21.     delayStart = ReadCoreTimer();
  22.     while ((ReadCoreTimer() - delayStart) < (delayUs * CORE_TIMER_MILLISECONDS));
  23. }


以下是配置位设置

  1. /******************* 配置位设置 ******************************/
  2. // DEVCFG3
  3. // USERID = No                                                           //Setting


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

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

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

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

@麦小播@Superflash213 @ MCHPMPU  
请叫我树人 发表于 2019-4-11 08:37 | 显示全部楼层
好帖子啊!帮你顶住啊!感谢分享啊! 真是不错啊!
xuanhuanzi 发表于 2019-4-11 14:55 | 显示全部楼层
楼上是个**
xuanhuanzi 发表于 2019-4-11 14:56 | 显示全部楼层
2us为何延时不了?
你心理没数啊?
xuanhuanzi 发表于 2019-4-11 14:56 | 显示全部楼层
你操作配置单时间都超过2us
这种直接用软延时就行了。
943614033 发表于 2019-4-12 09:01 | 显示全部楼层
飞机刚起飞,往地下一看,我KAO,过站了。。。
 楼主| cawyai23 发表于 2019-4-12 10:51 | 显示全部楼层
xuanhuanzi 发表于 2019-4-11 14:56
你操作配置单时间都超过2us
这种直接用软延时就行了。

大神,软延时怎么弄?求指教
能发个例程吗?
pic32fans 发表于 2019-4-15 10:19 | 显示全部楼层
cawyai23 发表于 2019-4-12 10:51
大神,软延时怎么弄?求指教
能发个例程吗?

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

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

不过你的测试相差太大,更多应该是时钟配置可能不对导致。
internally 发表于 2019-4-15 21:20 | 显示全部楼层
调一个库函数都超过这个时间了
 楼主| cawyai23 发表于 2019-4-16 15:31 | 显示全部楼层
pic32fans 发表于 2019-4-15 10:19
问题贴里带有芯片完整型号、系统配置(尤其时钟),最好有完整工程,这样应该能更好的帮助你。

从你的信 ...

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


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

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

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

  33. //*************** 宏定义 *******************************************************
 楼主| cawyai23 发表于 2019-4-16 15:36 | 显示全部楼层
pic32fans 发表于 2019-4-15 10:19
问题贴里带有芯片完整型号、系统配置(尤其时钟),最好有完整工程,这样应该能更好的帮助你。

从你的信 ...

谢谢大神指点提问方式,我已经重新编辑问题了。恳请大神看看
 楼主| cawyai23 发表于 2019-4-16 15:36 | 显示全部楼层
internally 发表于 2019-4-15 21:20
调一个库函数都超过这个时间了

哦哦!谢谢大神指点。请问大神,有没有其他方式能延时us级别的?
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
    }   
}
Rock007 发表于 2019-4-19 14:28 | 显示全部楼层
如果是确定的2微秒,不需要调整时间,可以用固定个数的_nop
 楼主| 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。
  1.    while (_CP0_GET_COUNT()-t0 < 1);

是不是我要把晶振更换一下啊?我的晶振用的是8M的。晶振两脚上的电容用的是22pf。
 楼主| cawyai23 发表于 2019-5-7 15:34 | 显示全部楼层
Rock007 发表于 2019-4-19 14:28
如果是确定的2微秒,不需要调整时间,可以用固定个数的_nop

这个us级别延时,需要随时更改延时时间
scottmaxwell 发表于 2019-5-7 15:55 来自手机 | 显示全部楼层
先关全局中断,在插入nop空操作,再开全局中断,微调里L面nop个数,应该可以完成实现,还有不要用函数,用宏实现,因为函数调用时间并不可控,每次可能有些差别。
 楼主| cawyai23 发表于 2019-5-8 12:46 | 显示全部楼层
scottmaxwell 发表于 2019-5-7 15:55
先关全局中断,在插入nop空操作,再开全局中断,微调里L面nop个数,应该可以完成实现,还有不要用函数,用 ...

谢谢大神的指点,但我这个,延时时间是可变的,也许这次是2us,下次就是20us,延时时间不定。
pic32fans 发表于 2019-5-10 15:39 | 显示全部楼层
cawyai23 发表于 2019-5-8 12:46
谢谢大神的指点,但我这个,延时时间是可变的,也许这次是2us,下次就是20us,延时时间不定。 ...

两个建议:
1,频率提高到80MHz去调整;
2,编译优化级别提高一下去测试;
您需要登录后才可以回帖 登录 | 注册

本版积分规则

12

主题

78

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部