我试图理解以下两个表达式之间的区别,然后尝试在我的代码中使用:
第一
#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);
第二
extern void SysCtlClockSet(unsigned long ulConfig);
SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
我看到的SysCtlClockSet的定义是:
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? 请帮我理解这个。
答案 0 :(得分:1)
一个是通过表或函数指针(表名ROM_SYSCTLTABLE
)定义的。你的函数是表中的第24个,因此值23(第一个有索引0)。
其他是通过符号表中的条目定义为外部定义的函数。
两者都是可互换的,因为指针等于你的extern函数的地址,但情况可能并非总是如此。该表类似于中断向量表,在访问某些低级函数(驱动程序等)时常用。
答案 1 :(得分: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);