×
单片机 > 单片机程序设计 > 详情

STM32下SysTick的一个容易发生的错误,时钟频率设置

发布时间:2020-08-31 发布时间:
|

今天同事测试我之前写的一个小程序,发生了奇怪的错误,先是Uart通讯接收操作,出现了接收数据不全的问题:2个字节的应答帧,在实际运行中只能收到1个字节,导致程序死循环。检查后发现,是接收部分代码留的延时太短,造成了芯片误以为通讯已结束,但实际应答帧尚未传输完毕。(此处接收代码的工作模式是:当Uart接收到1个字节后,即开始一个定长的延时,该延时长度与通讯波特率相关,当正常通讯还在继续时,则应在延时结束前收到下一个字节数据,如延时结束仍未收到下一个字节数据,说明当前一帧数据已完成,可开始对已接收数据进行处理)


发现了问题后,进行相应的针对性操作,对延时长度进行了增加,即解决了此问题。但仍然觉得疑惑,因此段程序是已经通过测试的,运行正常,不应突然出现这种奇怪的错误,因此怀疑芯片自身的延时程序存在问题。


而后此程序继续出现的错误证实了之前的怀疑:新出现的错误是显示部分程序的延时明显不够,因此可以断定是延时部分出了问题。此程序的延时功能由滴答定时器的1ms延时函数来实现,对该函数进行排查,果然发现了问题根源。


stm32的滴答定时器设置主要有以下寄存器:


其中SysTick->CTRL寄存器包含了对滴答定时器的时钟频率来源设置和分频设置。前述小程序中,采用的是STM32F107芯片,外部时钟,工作频率为72MHz,在此程序中,为了让滴答定时器的工作压力稍减,使用了8分频的时钟设置,计数(72000000/8000)=9000,时长为1ms。代码如下:


void SystemTick_Configuration(void)

{

    RCC_ClocksTypeDef RCC_Clocks;

 

    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);

    RCC_GetClocksFreq(&RCC_Clocks);

    // SystTick configuration: an interrupt every 1 ms

    if(SysTick_Config(RCC_Clocks.SYSCLK_Frequency / 8000))

    {

        while(1) FEED_WWDG;

    }

}


此程序在我的电脑编译下是正常工作的,但在同事电脑编译下出了问题,滴答定时器的延时明显缩短,原因在于core_cm3.h文件。此文件位置在C:\Keil\ARM\CMSIS\Include文件夹下,此文件中的SysTick_Config函数包含以下操作:


static __INLINE uint32_t SysTick_Config(uint32_t ticks)

{

  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */

 

  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */

  NVIC_SetPriority (SysTick_IRQn, (1<<__nvic_prio_bits set priority for cortex-m0 system interrupts>

  SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */

  SysTick->CTRL  |= SysTick_CTRL_CLKSOURCE_Msk |

                   SysTick_CTRL_TICKINT_Msk   |

                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */

  return (0);                                                  /* Function successful */

}


此处对滴答定时器的时钟来源进行了操作,使其恢复了最高频率(72MHz),不分频:

SysTick->CTRL  |= SysTick_CTRL_CLKSOURCE_Msk |

在我的电脑上,因为对core_cm3.h文件做了以下修改,屏蔽了其对滴答定时器时钟的操作,所以可以正常运行:

SysTick->CTRL  |= //SysTick_CTRL_CLKSOURCE_Msk |

但在同事的电脑上没有做此操作,从而导致了1ms延时实际只有0.125ms,于是出现了前述的种种错误。


解决办法:


1、使用滴答定时器时,不再考虑减轻芯片负担,直接采用原始频率,可以保证不会出现此问题。


2、修改文件调用指向,不调用工程外的相关头文件,防止出现移植时,不同电脑间,工程外文件的不同导致的错误。




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
C51 特殊功能寄存器SFR的名称和地址