芯片支持使用内部振荡源, 或使用外置12MHz晶体
经过PLL倍频后为系统提供输入
倍频后的PLL时钟频率可通过寄存器进行配置,可选频率为:108MHz, 120MHz, 132MHz, 144MHz, 156MHz, 168MHz, 180MHz, 192MHz, 204MHz
PLL_CLK
FCLK / CPU_CLK
HCLK
PCLK
QSPI
芯片安全区基于内部32KHz,RTC默认基于内部OSC 32K, 使用外部XTAL 32K需要软件切换
支持内部或外部32KHz输出
以下代码基于 air105_project 的库函数
寄存器手册 Air105芯片数据手册_1.1.pdf
寄存器的基础地址, 定义在 air105.h
#define AIR105_FLASH_BASE (0x01000000UL) /*!< (FLASH ) Base Address */
#define AIR105_SRAM_BASE (0x20000000UL) /*!< (SRAM ) Base Address */
#define AIR105_PERIPH_BASE (0x40000000UL) /*!< (Peripheral) Base Address */
#define AIR105_AHB_BASE (AIR105_PERIPH_BASE)
#define AIR105_APB0_BASE (AIR105_PERIPH_BASE + 0x10000)
#define SYSCTRL_BASE (AIR105_APB0_BASE + 0xF000)
SYSCTRL_BASE
振荡源选择
SYSCTRL_SYSCLKSourceSelect(SELECT_EXT12M);
12MHz 时钟来源选择: 0:片外 XTAL, 1:片内 OSC
void SYSCTRL_SYSCLKSourceSelect(SYSCLK_SOURCE_TypeDef source)
{
assert_param(IS_SYSCLK_SOURCE(source));
switch (source)
{
case SELECT_EXT12M:
// FREQ_SEL 是一个32bit的寄存器, 先与补码(清零第12位), 然后写入值(0)
SYSCTRL->FREQ_SEL = ((SYSCTRL->FREQ_SEL & (~SYSCTRL_FREQ_SEL_CLOCK_SOURCE_Mask)) | SYSCTRL_FREQ_SEL_CLOCK_SOURCE_EXT);
break;
case SELECT_INC12M:
// 先与补码(清零第12位), 然后写入值(1)
SYSCTRL->FREQ_SEL = ((SYSCTRL->FREQ_SEL & (~SYSCTRL_FREQ_SEL_CLOCK_SOURCE_Mask)) | SYSCTRL_FREQ_SEL_CLOCK_SOURCE_INC);
break;
}
}
设置使用默认的内部时钟HSI(Internal clock)
void SystemClock_Config_HSI(void)
{
// 设置CPU频率, 直接选择, 不需要计算
SYSCTRL_PLLConfig(SYSCTRL_PLL_204MHz);
// 分频后产生 FCLK -> 这是主程序的时钟
SYSCTRL_PLLDivConfig(SYSCTRL_PLL_Div_None);
// 分频产生 HCLK, 如果 FCLK > 102MHz 则无论如何设置, 都会被二分频
SYSCTRL_HCLKConfig(SYSCTRL_HCLK_Div2);
// 分频产生 PCLK -> 这是大部分外设的时钟
SYSCTRL_PCLKConfig(SYSCTRL_PCLK_Div2);
QSPI_SetLatency((uint32_t)0);
}
PLL分频的选项
#define SYSCTRL_PLL_Div_None ((uint32_t)0x00)
#define SYSCTRL_PLL_Div2 ((uint32_t)0x01)
#define SYSCTRL_PLL_Div4 ((uint32_t)0x10)
void Delay_Init(void)
{
SYSCTRL_ClocksTypeDef clocks;
SYSCTRL_GetClocksFreq(&clocks);
SysTick_Config(clocks.CPU_Frequency / 1000000); ///< 1us
}
调用 SysTick_Config 将单个 SysTick 设置为 1 us.
也可以直接使用SYSCTRL->HCLK_1MS_VAL * 2 / 1000
这个变量代表了当前时钟配置下, 1ms需要的HCLK时钟周期, 根据当前FCLK是否大于108MHz 确定是否要乘以2.
之后就会每隔1us调用 SysTick_Handler(void), 在这里设置 32bit g_current_tick 递增, 可以用于延时控制. 因为32bit数的限制, 1.2个小时后会溢出, 所以这里有一个延迟的极限.
void SysTick_Handler(void)
{
g_current_tick++;
}
为避免溢出造成的延迟错误, 需要做一个判断
uint32_t get_diff_tick(uint32_t cur_tick, uint32_t prior_tick)
{
if (cur_tick < prior_tick)
{
// 如果当前值比前值还小, 说明发生了溢出, 用当前值加上原值取反(即原值离溢出的距离)
return (cur_tick + (~prior_tick));
}
else
{
return (cur_tick - prior_tick);
}
}
延迟的函数
void Delay_us(uint32_t usec)
{
uint32_t old_tick;
old_tick = g_current_tick;
while (get_diff_tick(g_current_tick, old_tick) < usec);
}
void Delay_ms(uint32_t msec)
{
uint32_t old_tick;
old_tick = g_current_tick;
while (get_diff_tick(g_current_tick, old_tick) < (msec * 1000));
}
代码地址: https://gitee.com/iosetting/air105_project
可以使用Keil5 MDK 直接打开 Demos 目录下的示例项目, 与Air105开发板接线参考前一篇合宙AIR105(一): Keil MDK开发环境, DAP-Link 烧录和调试
手机扫一扫
移动阅读更方便
你可能感兴趣的文章