(一)时钟树解析
(1)Usermanual中时钟树解析
在是clock system中有着时钟的介绍
解释为:
时钟支持低功耗模式,可以配置为外部时钟和内部时钟。
介绍了不同的时钟源频率以及特殊时钟源支持的频率范围
系统时钟树的介绍以及可能的配置信息,说明MSP432主要的时钟有5种类,分别是:
(1)ACLK:辅助时钟,给一些特殊外设提供时钟;
(2)MCLK:CPU时钟,最高可以配置成48M
(3)HSMCLK:高速设备时钟,类似于STM32的AHB总线
(4)SMCLK:低速设备时钟,类似STM32的APB总线
(5)BCLK:低功耗时可能会用到,猜测是RTC唤醒时用到;
后边一小段话是注意事项,解释为某些特殊设备无法使用某些时钟
通过Usermanual时钟的介绍,大概可以理解MSP432的时钟树了,按照常规TI的做法,为了展示芯片的低功耗特点,这些芯片的时钟不会配置成最高的运行速度,电赛中显然不需要考虑功耗,我们需要强大的性能,所以在后边时钟树的配置中,我们让MSP432运行在他的最高速率(CPU),其他总线时钟视情况而定
(二)时钟树修改
在初始化的.s汇编文件中,我们可以看到在配置堆栈后执行了这些函数,如下(以我配置的空工程为例):
可见TI使用SystemInit()函数配置了时钟树,这个函数可以使用全局搜索检索到:
解释为:该函数配置了时钟,看门狗,FPU,使能SRAM块,配置Flash等待时间,缓冲区等等
然后在这个文件中可以找到此宏,这代表了全局的CPU时钟,这些就是基本的时钟信息,按照如下步骤我们对其重新配置:
(1)修改__SYSTEM_CLOCK宏为48000000
(2)使用配置函数进行时钟配置,参照TI的DriverLib中时钟配置例子进行配置:
//配置晶振pin
GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_PJ,
GPIO_PIN3 | GPIO_PIN2, GPIO_PRIMARY_MODULE_FUNCTION);
//设置时钟频率
CS_setExternalClockSourceFrequency(32000,48000000);
//设置内核电压 bank延迟
PCM_setCoreVoltageLevel(PCM_VCORE1);
FlashCtl_setWaitState(FLASH_BANK0, 1);
FlashCtl_setWaitState(FLASH_BANK1, 1);
CS_startHFXT(false);
//连接到外部时钟
CS_initClockSignal(CS_MCLK , CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);
CS_initClockSignal(CS_ACLK , CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
CS_initClockSignal(CS_HSMCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_2);
CS_initClockSignal(CS_SMCLK , CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_4);
CS_initClockSignal(CS_BCLK , CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
然后时钟就会工作在我们所需要的频率下:
然后可以使用函数获取时钟进行检验,注意变量的大小,我使用了自己构造的结构体获取,便于读取:
需要注意的是最好在我们重新配置完时钟后开启FPU,这样浮点计算就更便捷了:
//开fpu
FPU_enableModule();
FPU_enableLazyStacking();
在这里我直接将他封装成函数,在启动时进行调用:
如下:
(三)基于Systick的通用延时函数(cortexM通用)
在这里我使用systick作为基准来配置延时函数,便于调用:
H文件:
#ifndef NULL
#define NULL ((void *)0)
#endif
#define DELAY_CLK SystemCoreClock
#define USEC_TO_COUNT(us, clockFreqInHz) (uint64_t)(((uint64_t)(us) * (clockFreqInHz)) / 1000000U)
//------------------------------------以下宏定义用于延时------------------------------------
void systick_delay(uint32 time);
void systick_delay_ms(uint32 ms); // 毫秒级延时函数 由于滴答定时器最大只有24位,因此用函数实现,这样延时时间范围较宽
#define systick_delay_us(time) systick_delay(USEC_TO_COUNT(time, DELAY_CLK)) // 设置延时时间 单位us 范围0 - 16777215(0xffffff)/(DELAY_CLK*1000)ms 主频48M systick最大延时时间大约为16ms
#define delay_ms(x) systick_delay_ms(x)
#define delay_us(x) systick_delay_us(x)
C文件:
//延时函数 systick实现 时钟刻度为系统频率
void systick_delay(uint32 t)
{
SysTick-> CTRL = 0x00;
SysTick->LOAD = t - 1;
SysTick->VAL = 0x00;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | //时钟源选择 (core clk)
SysTick_CTRL_ENABLE_Msk; //使能 systick
while( !(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
}
//延时ms
void systick_delay_ms (uint32 time)
{
while(time--) systick_delay(SystemCoreClock / 1000);
}
然后可以使用上一个教程中的GPIO翻转函数检验延时的正确性,注意这种延时跟配置的时钟频率无关,是基于内核的,通用的,时钟树以及延时的讲解到此结束。
克隆空白工程请使用 git , 如果你觉得还不错欢迎点亮 star !
git clone https://github.com/YGZone/Design-a-car-with-MSP432P401R.git