新手上路
- 积分
- 49
- 金钱
- 49
- 注册时间
- 2016-3-1
- 在线时间
- 13 小时
|
1金钱
问题:单片机使用内部高速时钟,Systick不准确:
单片机型号:STM32F103C8T6
1./main 函数设置如下:
- int main(void)
- {
- RCC_Configuration();
- RCC_ClocksTypeDef get_rcc_clock; //获取系统时钟状态
- RCC_GetClocksFreq(&get_rcc_clock); //仿真的时候就可以在结构体get_rcc_clock中看见各个外设的时钟了
- delay_init(); //延时函数初始化
- delay_ms(1000);
复制代码 2./RCC配置函数:
- /*
- 描述:使用HSI作为PLL的输入时钟
- 注意:1.需要注释SystemInit()函数及相关配置
- 2.使用HSI进行PLL后最高频率只能到64M,不能使用72M
- PLL = SYSCLK = HCLK = PCLK2 = 36M
- PCLK1= HCLK/2 = 36M
- */
- void RCC_Configuration(void)
- {
- RCC_DeInit();//将外设 RCC寄存器重设为缺省值
-
- RCC_HSICmd(ENABLE);//使能HSI
- while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);//等待HSI使能成功
-
- //FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
- //FLASH_SetLatency(FLASH_Latency_2);
-
- RCC_HCLKConfig(RCC_SYSCLK_Div1);//配置AHB时钟频率与系统时钟频率一致 8M
- RCC_PCLK1Config(RCC_HCLK_Div2);//配置APB1低速时钟频率为AHB时钟频率的1/2 4M
- RCC_PCLK2Config(RCC_HCLK_Div1);//配置APB2高速时钟频率与AHB时钟频率一致 8M
-
- //设置 PLL 时钟源及倍频系数
- //将内部晶振时钟2分频后作为PLL时钟源,倍频系数为9(即系统时钟为36MHz)
- RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9);//使能或者失能 PLL,这个参数可以取:ENABLE或者DISABLE
- RCC_PLLCmd(ENABLE);//如果PLL被用于系统时钟,那么它不能被失能
- //等待指定的 RCC 标志位设置成功 等待PLL初始化成功
- while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
-
- //设置系统时钟(SYSCLK) 设置PLL为系统时钟源
- RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//选择想要的系统时钟
- //等待PLL成功用作于系统时钟的时钟源
- // 0x00:HSI 作为系统时钟
- // 0x04:HSE作为系统时钟
- // 0x08:PLL作为系统时钟
- while(RCC_GetSYSCLKSource() != 0x08);//需与被选择的系统时钟对应起来,RCC_SYSCLKSource_PLL
- }
复制代码 3./delay_init() 设置,
- ///初始化延迟函数
- //当使用ucos的时候,此函数会初始化ucos的时钟节拍
- //SYSTICK的时钟固定为HCLK时钟的1/8
- //SYSCLK:系统时钟
- void delay_init()
- {
- #ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.
- u32 reload;
- #endif
- SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //systick的时钟频率是36/8Mhz; HCLK/8
- fac_us=<font color="#ff0000"><b>SystemCoreClock</b></font>/8000000; //为系统时钟的1/8
- // SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); //选择外部时钟 HCLK/8
- // fac_us=SystemCoreClock; //为系统时钟的1/8
-
- #ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.
- reload=SystemCoreClock/8000000; //每秒钟的计数次数 单位为K
- reload*=1000000/OS_TICKS_PER_SEC;//根据OS_TICKS_PER_SEC设定溢出时间
- //reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右
- fac_ms=1000/OS_TICKS_PER_SEC;//代表ucos可以延时的最少单位
- SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断
- SysTick->LOAD=reload; //每1/OS_TICKS_PER_SEC秒中断一次
- SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
- #else
- fac_ms=(u16)fac_us*1000;//非ucos下,代表每个ms需要的systick时钟数
- #endif
- }
复制代码 4./跟踪SystemCoreClock,发现其依然为72M,
5./将其手动改为36M
- SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //systick的时钟频率是36/8Mhz; HCLK/8
- fac_us=36000000/8000000; //为系统时钟的1/8
复制代码 6./测试发现时间差了好多:800ms左右,与设定值1000ms差太多
大循环:
- while(1)
- {
- delay_ms(1000);//等待接收中断
- LED3_REV;
复制代码
|
最佳答案
查看完整内容[请看2#楼]
找到答案:
36除以8==4.5,而fac_us是整型,所以计时会出现偏差!!!
将系统时钟设置为48M,再次测试,延时准确!
新的问题:能否通过某个变量灵活的设置SystemCoreClock???
|