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

来源:互联网 发布:淘宝新手运营 编辑:程序博客网 时间:2024/05/04 16:20

今天同事测试我之前写的一个小程序,发生了奇怪的错误,先是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) - 1);  /* 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),不分频:
<pre name="code" class="cpp">SysTick->CTRL  |= SysTick_CTRL_CLKSOURCE_Msk |

在我的电脑上,因为对core_cm3.h文件做了以下修改,屏蔽了其对滴答定时器时钟的操作,所以可以正常运行:
SysTick->CTRL  |= //SysTick_CTRL_CLKSOURCE_Msk |
但在同事的电脑上没有做此操作,从而导致了1ms延时实际只有0.125ms,于是出现了前述的种种错误。

解决办法:
1、使用滴答定时器时,不再考虑减轻芯片负担,直接采用原始频率,可以保证不会出现此问题。
2、修改文件调用指向,不调用工程外的相关头文件,防止出现移植时,不同电脑间,工程外文件的不同导致的错误。

0 0
原创粉丝点击