2014-12-30 67 views
1

我想了解以下两个表达式之间的差别,并随后试图在我的代码使用方法:试图了解函数指针使用此代码

首先

#define ROM_SysCtlClockSet ((void (*)(unsigned long ulConfig))ROM_SYSCTLTABLE[23]) 

// Set the clocking to run at 50 MHz from the PLL. 
    // 

ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | 
         SYSCTL_XTAL_16MHZ); 

的SysCtlClockSet的

extern void SysCtlClockSet(unsigned long ulConfig); 

SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN); 

定义因为我看到的是:

void 
SysCtlClockSet(unsigned long ulConfig) 
{ 
    unsigned long ulDelay, ulRCC, ulRCC2; 

    // 
    // See if this is a Sandstorm-class device and clocking features from newer 
    // devices were requested. 
    // 
    if(CLASS_IS_SANDSTORM && (ulConfig & SYSCTL_RCC2_USERCC2)) 
    { 
     // 
     // Return without changing the clocking because the requested 
     // configuration can not be achieved. 
     // 
     return; 
    } 

    // 
    // Get the current value of the RCC and RCC2 registers. If using a 
    // Sandstorm-class device, the RCC2 register reads back as zero and the 
    // writes to it from within this function are ignored. 
    // 
    ulRCC = HWREG(SYSCTL_RCC); 
    ulRCC2 = HWREG(SYSCTL_RCC2); 

    // 
    // Bypass the PLL and system clock dividers for now. 
    // 
    ulRCC |= SYSCTL_RCC_BYPASS; 
    ulRCC &= ~(SYSCTL_RCC_USESYSDIV); 
    ulRCC2 |= SYSCTL_RCC2_BYPASS2; 

    // 
    // Write the new RCC value. 
    // 
    HWREG(SYSCTL_RCC) = ulRCC; 
    HWREG(SYSCTL_RCC2) = ulRCC2; 

    // 
    // See if either oscillator needs to be enabled. 
    // 
    if(((ulRCC & SYSCTL_RCC_IOSCDIS) && !(ulConfig & SYSCTL_RCC_IOSCDIS)) || 
     ((ulRCC & SYSCTL_RCC_MOSCDIS) && !(ulConfig & SYSCTL_RCC_MOSCDIS))) 
    { 
     // 
     // Make sure that the required oscillators are enabled. For now, the 
     // previously enabled oscillators must be enabled along with the newly 
     // requested oscillators. 
     // 
     ulRCC &= (~(SYSCTL_RCC_IOSCDIS | SYSCTL_RCC_MOSCDIS) | 
        (ulConfig & (SYSCTL_RCC_IOSCDIS | SYSCTL_RCC_MOSCDIS))); 

     // 
     // Write the new RCC value. 
     // 
     HWREG(SYSCTL_RCC) = ulRCC; 

     // 
     // Wait for a bit, giving the oscillator time to stabilize. The number 
     // of iterations is adjusted based on the current clock source; a 
     // smaller number of iterations is required for slower clock rates. 
     // 
     if(((ulRCC2 & SYSCTL_RCC2_USERCC2) && 
      (((ulRCC2 & SYSCTL_RCC2_OSCSRC2_M) == SYSCTL_RCC2_OSCSRC2_30) || 
      ((ulRCC2 & SYSCTL_RCC2_OSCSRC2_M) == SYSCTL_RCC2_OSCSRC2_32))) || 
      (!(ulRCC2 & SYSCTL_RCC2_USERCC2) && 
      ((ulRCC & SYSCTL_RCC_OSCSRC_M) == SYSCTL_RCC_OSCSRC_30))) 
     { 
      // 
      // Delay for 4096 iterations. 
      // 
      SysCtlDelay(4096); 
     } 
     else 
     { 
      // 
      // Delay for 524,288 iterations. 
      // 
      SysCtlDelay(524288); 
     } 
    } 

    // 
    // Set the new crystal value and oscillator source. Because the OSCSRC2 
    // field in RCC2 overlaps the XTAL field in RCC, the OSCSRC field has a 
    // special encoding within ulConfig to avoid the overlap. 
    // 
    ulRCC &= ~(SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M); 
    ulRCC |= ulConfig & (SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M); 
    ulRCC2 &= ~(SYSCTL_RCC2_USERCC2 | SYSCTL_RCC2_OSCSRC2_M); 
    ulRCC2 |= ulConfig & (SYSCTL_RCC2_USERCC2 | SYSCTL_RCC_OSCSRC_M); 
    ulRCC2 |= (ulConfig & 0x00000008) << 3; 

    // 
    // Write the new RCC value. 
    // 
    HWREG(SYSCTL_RCC) = ulRCC; 
    HWREG(SYSCTL_RCC2) = ulRCC2; 

    // 
    // Wait for a bit so that new crystal value and oscillator source can take 
    // effect. 
    // 
    SysCtlDelay(16); 

    // 
    // Set the PLL configuration. 
    // 
    ulRCC &= ~(SYSCTL_RCC_PWRDN | SYSCTL_RCC_OEN); 
    ulRCC |= ulConfig & (SYSCTL_RCC_PWRDN | SYSCTL_RCC_OEN); 
    ulRCC2 &= ~(SYSCTL_RCC2_PWRDN2); 
    ulRCC2 |= ulConfig & SYSCTL_RCC2_PWRDN2; 

    // 
    // Clear the PLL lock interrupt. 
    // 
    HWREG(SYSCTL_MISC) = SYSCTL_INT_PLL_LOCK; 

    // 
    // Write the new RCC value. 
    // 
    if(ulRCC2 & SYSCTL_RCC2_USERCC2) 
    { 
     HWREG(SYSCTL_RCC2) = ulRCC2; 
     HWREG(SYSCTL_RCC) = ulRCC; 
    } 
    else 
    { 
     HWREG(SYSCTL_RCC) = ulRCC; 
     HWREG(SYSCTL_RCC2) = ulRCC2; 
    } 

    // 
    // Set the requested system divider and disable the appropriate 
    // oscillators. This value is not written immediately. 
    // 
    ulRCC &= ~(SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV | 
       SYSCTL_RCC_IOSCDIS | SYSCTL_RCC_MOSCDIS); 
    ulRCC |= ulConfig & (SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV | 
         SYSCTL_RCC_IOSCDIS | SYSCTL_RCC_MOSCDIS); 
    ulRCC2 &= ~(SYSCTL_RCC2_SYSDIV2_M); 
    ulRCC2 |= ulConfig & SYSCTL_RCC2_SYSDIV2_M; 
    if(ulConfig & SYSCTL_RCC2_DIV400) 
    { 
     ulRCC |= SYSCTL_RCC_USESYSDIV; 
     ulRCC2 &= ~(SYSCTL_RCC_USESYSDIV); 
     ulRCC2 |= ulConfig & (SYSCTL_RCC2_DIV400 | SYSCTL_RCC2_SYSDIV2LSB); 
    } 
    else 
    { 
     ulRCC2 &= ~(SYSCTL_RCC2_DIV400); 
    } 

    // 
    // See if the PLL output is being used to clock the system. 
    // 
    if(!(ulConfig & SYSCTL_RCC_BYPASS)) 
    { 
     // 
     // Wait until the PLL has locked. 
     // 
     for(ulDelay = 32768; ulDelay > 0; ulDelay--) 
     { 
      if(HWREG(SYSCTL_RIS) & SYSCTL_INT_PLL_LOCK) 
      { 
       break; 
      } 
     } 

     // 
     // Enable use of the PLL. 
     // 
     ulRCC &= ~(SYSCTL_RCC_BYPASS); 
     ulRCC2 &= ~(SYSCTL_RCC2_BYPASS2); 
    } 

    // 
    // Write the final RCC value. 
    // 
    HWREG(SYSCTL_RCC) = ulRCC; 
    HWREG(SYSCTL_RCC2) = ulRCC2; 

    // 
    // Delay for a little bit so that the system divider takes effect. 
    // 
    SysCtlDelay(16); 
} 

在原来的代码中,我看到了两者的使用可以互换的。

第一个和第二个都用于设置时钟频率,但在第一个我看到这是一个宏。

因此,第一个达到与第二个相同的东西。宏扩展后第一应该成为

((void (*)(unsigned long ulConfig))ROM_SYSCTLTABLE[23]) 
(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | 
          SYSCTL_XTAL_16MHZ); 

这是什么意思?那里是23号? 请帮助我理解这一点。

回答

1

通过一个表或指向函数的指针(表名ROM_SYSCTLTABLE)定义一个函数。你的函数是表中的第24个,因此值为23(第一个索引为0)。

其他通过符号表中的条目定义为外部定义的函数。

两者都是可以互换的,因为指针等于您的extern函数的地址,但并非总是如此。该表是这样一个中断矢量表访问某些低电平功能(驱动器等)时所常用的。

0

ROM_SYSCTLTABLE是一个指针数组。

ROM_SYSCTLTABLE[23]是该数组内的第24个元素。

((void (*)(unsigned long ulConfig))ROM_SYSCTLTABLE[23])这部分转换该指针是void (*)(unsigned long ulConfig)类型,这是一个函数指针类型接受一个unsigned long参数和返回void。

然后调用函数:

((void (*)(unsigned long ulConfig))ROM_SYSCTLTABLE[23]) 
(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | 
          SYSCTL_XTAL_16MHZ);