基于Systick系统时钟延时的LED闪烁灯
1、回顾我们的51 单片机编程,当我们需要做系统延迟的时候,最常采用的一
种方式就是使用for 循环的空语句等待来实现。
当然,在STM32 里面也可以这么实现。但是在STM32 的Cortex 内核里面,有个比其更加精准的定时器专业用于
系统定时,我们称之为Cortex 系统定时器(SysTick,系统滴答)。
Systick 就是一个定时器而已,只是它放在了NVIC(中断事件)中,
主要的目的是为了给操作系统提供一个硬件上的中断(号称滴答中断)。
这样,只要设置好其中断的时间,就可以每隔一定时间跳入其处理程序,
通过这种方式,我们可以做一些分时的任务处理。
然而,由于我们刚刚接触STM32,因此我们本课程内容,仅仅是
用其做一些延迟函数的处理。可能有些同学有疑问,微控制器的定时器资源一般
比较丰富,比如STM32 存在8 个定时器,为啥还要再提供一个SYSTICK?原因就
是所有基于ARM Cortex_M3 内核的控制器都带有SysTick 定时器,这样就方便了
程序在不同的器件之间的移植。而使用RTOS 的第一项工作往往就是将其移植到
开发人员的硬件平台上,由于SYSTICK 的存在无疑降低了移植的难度。具体
Systick 的概述,请参考《Cortex-M3 权威指南》179 页。
关于SysTick 的编程
流程如下:
配置系统时钟;
配置SysTick;
写SysTick 中断处理函数;
编写delay 延迟函数;
第一步:
先让我们来设置系统时钟。关于系统时钟的配置,我们可以直接使
用默认的固件库函数“void SystemInit(void);”,这个函数在固件库手册上面
是没有的,一旦使用默认配置之后,整个STM32 的系统时钟就会被配置成:
SYSCLK(系统时钟) = 72MHZ(系统最高允许时钟);
AHB 总线时钟= 72MHZ(AHB 最高允许时钟);
APB1 总线时钟= 36MHZ(APB1 最高允许时钟);
APB2 总线时钟= 72MHZ(APB2 最高允许时钟);
第二步:
配置SysTick。我们在设置SysTick 的时候,只用到“core_cm3.h”
文件的函数“__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)”。
这个函数在固件库里面是没有介绍的,因为这个函数是在“core_m3.h”里面定
义的,所以不属于STM32 固件库的范畴。参考《STM32F10xxx 参考手册》第80
页的STM32 系统时钟框图,我们可以知道,系统时钟(AHB,此时为72MHz)经8
分频或者不分频之后产生的时钟给Systick 作为时钟震荡源,因此此时的
Systick 默认为频率为72MHz,如果需要使用8 分频之后的频率,可以使用函数
“SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);”,因此我们只
需要把Systick 设置成72000 时(计算方式:(1/72000000Hz)*72000 次=1ms),
就能产生1ms 时间基准,说白了就是一个中断信号。
见函数void Systick_Init(void)配置
第三步:
编写Systick 的中断处理函数。对于STM32 所有的中断处理函数,
我们都可以在对应的“startup_stm32f10x_xx.s”里面找到其入口。比如,在做
Systick 中断处理的时候,我们选择的入口地址就是“SysTick_Handler”。因
此,我们可以写如下的代码,如程序片段6 所示。同时,需要把“stm32f10x_it.c”
里面的“SysTick_Handler”入口屏蔽,不然会报错。
__IO uint32_t TimingDelay;
void TimingDelay_Decrement(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
void SysTick_Handler(void)
{
TimingDelay_Decrement();
}
第四步,写delay_ms函数
void delay_ms(__IO uint32_t nTime)//延迟函数,设置为US
{
TimingDelay = nTime;//时钟滴答数
while(TimingDelay != );
}
以上只是Systick的配置,下面是一个完整实现LED灯闪烁的代码
下面包含四个文件:分别是mian.c文件、timer.c文件、timer.h文件、led.c文件、led.h文件
mian.c文件、
#include "stm32f10x.h" // 相当于51单片机中的 #include <reg51.h>
#include "timer.h"
#include "led.h"
int main(void)
{
SystemInit();//初始化系统,使得系统频率为72MHZ
systick_init();//配置Systick,使得1ms产生
led_gpio_init();//LED灯的配置,要用到LED灯就要配置
while()
{
GPIO_SetBits(GPIOB,GPIO_Pin_5);
delay_ms();//延时1s
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
delay_ms();
}
}
timer.c文件、
#include "timer.h"
#include "stm32f10x.h"
__IO uint32_t TimingDelay;//相当于宏定义一个TimingDelay
void systick_init()
{
//配置Systick重载值,系统时钟为72MHZ
//设置72000,中断时间:72000*(1/72000000)=1ms
//有返回值,返回0则装在成功
if(SysTick_Config()==)
{
while(); }
} void TimingDelay_Decrement(void)
{
if(TimingDelay !=0x00)
{
TimingDelay--;
}
}
/*中断处理函数,中断一次减1ms*/
void SysTick_Handler(void)
{
TimingDelay_Decrement();//调用上面的函数
} void delay_ms(__IO uint32_t nTime)
{
TimingDelay = nTime;//时钟滴答数
while(TimingDelay !=);
}
注意:这里需要做一个细节!!
在stm32f10x_it.c文件里面的void SysTick_Handler(void)这个函数注释掉。
看截图:
timer.h文件、
#ifndef _TIMER_H_
#define _TIMER_H_ #include "stm32f10x_tim.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_it.h"
#include "misc.h" extern __IO uint32_t TimingDelay; void systick_init();
void delay_ms(__IO uint32_t nTime);
#endif
led.c文件、
#include "led.h"
#include "stm32f10x_gpio.h"
//GPIO初始化
void led_gpio_init()
{
GPIO_InitTypeDef gpio;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
gpio.GPIO_Mode=GPIO_Mode_Out_PP;
gpio.GPIO_Pin=GPIO_Pin_5;
gpio.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&gpio);
}
led.h文件
#ifndef _LED_H_
#define _LED_H_ void led_gpio_init(); #endif
基于Systick系统时钟延时的LED闪烁灯的更多相关文章
- STM32学习笔记(六) SysTick系统时钟滴答实验(stm32中断入门)
系统时钟滴答实验很不难,我就在面简单说下,但其中涉及到了STM32最复杂也是以后用途最广的外设-NVIC,如果说RCC是实时性所必须考虑的部分,那么NVIC就是stm32功能性实现的基础,NVIC的难 ...
- [stm32][ucos] 1、基于ucos操作系统的LED闪烁、串口通信简单例程
* 内容简述: 本例程操作系统采用ucos2.86a版本, 建立了5个任务 任务名 优先级 ...
- STM32学习笔记:系统时钟和SysTick定时器
原文:http://blog.sina.com.cn/s/blog_49cb42490100s60d.html 1. STM32的时钟系统 在STM32中,一共有5个时钟源,分别是HSI.HS ...
- STM32(4)——系统时钟和SysTick
1.STM32的时钟系统 在STM32中,一共有5个时钟源,分别是HSI.HSE.LSI.LSE.PLL HSI是高速内部时钟,RC振荡器,频率为8MHz: HSE是高速外部时钟,可接石英/陶瓷谐振器 ...
- stm32之Systick(系统时钟)
Systick的两大作用: 1.可以产生精确延时: 2.可以提供给操作系统一个单独的心跳(时钟)节拍: 通常实现Delay(N)函数的方法为: for(i=0;i<x;i++) ; 对于STM3 ...
- 使用系统定时器SysTick实现精确延时微秒和毫秒函数
SysTick定时器简介 SysTick定时器是存在于系统内核的一个滴答定时器,只要是ARM Cortex-M0/M3/M4/M7内核的MCU都包含这个定时器,它是一个24位的递减定时器,当计数到 0 ...
- [ZigBee] 16、Zigbee协议栈应用(二)——基于OSAL的无线控制LED闪烁分析(下)
说在前面:上一篇介绍了无线LED闪烁实现的OSAL部分,本篇介绍如何实现无线数据收发及数据处理: 上一篇是用SI跟着流程查看源码,我个人认为以架构的思维去了解代码能让人更清晰 ::ZMain.c程序入 ...
- STM32系统时钟RCC(基于HAL库)
基础认识 为什么要有时钟: 时钟就是单片机的心脏,其每跳动一次,整个单片机的电路就会同步动作一次.时钟的速率决定了两次动作的间隔时间.速率越快,单片机在单位时间内所执行的动作将越多.时钟是单片机运行的 ...
- led闪烁(时序输入输出,自定义变量,时钟仿真,执行顺序)
1.设计定义 设计一个以200ms亮,200ms暗交替闪烁的led灯,并且有一个复位按钮可以停止工作. 2.设计输入 2.1端口 以固定周期交替闪烁说明由时钟控制,需要一个时钟控制端口clk,要求复位 ...
随机推荐
- python编程实现十进制的转换(十进制到任何进制不用系统函数实现)
# 用户给定一个十进制数据,以及进制n, 完成n进制的转换,输出结果给用户(不要借助已有函数) # 用户的输入进制数据Decdata = int(input("请输入一个十进制数据:&quo ...
- POJ 3080 Blue Jeans (字符串处理暴力枚举)
Blue Jeans Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 21078 Accepted: ...
- mysql 检查一个字符串是不是身份证号
)CHARSET utf8) ) BEGIN DECLARE flag BOOL DEFAULT FALSE; AND number REGEXP CONCAT('^(([1][1-5])|([2][ ...
- 一个kubeadm.config文件--定义了token,扩展了默认端口,外部ETCD集群,自定义docker仓库,基于ipvs的kubeproxy
这个版本是基于kubeadm.k8s.io/v1alpha3的,如果到了beta1,可能还要变动呢. apiVersion: kubeadm.k8s.io/v1alpha3 kind: InitCon ...
- 常用js正则表达式大全
常用js正则表达式大全.一.校验数字的js正则表达式 1 数字:^[0-9]*$ 2 n位的数字:^\d{n}$ 3 至少n位的数字:^\d{n,}$ 4 m-n位的数字:^\d{m,n}$ 5 零和 ...
- JVM性能参数优化
以上是jdk1.7的默认GC回收器 Java的gc回收的类型主要有几种 UseSerialGC, UseConcMarkSweepGC, UseParNewGC, UseParallelGC, Use ...
- ELK收集Nginx自定义日志格式输出
1.ELK收集日志的有两种常用的方式: 1.1:不修改源日志格式,简单的说就是在logstash中转通过 grok方式进行过滤处理,将原始无规则的日志转换为规则日志(Logstash自定义日志格式) ...
- net core体系-web应用程序-4net core2.0大白话带你入门-2asp.net core新建项目
新建asp.net core项目 开发环境:Windows Server R2 2008 开发工具:Microsoft Visual Studio 2017 新建asp.net core项目 创建 ...
- BZOJ2287 【POJ Challenge】消失之物 动态规划 分治
原文链接http://www.cnblogs.com/zhouzhendong/p/8684027.html 题目传送门 - BZOJ2287 题意 有$n$个物品,第$i$个物品的体积为$w_i$. ...
- Scala-Unit7-Scala并发编程模型AKKA
一.Akka简介 Akka时spark的底层通信框架,Hadoop的底层通信框架时rpc. 并发的程序编写很难,但是Akka解决了spark的这个问题. Akka构建在JVM平台上,是一种高并发.分布 ...