当前位置: 首页 > news >正文

第11章_瑞萨MCU零基础入门系列教程之SysTick

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写,需要的同学可以在这里获取: https://item.taobao.com/item.htm?id=728461040949

配套资料获取:https://renesas-docs.100ask.net

瑞萨MCU零基础入门系列教程汇总: https://blog.csdn.net/qq_35181236/article/details/132779862


第11章 SysTick

本章目标

  • 了解滴答定时器的概念
  • 学会配置滴答定时器和扩展驱动应用

11.1 认识滴答定时器

SysTick定时器也被称为滴答定时器。在Cortex架构的处理器里,有一个24bit的向下计数定时器,它就是滴答定时器。它不是处理器之外的、跟GPIO等设备同等地位的设备,而是位于处理器内部的定时器。

对于Cortex-M33内核而言,它拥有2个滴答定时器:一个用于非安全系的滴答定时器,另一个用于安全系的滴答定时器。如果开发者不使用Cortex-M33的TrustZone的程序安全功能,那么只能使用一个非安全系的滴答定时器。

滴答定时器有4个寄存器用于控制和获取状态:

a) 控制和状态寄存器:SYST_CSR
b) 重载值寄存器:SYST_RVR
c) 当前计数值寄存器:SYST_CVR
d) 校验值寄存器:SYST_CALIB

使用滴答定时器就是对这几个寄存器进行配置让它按照指定的频率进行计数,本章会实现几个驱动函数为后续章节的外设驱动使用。

11.2 滴答定时器的配置

在配置滴答定时器前,首先应该要熟悉其工作机制,其工作机制有如下几条:

① 当使能了滴答定时器的计数后,滴答定时器将会从重载值向下计数到零,然后在下一个时钟周期从重载值寄存器读取重载值,在紧随的下一个时钟周期又开始向下计数。
② 如果给重载值寄存器RVR写入了一个‘0’,那么本次计数循环(也就是本次向下计数到0)后就会停止计数。
③ 当计数到0使,控制状态寄存器CSR的计数标志COUNTFLAG位会被置1.,当读取CSR寄存器时会将这一位清零。
④ 如果给当前计数值寄存器CVR写入一个值时,会更新CVR的值且会将COUNTFLAG清零;
⑤ 如果程序处于调试状态,当开发者暂停调试时,滴答定时器也会暂停计数;

可以看到,这几个机制中使用到的寄存器只有3个:CSR(Control and Status Register,控制和状态寄存器)、RVR(Reload Value Register,重载值寄存器)和CVR(Current Value Register,当前值寄存器)。接下来就着重认识下这3个寄存器,并且学会如何配置他们。

11.2.1 控制和状态寄存器SYST_CSR

控制状态寄存器各个位的描述如下图:

  • Bit0-ENABLE:计数器使能位;0-不使能计数器;1-使能计数器;
  • Bit1-TICKINT:滴答定时器中断请求位;0-计数到0不产生中断请求;1-产生中断请求;
  • Bit2-CLKSOURCE:滴答定时器的时钟选择位;0-使用外部基准时钟;1-使用处理器时钟;
  • Bit16-COUONTFLAG:滴答定时器技术标志位,当计数到0时置1,如果没有读取CSR的话将会一直为1;

CSR寄存器上电复位默认值是0x00000000,一般情况下,程序是需要滴答定时器产生中断请求来判定滴答定时器计数到0的,所以TICKINT通常被设置为1;而时钟源的选择,惯用的是选择处理器时钟。所以在初始化的时候,一般将CSR的值设置为0x07。

11.2.2 重载值寄存器SYST_RVR

重载值寄存器虽然是一个32bit的寄存器,但是鉴于滴答定时器的设计只有24位的计数值,因而此寄存器只有低24bit有效,高8bit保留,如下图所示:

所谓重载值,就是指滴答定时器计数到0时,又重新从这个值开始向下计数。例如程序中需要滴答定时器从100开始向下计数,那么这里就将RVR的低24bit设置为‘100-1’,也就是十六进制的0x63,二进制的0110 0011,那么RVR寄存器的值就是下图这样:

11.2.3 当前计数值寄存器SYST_CVR

当前计数值寄存器CVR也是低24bit有效,用来表示滴答定时器当前的计数值,如图所示:

无论程序给此寄存器写入什么值,都会将此寄存器清零,并且会将计数标志位COUNTFLAG清零。

11.2.4 滴答定时器的初始化配置

滴答定时器还有一个校准寄存器CALIB,它是只读寄存器,无需操作。从Cortex-M33的调试手册中其对滴答定时器的各个寄存器总结如下图:

那么开发者配置滴答定时器时,步骤如下:

① 选择抵达定时器的时钟源;
② 使能滴答定时器的中断请求;
③ 设置重载值;
④ 清零当前计数值;
⑤ 使能滴答定时器计数;

  1. 初始化滴答定时器

在Cortex内核源文件的core_cmXX.h,比如core_cm33.h定义滴答定时器的初始化函数,代码如下:

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk){return (1UL);                       /* Reload value impossible */}SysTick->LOAD  = (uint32_t)(ticks - 1UL);              /* set reload register */NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */SysTick->VAL   = 0UL;          /* 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 (0UL);                  /* Function successful */
}

开发者只需要在自己的代码中调用此函数,传入一个指定的重载值即可,例如下面这个代码:

fsp_err_t SystickInit(void)
{/* 获取处理器时钟uwSysclk */uint32_t uwSysclk= R_BSP_SourceClockHzGet(FSP_PRIV_CLOCK_PLL);/* 技术周期为uwSysclk/1000 */if(SysTick_Config(uwSysclk/1000) != 0){return FSP_ERR_ASSERTION;}/* Return function status */return FSP_SUCCESS;
}

如上初始化滴答定时器后,它的计数时钟频率就是处理器的系统主频

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在此频率下向下计数

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

个数后触发中断,也就是每秒钟触发1000次中断,换算公式如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

假如

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

那么传入给SysTick_Config函数的值就是200K,滴答定时器就会以200MHz的频率从200K往0开始递减,递减为0时触发一次中断,中断触发频率就是

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 实现滴答定时器的中断服务函数

当滴答定时器计数到0时,会触发中断,中断服务函数SysTick_Handler被调用,这个函数需要开发者实现,比如给一个全局变量递增1,参考如下代码:

volatile  uint32_t dwTick = 0;
void SysTick_Handler(void)
{dwTick += 1;
}

11.3 基于SysTick的扩展应用

本实验会用到板载LED外设和printf功能,请读者参考本书《第5章 GPIO输入输出》和《第7章 UART》来配置LED的GPIO和UART模块,并且移植drv_uart.c和drv_config.h到本节实验的工程“1101_systick_delay”中。

在上一小节已经初始化了滴答定时器、实现了中断服务函数。本节在此基础上实现一个ms级别的延时函数(因为初始化设置的滴答定时器是1KHz的中断触发频率)。参考如下代码:

#define HAL_MAX_DELAY      0xFFFFFFU
void HAL_Delay(uint32_t dwTime)
{uint32_t dwStart = dwTick;uint32_t dwWait = dwTime;/* Add a freq to guarantee minimum wait */if (dwWait < HAL_MAX_DELAY){dwWait += (uint32_t)(1);}while((dwTick - dwStart) < dwWait){}
}
  • 第10行:在延时值基础上加1;
  • 第13行:滴答定时器中断服务函数中的递增变量dwTick减去此延时函数调用时刻的dwStart,即滴答定时器触发“dwTick- dwStart”次后大于等于延时时长后才退出函数;

为什么dwWait要先加1?这是因为执行HAL_Delay函数时必定是在2次滴答定时器中断之间,距离下一次中断的时间必定小于1ms。比如传入的dwTime等于2时,实际延时的时间是大于1ms、小于2ms。第10行里让dwWait值加1,目的是使得延时能满足下限:“至少延时dwWait毫秒”。

还可以读取dwTick获取系统运行时间/时刻,例如以下代码:

uint32_t HAL_GetTick(void)
{return dwTick;
}

11.4 测试程序

本书测试滴答定时器的方法是:使用基于滴答定时器的延时函数来闪烁LED,并且打印延时前后的tick值。代码如下:

void SystickAppTest(void)
{uint8_t ucCount = 5;uint32_t dwLastTick = 0, dwCurtick = 0;bsp_io_level_t nLevel = false;while(ucCount--){dwLastTick = HAL_GetTick();HAL_Delay(1000);dwCurtick = HAL_GetTick();

11.5 上机实验

本实验将滴答定时器的驱动在hal_systick.c中实现,在hal_systick.h中声明;测试函数在app_systick.c中实现,在app.h中声明;最后在hal_entry.c中调用初始化函数和测试函数,代码如下:

#include "app.h"
#include "hal_systick.h"
#include "drv_uart.h"
#include "hal_data.h"void hal_entry(void)
{/* TODO: add your own code here */SystickInit();UARTDrvInit();SystickAppTest();
}

将程序编译出来的二进制可执行文件烧录到处理器中运行可以得到如下图的结果:

开发板上LED间隔1s改变状态。


本章完

相关文章:

第11章_瑞萨MCU零基础入门系列教程之SysTick

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…...

【面试题精讲】如何使用Stream的聚合功能

有的时候博客内容会有变动&#xff0c;首发博客是最新的&#xff0c;其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 系列文章地址 求和&#xff08;Sum&#xff09;&#xff1a; List<Integer> numbers Arrays.asList(1, 2, 3, 4, 5);int sum n…...

Linux 中的 chmod 命令及示例

在 Unix 操作系统中,chmod命令用于更改文件的访问模式。该名称是change mode的缩写。其中规定每个文件和目录都有一组权限来控制权限,例如谁可以读取、写入或执行该文件。其中权限分为三类:同时读、写和执行,用“r”、“w”和“x”表示。这些字母组合在一起形成一组用户的特…...

sannaing i14 pro max使用体验

体验了一把山寨机&#xff0c;不明真相的人会以为这是三星的英文标志&#xff0c;又是pro又是max的&#xff0c;价格600&#xff0c;进系统去看了配置&#xff0c;cpu写的是snapdragon 888&#xff0c;运存12g&#xff0c;内存500g。下了个安兔兔也是被忽悠了&#xff0c;它也以…...

Shazam音乐检索算法原理及实现

算法基本流程如下&#xff1a; 1. 采集音乐库 2. 音乐指纹采集 3. 采用局部最大值作为特征点 4. 将临近的特征点进行组合形成特征点对 5. 对每个特征点对进行hash编码 编码过程&#xff1a;将f1和f2进行10bit量化&#xff0c;其余bit用来存储时间偏移合集形成32bit的hash码 …...

vue递归组件

父组件&#xff1a; <template><div><treeVue :treeData"treeData"></treeVue></div> </template><script setup lang"ts"> import { reactive } from "vue"; import treeVue from "./tree.vue…...

软件测试/测试开发丨测试用例自动录入 学习笔记

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/27139 测试用例自动录入 测试用例自动录入的价值 省略人工同步的步骤&#xff0c;节省时间 兼容代码版本的自动化测试用例 用例的执行与调度统一化管理…...

来学Python啦,大话字符串

To be a happy man&#xff0c; reading&#xff0c; travel&#xff0c; hard work&#xff0c; care for the body and mind。做一个幸福的人&#xff0c;读书&#xff0c;旅行&#xff0c;努力工作&#xff0c;关心身体和心境。 前面我们讲解过关于用Python写温度转换器&…...

pyqt5设置背景图片

PyQt5设置背景图片 1、打开QTDesigner 创建一个UI&#xff0c;camera.ui。 2、创建一个pictures.qrc文件 在ui文件同级目录下先创建一个pictures.txt&#xff0c;填写内容&#xff1a; <RCC><qresource prefix"media"><file>1.jpg</file>…...

C# WPF 自己写的一个模拟病毒传播的程序,有可视化

源代码: https://github.com/t39q/VirusSpread 主要代码 using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks;namespace VirusSpread.Bu…...

stable diffusion实践操作-大模型介绍-SDXL1大模型

系列文章目录 大家移步下面链接中&#xff0c;里面详细介绍了stable diffusion的原理&#xff0c;操作等&#xff08;本文只是下面系列文章的一个写作模板&#xff09;。 stable diffusion实践操作 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生…...

软考高级系统架构设计师系列案例考点专题四:嵌入式系统

软考高级系统架构设计师系列案例考点专题四:嵌入式系统 一、相关概念二、软件可靠性和硬件可靠性的区别三、可靠性指标四、可靠性设计五、冗余技术六、软件容错七、双机容错技术八、集群技术九、负载均衡十、可维护性的评价指标十一、软件维护的分类嵌入式每年必考一题,但是属…...

Django Form实现表单使用及应用场景

首先需要定义一个使用场景&#xff1a; 音乐网站的前端部分可以添加上传歌手的单曲&#xff0c; 这个添加页面就使用django form表单来实现。 目录 数据表内容 歌手表及表模型 单曲表及表模型 演示表单使用 设置路由 创建form.py 视图实例化表单类 模板使用表单对象 表…...

golang面试题:json包变量不加tag会怎么样?

问题 json包里使用的时候&#xff0c;结构体里的变量不加tag能不能正常转成json里的字段&#xff1f; 怎么答 如果变量首字母小写&#xff0c;则为private。无论如何不能转&#xff0c;因为取不到反射信息。如果变量首字母大写&#xff0c;则为public。 不加tag&#xff0c…...

国内项目管理中级证书CSPM-3正在报名!

CSPM-3中级项目管理专业人员认证&#xff0c;是中国标准化协会&#xff08;全国项目管理标准化技术委员会秘书处&#xff09;&#xff0c;面向社会开展项目管理专业人员能力的等级证书。旨在构建多层次从业人员培养培训体系&#xff0c;建立健全人才职业能力评价和激励机制的要…...

vue表格不显示列号123456

我在网上找了半天&#xff0c;都是如何添加列号123456的&#xff0c;没有找到不显示列号的参考&#xff0c;现在把这个解决了&#xff0c;特此记录一下。 没有加右边的就会显示&#xff0c;加上右边的就隐藏了...

【大数据】Kafka 入门指南

Kafka 入门指南 1.Kafka 简介2.Kafka 架构3.分区与副本4.偏移量5.消费者组6.总结 1.Kafka 简介 Apache Kafka 是一种高吞吐、分布式的流处理平台&#xff0c;由 LinkedIn 开发并于 2011 年开源。它具有 高伸缩性、高可靠性 和 低延迟 等特点&#xff0c;因此在大型数据处理场景…...

Qt 5.15集成Crypto++ 8.8.0(MSVC 2019)笔记

一、背景 笔者已介绍过在Qt 5.15.x中使用MinGW&#xff08;8.10版本&#xff09;编译并集成Crypto 8.8.0。 但是该编译出来的库&#xff08;.a和.dll&#xff09;不适用MSVC&#xff08;2019版本&#xff09;构建环境&#xff0c;需要重新编译&#xff08;.lib或和.dll&#xf…...

前端面试的话术集锦第 9 篇:高频考点(webpack性能优化)

这是记录前端面试的话术集锦第九篇博文——高频考点(webpack性能优化),我会不断更新该博文。❗❗❗ 在此章节中,我不会浪费篇幅给大家讲如何写配置文件。如果你想学习这方面的内容,那么完全可以去官网学习。在这部分的内容中,我们会聚焦于以下两个知识点,并且每一个知识…...

程序员,你真热爱编程吗?

程序员的热爱与演变 我发现&#xff0c;程序员这个行业不像其他行业那样&#xff0c;很多人是因为热爱编程才去做程序员&#xff0c;不会被逼无奈去做程序员&#xff08;要是真有就太惨了&#xff09;。 热爱编程的漫长过程 热爱过、⼜不爱了、⼜爱了&#xff0c;这是个过程…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

华为OD机考-机房布局

import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...