历史上的今天
返回首页

历史上的今天

今天是:2024年11月11日(星期一)

正在发生

2020年11月11日 | STM32F10x 学习笔记之SysTick 定时器

2020-11-11 来源:eefocus

SysTick 定时器被集成在NVIC中。因此,只要是Cortex-M3 内核的单片机,就都有它。这个学习笔记就用SysTick 定时器来实现走马灯的功能。


SysTick 定时器非常简答,只有四个寄存器。这四个寄存器的含义在《Cortex-M3权威指南》那本书中讲的非常的清楚,这里不复述了,下面只讲讲在STM32上SysTick有什么特殊之处。按照CMSIS 标准,用C语言访问这四个寄存器时使用的寄存器名称分别如下:


SysTick->CTRL

SysTick->LOAD

SysTick->VAL

SysTick->CALIB


SysTick->CALIB 的值固定为9000,因此,只有当系统嘀嗒时钟设定为9MHz(HCLK/8的最大值) ,产生1ms 时间基准。


STM32提供了2个时钟源:


0: AHB/8


1: Processor clock (AHB)


因此,SysTick->CTRL = 7 表示使用处理器时钟作为时钟源,使能SysTick,并且使能SysTick中断。SysTick->CTRL = 3 时频率降为原来的1/8。 


我的开发板上有四个LED,分别对应的GPIO端口D 的 PD2、PD3、PD4和PD7。


下面是例子程序,仍然先是直接设置寄存器。


#include "stm32f10x.h"  

  

#define RCC_GPIO_LED                                 RCC_APB2Periph_GPIOD  

#define GPIO_LED_PORT                                GPIOD      

#define GPIO_LED1                                    GPIO_Pin_2      

#define GPIO_LED2                                    GPIO_Pin_3      

#define GPIO_LED3                                    GPIO_Pin_4      

#define GPIO_LED4                                    GPIO_Pin_7  

#define GPIO_LED_ALL                                 GPIO_LED1 |GPIO_LED2 |GPIO_LED3 |GPIO_LED4   

  

  

void LED_Spark(void)  

{  

    static int state = 0;  

    switch (state)  

    {  

    case 0:  

        GPIO_SetBits(GPIO_LED_PORT, GPIO_LED_ALL);  

        GPIO_ResetBits(GPIO_LED_PORT, GPIO_LED1);  

        state ++;  

        break;  

    case 1:  

        GPIO_SetBits(GPIO_LED_PORT, GPIO_LED_ALL);  

        GPIO_ResetBits(GPIO_LED_PORT, GPIO_LED2);  

        state ++;  

        break;  

    case 2:  

        GPIO_SetBits(GPIO_LED_PORT, GPIO_LED_ALL);  

        GPIO_ResetBits(GPIO_LED_PORT, GPIO_LED3);  

        state ++;  

        break;  

    case 3:  

        GPIO_SetBits(GPIO_LED_PORT, GPIO_LED_ALL);  

        GPIO_ResetBits(GPIO_LED_PORT, GPIO_LED4);  

        state = 0;  

        break;  

    default:  

        state = 0;  

        break;  

    }  

}  

int main(void)  

{  

    SystemInit();  

    RCC->APB2ENR  |=  0x00000020;  

    GPIOD->CRL = 0x24422244; //PD2 PD3 PD4 PD7 Set to Output mode    

      

    SysTick->LOAD = 24000000/200;  

    SysTick->CTRL = 3;       

  

    for(;;)  

    {  

    }     

}  

  

/** 

 * @brief  This function handles SysTick Handler. 

 * @param  None 

 * @retval None 

 */  

void SysTick_Handler(void)  

{  

    static int count = 0;  

    count ++;  

    if (count == 100)   

    {  

        LED_Spark();  

        count = 0;  

    }  

}  


然后是利用STM32 固件函数库提供的函数的例子。


[cpp]  view plain copy

#include "stm32f10x.h"  

  

#define RCC_GPIO_LED                                 RCC_APB2Periph_GPIOD  

#define GPIO_LED_PORT                                GPIOD      

#define GPIO_LED1                                    GPIO_Pin_2      

#define GPIO_LED2                                    GPIO_Pin_3      

#define GPIO_LED3                                    GPIO_Pin_4      

#define GPIO_LED4                                    GPIO_Pin_7  

#define GPIO_LED_ALL                                 GPIO_LED1 |GPIO_LED2 |GPIO_LED3 |GPIO_LED4   

  

void LED_Spark(void)  

{  

    static int state = 0;  

    switch (state)  

    {  

    case 0:  

        GPIO_SetBits(GPIO_LED_PORT, GPIO_LED_ALL);  

        GPIO_ResetBits(GPIO_LED_PORT, GPIO_LED1);  

        state ++;  

        break;  

    case 1:  

        GPIO_SetBits(GPIO_LED_PORT, GPIO_LED_ALL);  

        GPIO_ResetBits(GPIO_LED_PORT, GPIO_LED2);  

        state ++;  

        break;  

    case 2:  

        GPIO_SetBits(GPIO_LED_PORT, GPIO_LED_ALL);  

        GPIO_ResetBits(GPIO_LED_PORT, GPIO_LED3);  

        state ++;  

        break;  

    case 3:  

        GPIO_SetBits(GPIO_LED_PORT, GPIO_LED_ALL);  

        GPIO_ResetBits(GPIO_LED_PORT, GPIO_LED4);  

        state = 0;  

        break;  

    default:  

        state = 0;  

        break;  

    }  

}  

int main(void)  

{  

    GPIO_InitTypeDef GPIO_InitStructure;  

    SystemInit();  

    SysTick_Config(SystemCoreClock/100);  

  

    /* Enable GPIOB, GPIOC and AFIO clock */  

    RCC_APB2PeriphClockCmd(RCC_GPIO_LED, ENABLE);  //RCC_APB2Periph_AFIO  

      

    /* LEDs pins configuration */  

    GPIO_InitStructure.GPIO_Pin = GPIO_LED_ALL;  

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;  

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  

    GPIO_Init(GPIO_LED_PORT, &GPIO_InitStructure);  

  

    for(;;)  

    {  

  

    }     

}  

  

/** 

 * @brief  This function handles SysTick Handler. 

 * @param  None 

 * @retval None 

 */  

void SysTick_Handler(void)  

{  

    static int count = 0;  

    count ++;  

    if (count == 100)   

    {  

        LED_Spark();  

        count = 0;  

    }  

}  

需要说明的是,若是用 SysTick_Config 函数来设置SysTick的中断频率,时钟源就不能人为的指定了,这时使用的时钟源就是内核的频率。


SystemCoreClock 是个全局变量,它的值就是内核的运行频率,不过前提要调用 SystemInit() 函数来设置内核的频率。如果内核的频率是字节写寄存器来设置的,SystemCoreClock 的值就不一定对了。

推荐阅读

史海拾趣

DBLECTRO公司的发展小趣事

进入21世纪后,随着全球对环保和可持续发展的关注度不断提高,迪贝电子也积极响应这一趋势,将环保和社会责任融入到企业的经营理念中。公司投入大量资金研发更加环保、节能的产品,并积极参与各种环保公益活动。同时,迪贝电子还积极推广绿色制造理念,通过优化生产流程、降低能耗和减少废弃物排放等措施,实现了企业的可持续发展。

EPC公司的发展小趣事

另一家EPC公司认识到全球化市场的重要性,积极拓展海外市场。公司首先在欧洲和北美地区设立了分公司,通过深入了解当地市场需求和法规要求,成功开展了多个项目。随后,公司进一步将业务拓展至亚洲和非洲等地区,形成了全球化的市场布局。在全球化的过程中,公司注重本土化经营,积极融入当地市场,为客户提供定制化的解决方案,赢得了客户的信任和支持。

Abbatron公司的发展小趣事

Abbatron公司深知合作的重要性,积极寻求与业内其他企业的合作机会。通过与某知名电子制造商的合作,Abbatron公司成功将其创新技术应用于实际产品中,进一步扩大了市场份额。这种合作模式不仅促进了双方的发展,也为整个电子行业带来了更多的可能性。

EPIGAP公司的发展小趣事

EPIGAP公司非常重视创新文化的建设。公司鼓励员工提出新的想法和创意,并为员工提供充分的支持和资源。此外,EPIGAP还积极引进和培养人才,建立了一支高素质、专业化的研发团队。这支团队在公司的发展历程中发挥了至关重要的作用,不断推动公司产品的升级换代和技术创新。

EMCORE公司的发展小趣事

随着全球对环保问题的日益关注,EPIGAP公司也开始注重绿色环保和可持续发展。公司积极采用环保材料和生产工艺,减少生产过程中的污染物排放。同时,EPIGAP还加大了对可再生能源的研发力度,推动公司向绿色、低碳、循环发展的方向迈进。这一战略不仅符合全球环保趋势,也为公司赢得了良好的社会声誉。

Akustica(Bosch)公司的发展小趣事

EPIGAP公司非常重视创新文化的建设。公司鼓励员工提出新的想法和创意,并为员工提供充分的支持和资源。此外,EPIGAP还积极引进和培养人才,建立了一支高素质、专业化的研发团队。这支团队在公司的发展历程中发挥了至关重要的作用,不断推动公司产品的升级换代和技术创新。

问答坊 | AI 解惑

弱弱的问一句关于CPU利用率问题。

想问一下关于CPU利用率的问题,如果WINDOWS启动完后,什么都启动好了,查看CPU的利用率是0%,是不是这个时候CPU就没有工作了呢?但是在进程里却发现还有好多个进程在执行着,既然是0%,那为什么还有进程在执行呢?…

查看全部问答>

PLC与PC串口RTU通讯问题

最近写了一个PC与PLC 串口通信的小程序,我对PLC一点都不了解,主要是读取寄存器的值. 我想问问 1 PLC的地址怎么表示,只有一台PLC通过USB转串口连接PC 2 RTU模式读取数,我是不是也应该在PLC上设置成RTU? (施耐德的PLC 怎么设置?) …

查看全部问答>

wince5.0下MFC中没有CBitmapButton类,请问有人实现图片按钮的自定义的类么?

wince5.0下MFC中没有CBitmapButton类,请问有人实现图片按钮的自定义的类么?…

查看全部问答>

PC可以直接使用手机显示屏吗?

有个工控设备,其中内置一台个人电脑(PC全内置主板),需要配备显示器和键盘。 因为安装空间太小,容纳不了普通CRT或笔记本LCD显示器。况且,该设备的用户界面很简单,只需要控制串口通讯以及操作一个简单的ACCESS数据库,使用带触摸的2.5~3.5寸 ...…

查看全部问答>

VS2005下的类视图分页下,一个类在类列表里面看不到,怎么回事?.h和.cpp文件工程下都加进去了。

VS2005下的类视图分页下,一个类在类列表里面看不到,怎么回事?.h和.cpp文件工程下都加进去了。…

查看全部问答>

EVC pocket pc 2003程序和VS2005 pocket pc SE2003程序区别及问题!

EVC下pocket pc 2003和VS2005 pocket pc se 2003模拟器有什么区别???? 是这样的,我在EVC下pocket pc 2003下编译成功并能运行的一个.exe文件直接共享在VS2005 pocket pc se 2003下,但是却点击运行不了.出现如下错误: connot find \"mfctest\"(//我 ...…

查看全部问答>

STTM8使用IAR的C编译问题

以下程序如果用STM8S207系列芯片在IAR上编译头文件是#include <iostm8s207sb.h>。哪我如果用103芯片,头文件应该怎样写?哪里这一方面的资料介绍? #include <iostm8s207sb.h> #define LED1_FLASH  PD_ODR_ODR3 =  ...…

查看全部问答>

速找ic型号 fx5200的pdf资料 那里能特找到 谢谢

速找ic型号 fx5200的pdf资料 那里能特找到 谢谢…

查看全部问答>

Stellaris ICDI ND manual(811国产板使用说明书)

附:stellaris_icdi_switch转换工具的使用说明…

查看全部问答>

毕业了,想要书的随便挑

直接买废纸有点可惜,有几本有点用处的书 想要的随便挑,挑完再买废纸 …

查看全部问答>