RP2040 C SDK SysTick滴答定时器功能使用

news2024/9/19 6:02:52

RP2040 C SDK SysTick滴答定时器功能使用


  • ✨更好的阅读体验请移步到:飞书-云文档:https://u1etqmuwl9z.feishu.cn/wiki/VkoHwPGqHierOEkY651cZvaOntg?from=from_copylink
  • RP2040的SysTick滴答定时器为24位的,计数方式为倒计时,扩展了处理器和NVIC的功能,并提供:
  • 一个24位的系统计时器(SysTick)
  • 附加的可配置优先级SysTick中断。
    SysTick计时器使用1μs脉冲作为时钟启用。这是在监视器块中作为timer_tick中生成的。SysTick计时的准确性取决于这个计时器的准确性。SysTick计时器也可以从系统时钟开始运行(参见SYST_CALIB)。

📗有关寄存器介绍

  • SYST_CSR Register:使用SysTick控制器和状态寄存器来启用SysTick功能。
  • 偏移地址:0xe010
    在这里插入图片描述
  • SYST_RVR Register:
  • Offset: 0xe014
    Use the SysTick Reload Value Register to specify the start value to load into the current value register when the counter reaches 0. It can be any value between 0 and 0x00FFFFFF. A start value of 0 is possible, but has no effect because the SysTick interrupt and COUNTFLAG are activated when counting from 1 to 0. The reset value of this register is UNKNOWN.
    To generate a multi-shot timer with a period of N processor clock cycles, use a RELOAD value of N-1. For example, if the SysTick interrupt is required every 100 clock pulses, set RELOAD to 99.

在这里插入图片描述

  • SYST_CVR Register
  • Offset: 0xe018
    Use the SysTick Current Value Register to find the current value in the register. The reset value of this register is UNKNOWN.
    在这里插入图片描述
  • SYST_CALIB Register
  • Offset: 0xe01c

Use the SysTick Calibration Value Register to enable software to scale to any required speed using divide and multiply
在这里插入图片描述

📘滴答定时器作为非阻塞定时任务调度使用


/*
 CMSIS-DAP烧录命令:openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c  "adapter speed 5000"-c "program RP2040_ticks.elf verify reset exit"

 jlink命令: openocd -f interface/jlink.cfg -f target/rp2040.cfg  -c  "adapter speed 2000" -c  "program RP2040_ticks.elf verify reset exit"


*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/timer.h"
#include "hardware/structs/systick.h"
#include "hardware/clocks.h"
//#include "hardware/uart.h"
//#include "hardware/irq.h"
//#include "hardware/structs/scb.h"
#include <tusb.h>



#define BUILTIN_LED PICO_DEFAULT_LED_PIN // LED is on the same pin as the default LED 25

void measure_freqs(void);
void MicrosBlink(uint32_t currentTime);
uint32_t previousBlinkTime;
uint32_t blinkInterval = 1000000; //LED闪烁时间间隔
bool toggle;

int main()
{

    // set_sys_clock_khz(133000, true); // 325us
   // set_sys_clock_khz(270000, true);
    stdio_init_all();
    // GPIO initialisation.
    gpio_init(BUILTIN_LED);
    gpio_set_dir(BUILTIN_LED, GPIO_OUT);
    gpio_pull_up(BUILTIN_LED);
    sleep_ms(1);

    while (!tud_cdc_connected()) { sleep_ms(100);  }//等待USB CDC打开
    printf("tud_cdc_connected()\n");

    systick_hw->csr = 0x5;
    systick_hw->rvr = 0x00FFFFFF;

    uint32_t new, old, t0, t1;
    old=systick_hw->cvr;

    t0=time_us_32();
    sleep_us(49999);
    new=systick_hw->cvr;
    t1=time_us_32();

    printf("\n          old_cvr=%d,new_cvr=%d\n",old,new);
    printf("\n          old-new=%d\n",old-new);
    printf("            t1-t0=%d\n",t1-t0);
    printf("(old-new)/(t1-t0)=%.1f\n",(old-new)/(t1-t0*1.0));//频率
    measure_freqs();

    while (true)
    {
     // tight_loop_contents();
        // sleep_ms(1000);
        // gpio_xor_mask(1ul << BUILTIN_LED); // Toggle the LED

        uint32_t currentMillis = time_us_32(); // 获取当前时间

        MicrosBlink(currentMillis);
    }

    return 0;
}


void measure_freqs(void) {
    uint f_pll_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_SYS_CLKSRC_PRIMARY);
    uint f_pll_usb = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_USB_CLKSRC_PRIMARY);
    uint f_rosc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC);
    uint f_clk_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_SYS);
    uint f_clk_peri = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_PERI);
    uint f_clk_usb = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_USB);
    uint f_clk_adc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_ADC);
    uint f_clk_rtc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_RTC);

    printf("pll_sys  = %dkHz\n", f_pll_sys);
    printf("pll_usb  = %dkHz\n", f_pll_usb);
    printf("rosc     = %dkHz\n", f_rosc);
    printf("clk_sys  = %dkHz\n", f_clk_sys);
    printf("clk_peri = %dkHz\n", f_clk_peri);
    printf("clk_usb  = %dkHz\n", f_clk_usb);
    printf("clk_adc  = %dkHz\n", f_clk_adc);
    printf("clk_rtc  = %dkHz\n", f_clk_rtc);

    // Can't measure clk_ref / xosc as it is the ref
}

void MicrosBlink(uint32_t currentTime) {
  //检查是否到达时间间隔
  if (currentTime-previousBlinkTime  >= blinkInterval) {    //如果时间间隔达到了
    toggle = (toggle == 1) ? 0 : 1;
 gpio_put(BUILTIN_LED, toggle);
    previousBlinkTime = currentTime;  // 将上一次时间复位

  printf("toggle = %d\n",toggle);
  }

}

在这里插入图片描述

📙利用库实现

  • 📍https://github.com/Blimp01/pico_non_blocking_timer
/*
 CMSIS-DAP烧录命令:openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c  "adapter speed 5000"-c "program example.elf verify reset exit"

 jlink命令: openocd -f interface/jlink.cfg -f target/rp2040.cfg  -c  "adapter speed 2000" -c  "program example.elf verify reset exit"


*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "pico/binary_info.h"
#include "non_blocking_timer.h"

const uint LED_PIN = 25;

non_blocking_timer_handler led_timer; // create user timer struct

void toggle_led()
{
        gpio_put(LED_PIN, !gpio_get(LED_PIN));
}

int main()
{
        stdio_init_all();
        init_non_blocking_timer(&led_timer, 1000,0); //initalise ledtimer for a 1second period
        init_systick();                            //init and enable systick

        gpio_init(LED_PIN);
        gpio_set_dir(LED_PIN,GPIO_OUT);
        start_non_blocking_timer(&led_timer);
        while(1)
        {
                if(non_blocking_timer_expired(&led_timer) == TIMER_EXPIRED)
                {
                        printf("systick %ld\r\n",get_systick()); //Print out systick value
                        toggle_led();                            //Toggle LED 1s On 1s OFF
                        start_non_blocking_timer(&led_timer);    //restart 1s timer
                }
        }
}

📗使用滴答定时器中断


/*
 CMSIS-DAP烧录命令:openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c  "adapter speed 5000"-c "program RP2040_ticks.elf verify reset exit"

 jlink命令: openocd -f interface/jlink.cfg -f target/rp2040.cfg  -c  "adapter speed 2000" -c  "program RP2040_ticks.elf verify reset exit"

*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/exception.h"
#include "hardware/timer.h"
#include "hardware/structs/systick.h"
#include "hardware/clocks.h"
// #include "hardware/uart.h"
// #include "hardware/irq.h"

#include <tusb.h>


#define BUILTIN_LED PICO_DEFAULT_LED_PIN // LED is on the same pin as the default LED 25

void measure_freqs(void);
void MicrosBlink(uint32_t currentTime);
void disableAllInts();
uint32_t previousBlinkTime;
uint32_t blinkInterval = 1000000; // LED闪烁时间间隔
bool toggle;
uint32_t ST_period = 1000000 - 1;


void enableSysTick()
{
                                                                             // 1mS
  systick_hw->rvr = ST_period;                                                                                   // 24 bits
 // systick_hw->csr = M0PLUS_SYST_CSR_CLKSOURCE_BITS | M0PLUS_SYST_CSR_ENABLE_BITS | M0PLUS_SYST_CSR_TICKINT_BITS; // enable with processor clock
    systick_hw->csr = 0x07;  //Enable timer with interrupt
}

void Systick_Handler_Callback(void)
{
    systick_hw->csr = 0x00; // Disable systick
     systick_hw->rvr = ST_period ; // reload the systick counter
    systick_hw->cvr = 0; // Clear the count to force reload
  toggle = (toggle == 1) ? 0 : 1;
  gpio_put(BUILTIN_LED, toggle); // toggle LED
  printf("toggle = %d\n", toggle);
    systick_hw->csr = 0x03; // Enable timer with interrupt
}

int main()
{

  // set_sys_clock_khz(133000, true); // 325us
  // set_sys_clock_khz(270000, true);
  set_sys_clock_khz(125000, 0);   //clk_sys125MHz
  stdio_init_all();
  // GPIO initialisation.
  gpio_init(BUILTIN_LED);
  gpio_set_dir(BUILTIN_LED, GPIO_OUT);
  gpio_pull_up(BUILTIN_LED);
  sleep_ms(1);

  uint32_t fcpu = clock_get_hz(clk_sys);
  while (!tud_cdc_connected())
  {
    sleep_ms(100);
  }
  printf("tud_cdc_connected()\n");

  systick_hw->csr = 0x5;

  systick_hw->rvr = 0x00FFFFFF;

  uint32_t new, old, t0, t1;
  old = systick_hw->cvr;

  t0 = time_us_32();
  sleep_us(49999);
  new = systick_hw->cvr;
  t1 = time_us_32();

  printf("\n          old_cvr=%d,new_cvr=%d\n", old, new);
  printf("\n          old-new=%d\n", old - new);
  printf("            t1-t0=%d\n", t1 - t0);
  printf("(old-new)/(t1-t0)=%.1f\n", (old - new) / (t1 - t0 * 1.0)); // 频率
  measure_freqs();

   enableSysTick();
  // register the Systick Handler
  exception_set_exclusive_handler(SYSTICK_EXCEPTION, Systick_Handler_Callback);
  irq_set_priority(SYSTICK_EXCEPTION, PICO_HIGHEST_IRQ_PRIORITY); // set systick highest priority

  while (true)
  {
    // tight_loop_contents();
    // sleep_ms(1000);
    // gpio_xor_mask(1ul << BUILTIN_LED); // Toggle the LED

    //    uint32_t currentMillis = time_us_32(); // 获取当前时间

    //  MicrosBlink(currentMillis);

    // measure_freqs();
  }

  return 0;
}

void measure_freqs(void)
{
  uint f_pll_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_SYS_CLKSRC_PRIMARY);
  uint f_pll_usb = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_USB_CLKSRC_PRIMARY);
  uint f_rosc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC);
  uint f_clk_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_SYS);
  uint f_clk_peri = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_PERI);
  uint f_clk_usb = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_USB);
  uint f_clk_adc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_ADC);
  uint f_clk_rtc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_RTC);

  printf("pll_sys  = %dkHz\n", f_pll_sys);
  printf("pll_usb  = %dkHz\n", f_pll_usb);
  printf("rosc     = %dkHz\n", f_rosc);
  printf("clk_sys  = %dkHz\n", f_clk_sys);
  printf("clk_peri = %dkHz\n", f_clk_peri);
  printf("clk_usb  = %dkHz\n", f_clk_usb);
  printf("clk_adc  = %dkHz\n", f_clk_adc);
  printf("clk_rtc  = %dkHz\n", f_clk_rtc);

  // Can't measure clk_ref / xosc as it is the ref
}

void MicrosBlink(uint32_t currentTime)
{
  // 检查是否到达时间间隔
  if (currentTime - previousBlinkTime >= blinkInterval)
  { // 如果时间间隔达到了
    toggle = (toggle == 1) ? 0 : 1;
    gpio_put(BUILTIN_LED, toggle);
    previousBlinkTime = currentTime; // 将上一次时间复位

    printf("toggle = %d\n", toggle);
  }
  // else if (currentTime-previousBlinkTime <= 0) {   // 如果时间间隔小于0时间溢出
  //   previousBlinkTime = currentTime;
  // }
}

void disableAllInts()
{
  int i;
  for (i = 0; i < 32; i++)
  { // 32 interrupts on NVIC
    irq_set_enabled(i, false);
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2141065.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于对数变换的图像美白增强,Matlab实现

博主简介&#xff1a;matlab图像处理&#xff08;QQ:3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于对数变换的图像美白增强&#xff0c;用matlab实现。 一、案例背景和算法介绍 这次案例是美白算法&…

Stable Diffusion Web UI基础插件推荐

通过前面知识的介绍&#xff0c;我们对使用 Web UI 进行绘画有了基本了解&#xff0c;在平时我们使用中&#xff0c;有很多好用的插件&#xff0c;通过这些插件我们创作能够事半功倍&#xff0c;下面我就推荐一下在平时经常使用到的插件&#xff0c;希望这篇文章能够帮助大家更…

MelosBoom:解锁数据价值的新纪元

在当今的数字时代&#xff0c;数据被誉为“新的石油”&#xff0c;但用户在传统的Web2环境中&#xff0c;往往无法真正享受到自己贡献数据的价值。大型互联网公司通过集中化的系统和算法&#xff0c;垄断了数据的使用权&#xff0c;并从中获取巨大的商业利益&#xff0c;而数据…

浏览器页面被禁用 F12(dev tools)

解决办法1: 使用浏览器设置栏, 打开开发者工具, 设置->更多工具->开发者工具 解决办法2: 命令行启动浏览器, 携带参数, 强制打开所有页面的 devtools chrome.exe –auto-open-devtools-for-tabs –user-data-dir./

时序必读论文10|ICLR23 Crossformer 跨维度依赖的多变量时序预测模型

论文标题&#xff1a;iCROSSFORMER : TRANSFORMER UTILIZING CROSS DIMENSION DEPENDENCY FOR MULTIVARIATE TIME SERIES FORECASTING 开源代码&#xff1a;https://github.com/Thinklab-SJTU/Crossformer 前言 Crossformer是一篇非常典型的在transformer基础上魔改注意力机…

k8s使用本地docker私服启动自制的flink集群

目标&#xff1a;使用本地flink环境自制flink镜像包上传到本地的私服&#xff0c;然后k8s使用本地的私服拉取镜像启动Flink集群 1、将本地的flink软件包打包成Docker镜像 从官网下载flink-1.13.6的安装包&#xff0c;修改其中的flink-conf.yaml&#xff0c;修改下面几项配置 …

鸿蒙开发之ArkTS 基础九 枚举类型

枚举把变量固定在特定的范围内 枚举的语法&#xff1a; enum 枚举名字 { 常量1 值1, 常量1 值1, 常量1 值1, ... } 定义具体如下: 使用具体如下&#xff1a;

【无人机设计与控制】四旋翼无人机俯仰姿态保持模糊PID控制(带说明报告)

摘要 为了克服常规PID控制方法在无人机俯仰姿态控制中的不足&#xff0c;本研究设计了一种基于模糊自适应PID控制的控制律。通过引入模糊控制器&#xff0c;实现了对输入输出论域的优化选择&#xff0c;同时解决了模糊规则数量与控制精度之间的矛盾。仿真结果表明&#xff0c;…

【探索数据结构与算法】希尔排序原理、实现与分析(图文详解)

目录 一、 引言 二、算法思想 三、算法步骤 四、代码实现 五、复杂度 &#x1f493; 博客主页&#xff1a;C-SDN花园GGbond ⏩ 文章专栏&#xff1a;探索数据结构与算法 一、 引言 希尔排序&#xff08;Shell Sort&#xff09;是插入排序的一种更高效的改进版本&#x…

vulnhub靶机:Skytower

下载 下载地址&#xff1a;https://www.vulnhub.com/entry/skytower-1,96/ 导入靶机 解压发现是VirtualBox格式的&#xff0c;下载一个VirtualBox&#xff1a;Downloads – Oracle VirtualBox 选择解压后的vbox文件&#xff0c;然后点击左上角管理 点击导出虚拟电脑&#xff…

Datawhale------Tiny-universe学习笔记——Qwen

1. Qwen整体介绍 对于一个完全没接触过大模型的小白来说&#xff0c;猛一听这个名字首先会一懵&#xff1a;Qwen是啥。这里首先解答一下这个问题。下面是官网给出介绍&#xff1a;Qwen是阿里巴巴集团Qwen团队研发的大语言模型和大型多模态模型系列。其实随着大模型领域的发展&a…

卡尔曼滤波中Q和R与噪声的关系

卡尔曼滤波 一种用于估计系统状态的递归滤波器&#xff0c;通过融合传感器测量和系统模型&#xff0c;提供系统状态的最优估计。 Q和R是什么 在卡尔曼滤波中&#xff0c;Q和R分别表示过程噪声和测量噪声的协方差矩阵。 Q Q Q矩阵&#xff08;过程噪声协方差矩阵&#xff09;…

电子连接器温升仿真教程 一

电子连接器温升是指电子连接器的所有端子在施加额定电载荷的情况下,经过一段时间后,达成热平衡,连接器局部温度不再继续升高,此时规定测试点的温度与测试环境温度的差值。连接器的温升规格值因其应用环境不同,而不同。工业应用,且不与人体接触的电子连接器一般允许温升会…

日系编曲:电吉他音色制作 拾音器选择 电吉他音色制作逻辑 音箱分类 效果器单块分类

拾音器选择 拾音器&#xff1a;获取琴弦震动产生电信号经过线材传输到音箱&#xff08;amp&#xff09;使听众听到 一般的电吉他分为三块和两块拾音器&#xff0c;挡位分为三档或五档 Bridge&#xff08;琴桥拾音器&#xff09;&#xff1a;声音更加清晰&#xff0c;音色更突…

[JAVA]介绍怎样在Java中通过字节字符流实现文件读取与写入

一&#xff0c;初识File类及其常用方法 File类是java.io包下代表与平台无关的文件和目录&#xff0c;程序中操作文件和目录&#xff0c;都可以通过File类来完成。 通过这个File对象&#xff0c;可以进行一系列与文件相关的操作&#xff0c;比如判断文件是否存在&#xff0c;获…

第3步VM的虚拟机无法用网络安装直接改用CDROM镜像包安装软件

精简版的CentOS只有ip add可用 ping命令可用其它软件版本太低都不能用&#xff0c;改用光盘镜像来安装软件。 步骤&#xff1a;1、修改Vm的设置&#xff0c;将光盘映像改为ISO文件。 步骤&#xff1a;2、在centos挂载cdrom 步骤&#xff1a;3、挂载成功后直接安装软件 发现软件…

认知杂谈68《燃爆!兄弟萌不可错过的人生开挂宝典》

内容摘要​&#xff1a; 生活如舞台&#xff0c;我们要做自己人生的导演兼主演。实现自我成长需打牢基础&#xff0c;如读《认知觉醒》等书并制定成长计划。 要向上生长&#xff0c;定短期和长期目标&#xff0c;学新技能、提升沟通能力&#xff0c;可借助在线平台和社群。用番…

面试经典150题——多数元素

目录 题目链接&#xff1a;169. 多数元素 - 力扣&#xff08;LeetCode&#xff09; 题目描述 示例 提示&#xff1a; 解法一&#xff1a;哈希表 Java写法&#xff1a; C写法&#xff1a; 解法二&#xff1a;它就在那里 Java写法&#xff1a; C写法&#xff1a; 解法…

求n至少为多大时,n个1组成的整数能被2013整除

题目&#xff1a;编写程序&#xff0c;求n至少为多大时&#xff0c;n个1组成的整数能被2013整除 #include<iostream> using namespace std; int main(){int n1;int m1;while(m%2013!0){m(m%2013)*101;n;}cout<<n<<endl;return 0; } 思路&#xff1a;直接用n…

2024年上海小学生古诗文大会倒计时一个月:做几道2024官方模拟题

2024年上海市小学生古诗文大会自由报名活动的初赛日期于10月19日开始&#xff0c;距离今天只有33天了。 那么如何准备2024年的小学生古诗文大会的自由报名初选呢&#xff1f;吃透&#xff08;记熟&#xff09;2024年小学生古诗文阅读专辑上的题目、知识点和往年真题及知识点。…