PIC32MX 系统时钟是预期的一半 Value/Harmony

PIC32MX System clock half of expected Value/Harmony

我最近在一家新公司开始工作,那里进行 PIC32 编程的程序员现在不在了,我确实需要对他的 uC 代码进行故障排除。

他不喜欢 Microchip Harmony Configurator/Framework,因此他只使用 Harmony 框架的外设库进行编码(这意味着他在代码中使用了很多 PLIB_* 函数,取自示例) . 为此,他从 framework/system/devcon/src 中提取了 sys_devcon.c 和 sys_devcon.h 文件,并将该文件复制到项目的源代码中。

现在我的问题是: 下面是 device.cfg。引脚 OSC1 和 OSC2 连接到主振荡器 (4MHz)。我们已经通过使用 LeCroy Teledyne(显示 4MHz)对其进行测试来确认振荡器工作正常。 使用文件给出的配置,系统时钟 (SYSCLK) 由 SYSPLL 派生。由于我的 IDIV 是 1,我的 MULT 是 18,我的 ODIV 是 1,我希望 SYSCLK 在 72MHz (4/1*18/1=72) 时达到 运行。 PBDIV 设置为 DIV_2(因此 PBCLK=SYSCLK/2 -> 36MHz)。 REFCLK 预计在 6.4MHz 时 运行。

但是: 测得的 PBCLK 显示 18MHz,测得的 REFCLK(SYSPLL 为 F_REFIN,显示 3.2MHz,这意味着 SYSCLK 只有 运行s 36MHz(不是预期的 72MHz)。但是考虑到配置应该 运行 两倍快。我无法找到为什么 SYSCLK 运行 半速的问题。

我对代码中的每个 PLIB_OSC*(包括 PLIB_OSC_SLEW*)函数进行了故障排除,但没有发现任何问题(只有 5 行使用某种 PLIB_OSC*职能)。也许有人得到了一些 ideas/hints 来进行故障排除。也不清楚 SYSCLK 是否实际上减半,或者在 SYSPLL 之后(在 REFCLK 和 PBCLK 之间)是否有一些分频器。有什么方法可以测量 SYSCLK 吗?

uC:PIC32MX174F256B XC-版本:V2.10 Harmony:V2.05.01(仅使用PLIB) MPLAB X IDE:v4.20

#ifndef PIC32MX174F256B_CONFIG_HEADER

#define PIC32MX174F256B_CONFIG_HEADER


#ifdef __cplusplus
extern "C" {
#endif

/* PIC32MX174F256B Configuration Bit Settings */


// DEVCFG3
// USERID = No Setting

// Alternate I/O Select for I2C1 (I2C1 uses the SDA1/SCL1 pins)
#pragma config AI2C1 = OFF

// Alternate I/O Select for I2C2 (I2C2 uses the SDA2/SCL2 pins)  
#pragma config AI2C2 = OFF              
#pragma config PMDL1WAY = OFF            // Peripheral Module Enable Configuration
#pragma config IOL1WAY = OFF             // Peripheral Pin Select Configuration (Allow reconfigurations)

// DEVCFG2
#pragma config FPLLIDIV = DIV_1         // PLL Input Divider (1x Divider)
#pragma config FPLLMUL = MUL_18         // PLL Multiplier (18x Multiplier)
#pragma config FPLLICLK = PLL_POSC      // System PLL Input Clock Selection (POSC is input to the System PLL)
#pragma config FPLLODIV = DIV_1         // System PLL Output Clock Divider (PLL Divide by 1)
#pragma config BOREN = ON               // Brown-Out Reset (BOR) Enable (Enable BOR)
#pragma config DSBOREN = ON             // Deep Sleep BOR Enable (Enable ZPBOR during Deep Sleep Mode)
#pragma config DSWDTPS = DSPS7         // Deep Sleep Watchdog Timer Postscaler (1:2^11)
#pragma config DSWDTOSC = LPRC          // Deep Sleep WDT Reference Clock Selection (Select LPRC as
                                        // DSWDT Reference clock)
#pragma config DSWDTEN = OFF            // Deep Sleep Watchdog Timer Enable (Disable DSWDT during
                                        // Deep Sleep Mode)
#pragma config FDSEN = ON               // Deep Sleep Enable (Enable DSEN bit in DSCON)

// DEVCFG1
#pragma config FNOSC = SPLL             // Oscillator Selection Bits (Primary Osc (HS,EC, XT))
#pragma config FSOSCEN = OFF            // Secondary Oscillator Enable (Disabled)
#pragma config IESO = OFF                // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = XT             // Primary Oscillator Configuration (XT osc mode)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)

// value can also be adjusted in module sys_system from libpic32mx174f256b
#pragma config FPBDIV = DIV_2           // Peripheral Clock Divisor

#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 WDTSPGM = ON             // Watchdog Timer Stop During Flash Programming (Watchdog
                                        // Timer stops during Flash programming)
#pragma config WINDIS = OFF             // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
#pragma config FWDTWINSZ = WINSZ_25     // Watchdog Timer Window Size (Window Size is 25%)

// DEVCFG0
#pragma config JTAGEN = OFF             // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx2        // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2)
#pragma config PWP = OFF                // Program Flash Write Protect (Disable)
#pragma config SMCLR = MCLR_NORM        // Soft Master Clear Enable (MCLR pin generates a normal system Reset)
#pragma config BWP = OFF                // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF                 // Code Protect (Protection Disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

我可能发现了问题: 设备数据 sheet 指出: 0-72 MHz 操作需要“3”个等待状态

然而,sys_devcon.c 只定义了 0-2 种等待状态。但不仅如此,它实际上不会定义任何等待状态,因为没有定义#if defined(PLIB_PCACHE_ExistsWaitState)。

 #if defined(PLIB_PCACHE_ExistsWaitState)
if (PLIB_PCACHE_ExistsWaitState(PCACHE_ID_0))
{
    int ws; /* number of wait states */
    if (sysclk <= 30000000)
        ws = 0;
    else if (sysclk <= 60000000)
        ws = 1;
    else
        ws = 2;

    /* Interrupts must be disabled when changing wait states */
    int_flag = (bool)(PLIB_INT_GetStateAndDisable( INT_ID_0 ) & 0x01);

    PLIB_PCACHE_WaitStateSet(PCACHE_ID_0, ws);

    if (int_flag)
    {
        PLIB_INT_Enable(INT_ID_0);
        int_flag = false;
    }
}
#endif // defined(PLIB_PCACHE_ExistsWaitState)

不过, #if defined(PLIB_PCACHE_ExistsWaitState) 未定义,因此它永远不会分配等待状态。 我是简单地用 #define PLIB_PCACHE_ExistsWaitState 定义它还是 运行 会出错?

我终于自己解决了这个问题

这只是我缺乏知识。我在 2 个单独的数据表中找到了关键信息。

其中之一是第 318 页的 "PIC32MX1XX/2XX 28/44-PIN XLP FAMILY Data Sheet",其中规定最大 SPICLK 不得超过 25MHz(我相信 .

第二个关键信息是波特率的计算。 我认为波特率等于所选的 PBCLK(所以当我有一个 72MHz 的 SYSCLK 并且 PBCLK 是 SYSCLK=PBCLK/2 => 36MHz 时,波特率也设置为 36MHz)。 但是在第 23-29 页 "PIC32 FRM Section 23. Serial Peripheral Interface (SPI)" 有公式 F_SCK = F_PB / ( 2 ⋅ ( SPIxBRG + 1 ))