ubuntu 18.04 ros1学习

总结了一下,学习内容主要有:

1.ubuntu的基础命令

   pwd: 获得当前路径

   cd: 进入或者退出一个目录

   ls:列举该文件夹下的所有文件名称

   mv 移动一个文件到另一个目录中

  cp 拷贝一个文件到另一个目录中

   rm -r 删除文件

  gedit 

  sudo 给予管理员权限 

  sudo apt-get install

  sudo pkg -i xx.deb

  unzip xx.zip 解压缩zip文件

  zip -r archive_name.zip directory_to_compress  压缩 目录到文件中

   

2.ros工作空间的构建

    2.1 典型的功能包创建和运行过程

   

2.2一个ros工作空间的目录架构

2.3 代码过程

//1. 创建工作空间
mkdir -p ~/ws_test/src
//2. 进入工作空间
cd ws_test
//3. 初始化工作空间,会生成build,devel,build存放编译信息,devel存放可执行文件与相关依赖项,src文件存放代码
catkin_make

//4. cd src
//5. 创建包,宝引用了roscpp
catkin_create_pkg helloworld roscpp 

//6. 写程序,鼠标点击helloworld包的src,创建helloworld.cpp文件,文件中写如下内容
int main(int argc, char** argv)
{
    ros::init(argc,argv, "node_name");
    ROS_INFO("helloworld");
    return 0;
}

//7. 在CMakeLists.txt中配置, 指定生成可执行文件
add_executable(helloworld src/helloworld.cpp)
target_link_library(helloworld ${catkin_LIBRARY})

//8. 对工作空间进行编译,回退到ws_test目录下
catkin_make编译

//9.运行,在一个终端中启动roscore,在另一个终端中启动可执行文件rosrun pkg包名字  exe可执行文件名
//9.1 roscore
//9.2 

source ./devel/setup.bash
rosrun helloworld helloworld

ros通讯机制

【摘抄书中的】同此歌行来说,一个移动机器人项目是多个进程协同完成的,除了极少部分进程可以独立完成自己的之外,其他的进程均需要进行进程之间的数据交互,因此进程间的通讯机制是构建复杂机器人项目的基础。

ROS节点

在ros的世界中,最小的进程单元就是节点Node,通常一个node负责机器人的一个单独模块。一个package中可以有多个可执行文件(通常为C++编译生成的可执行文件或者python脚本),可执行文件在运行之后就形成了一个进程,这个进程就是ros节点。

节点管理器master

节点管理器Master在整个网络通讯中相当于管理中心,管理着各个节点(Node),节点在启动的时候,首先要在Master中进行注册,之后Master会将该节点NODE纳入到整个ros系统中。Node之间的通讯也是由Master进行牵线,然后才能两两的进行点对点的通讯。当ROS节点启动的时候,首先启动Master,再由节点管理器以此启动Node。

换句话说,节点管理器实际上扮演了一个“通讯调度中心”的角色,它启动之后,各个Node之间才会建立相应的关联。但是,在Node连接建立之后,Master的任务就完成了,此时如果关闭Masetr,已经运行的Node之间的通信还可以继续进行。

ros通讯方式有4种,分别是:

1.topic话题通讯模式

2.Service服务模式

3.Parammeter Service模式

4.Actionlib模式

3.话题的订阅、发布、消息自定义

Topic话题订阅模式是一种ROS常见的通讯方式,对于实时性、周期性的消息,使用Topic模式来传输消息是最佳选择,Topic模式是一种点对点的单项通讯方式,这里的点指的是Node,也就是节点之间可以通过Topic来传递消息。Topic话题主要经历下面的初始化过程:首先,Publisher发布者节点和subscriber订阅者节点都要到节点管理器Master中进行注册;然后,Publisher会发布Topic话题,

每一个节点只接受话题所发布的数据,发布数据后至于接收者是否接收到数据,那就和这个节点无关了。结合小海龟,来说明一下话题发布和订阅如何使用:

//1.构建工作空间
  mkdir ~/mrobot_ws/src
  catkin_create_pkg learning_topic roscpp rospy std_msgs geometry_msgs turtlesim
  
  这时候在src文件夹下生成了learing_topic/include和 learning_topic/src两个目录
//2. 在learning_topic/src下创建velocity_publisher.cpp文件,代码如下:
#include<ros/ros.h>
#include<geometry_msgs/Twist.h>
int main(int argc, char** argv)
{
    ros::init(argc, argv, "velocity_publisher");
    ros::NodeHandle nh;
    ros::Publisher turtle_vel_pub = ros::advertise<egometry_msgs::Twist>("turtle1/cmd_vel",10);

    ros::Rate loop_rate(10);
    while(ros::ok())
   {
       geometry_msgs Twist tw;
       tw.linear.x = 0.5;
       tw.angular.z = 0.2;
       turtle_vel_pub.pub(tw);
       ROS_INFO("Publish turtle velocity command["%0.2f m/s, %0.2f rad/s]", tw.linear.x, tw.angular.z);
       loop_rate.sleep();
   }
}


//3. 配置 CMakeList.txt
add_executable(velocity_publisher src/velocity_publiser.cpp)
target_link_libraries(velocity_publiser ${catkin_LIBRARY})

//4.编译以及运行
cd mrobot_ws
catkin_make
source ./devel/setup.bash
// 在一个终端中启动ros
roscore

//在另一个终端中,启动小乌龟
rosrun turtlesim turtlesim_node

//在第三个终端中启动velocity_publiser
rosrun learning_topic velocity_publiser

//启动第四个终端中,查看消息
rostopic list





消息订阅

//1.在learning_topic下的src文件夹下创建pose_subscriber.cpp文件,文件内容为:
#include<ros/ros.h>
#include<turtlesim/Pose.h>

void poseCall(const turtlesim::Pose::ConstPtr& msg)
{
    ROS_INFO("turtle pse, x:%0.6f, y:%0.6f, msg->x, msg->y);
}

int main(int argc, char** argv)
{
    ros::init(argc,argv,"pose_subsrciber");

    ros::NodeHandle nh;
    ros::Subscriber pose_sub = ros::subscribe("/turtle1/pose",10,poseCall);
    
    ros::spin();
}

//2.在CMakeList.txt中写入
add_executable(pose_subscriber src/pose_subsrciber.cpp)
target_link_libraries(pose_subscriber ${catkin_LIBRARIES})

//3.编译并运行
cd mrobot_ws
catkin_make
source ./devel/setup.bash
//3.1在第一个终端中启动ros
roscore
//3.2在第二个终端中启动小乌龟
rosrun turtlesim turtlesim_node

//3.3在第三个终端中,使用订阅者
source ./devel/setup.bash
rosrun learning_topic pose_subscriber





topic消息自定义

//1.在learning_topic文件夹下创建msg文件,msg文件夹下创建Person.msg文件,内容如下:
    string name
    uint8 sex
    uint8 age
    uint8 unknown = 0
    uint8 male = 1
    uint8 female = 2

//2.在package.xml中添加功能包依赖项,将如下内容添加到package.xml中
  <build_depend>message_generation</build_depend>
<build_export_depend>message_generation</build_export_depend>
<exec_depend>message_runtime</exec_depend>

//3.在CMakeList.txt中添加编译选项,将以下内容添加到CMakeLists.txt文件的对应位置
   find_package(... message_generation...)
   catkin_package(... CATKIN_DEPENDS roscpp rospy std_msgs turtlesim geometry_msgs message_runtime ...)
   add_message_files(FILES Person.msg)
   
   generate_message(DEPENDENCIES std_msgs)

//4. 编译程序
  cd mrobot_ws
  catkin_make

/*----------------------------发布消息------------------------------------*/

//1.在learning_topic/src目录下创建person_publisher.cpp文件,内容为:
#include<ros/ros.h>
#include<learning_topic/Person.h>
int main(int argc, char** argv)
{
    ros::init(argc,argv,"person_publisher");
    ros::NodeHandle nh;
    ros::Publisher person_info_pub = ros::advertise<learning_topic::Person>("/person_info",10);
    ros::Rate loop_rate(10);
    while(ros::ok())
    {
       learning_topic lt;
       lt.name = "Tom";
       lt.age = 18;
       lt.sex = learning_topic::Person::male;
       person_info_pub.pub(lt);
       ROS_INFO("Publish Person Info: name: %s, age:%d, sex:%d", lt.name.c_str(),lt.age,lt.sex);
       loop_rate.sleep();
     }
}

//2.在CMakeLists.txt中添加
add_executable(person_publisher src/person_publisher.cpp)
target_link_libraries(person_publisher ${catkin_LIBRARIES})
add_dependencies(person_publisher ${PROJECTION_NAME}_generate_messages_cpp)

/*********************************订阅消息***********************/
//1. 在learning_topic/src目录下新建person_subscribe.cpp文件,文件内容为:
#include<ros/ros.h>
#include<learning_topic/Person.h>

void person_info_callBack(const learning_topic::Person::ConstPtr& msg)
{
    ROS_INFO("subscribe person info: name: %s, age: %d, sex: %d",msg->name, msg->age, msg->sex);
}

int main(int argc, char** argv)
{
    ros::init(argc,argv,"subscribe_person_info");
    ros::NodeHandle nh;
    ros::Subscriber sub = nh.subscribe("/person_info",10,person_info_callBack);
    ros::spin();

}

//2. 配置CMakeLists.txt
add_executable(person_subscriber src/person_subscriber.cpp)
target_link_libraries(person_subscriber ${catkin_LIBRARIES})
add_dependencies(person_subscriber ${PROJECTION_NAME}_generate_messages_cpp)

4.服务的订阅、发布、服务自定义

topic话题通讯方式是一种单向的通讯方式,单向通讯并不能完全满足通讯要求,这些任午请求后希望得到回复,并且这些业务是临时的非周期性的任五,如果采用topic话题通讯方式,将会造成大量不必要的浪费。为了解决问题,ROS提供了service服务模式,service服务包含两个部分:一部分是请求方(CLient),另一部分是应答方(Server).service是双向的,Client发送一个请求Request给Server,要等待Server处理并反馈一个Reply,这样通过“请求-应答”机制完成了整个服务通讯。

请求方Client创建具体步骤如下:

//1. 创建实例项目
cd ~/mrobot_ws/src
catkin_create_pkg learning_service roscpp rospy std_msgs geometry_msgs turtlesim

//2. 在learning_service/src文件夹下,建turtle_spqwn_request.cpp文件,内容如下:
#include<ros/ros.h>
#include<turtlesim/Spawn>

int main(int argc, char** argv)
{
    ros::init(argc,argv, "turtle_spqwn");
    ros::service::waitForService("/spawn")
    ros::ServiceClient add_turtle = nh.serviceClient<turtlesim::Spawn>("/spawn");
    
    turtlesim::Spawn srv;
    srv.request.x = 2.0;
    srv.request.y = 2.0;
    srv.request.name = "turtle2";
    
    ROS_INFO("Call service to spawn turtle[x:%0.6f, y:%0.6f,name:%s]",srv.request.x, srv.request.y, srv.request.name);
    add_turtle.call(srv);
    ROS_INFO("Spawn turtle successfully[name:%s]", srv.response.name.c_str());

}

//2.CMakeList.txt添加
add_executable(turtle_spawn_request src/turtle_spawn_request.cpp)
target_link_libraries(turtle_spawn_request ${catkin_LIBRARIES})

//3. 编译并运行程序
catkin_make
//3.1启动第一个终端
roscore
//3.2启动第二个终端
source ./devel/setup.bash
rosrun turtlesim turtlesim_node

//启动第三个终端
source ./devel/setup.bash
rosrun learning_topic turtle_spawn_request



/*************************服务端***********************/
#include<ros/ros.h>
#include<turtlesim/Spawn>

ros::Publisher turtle_vel_pub;
bool pubCommand = false;

bool commandCallBack(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res)
{
    pubCommand = !pubCommand;
    ROS_INFO("Publish turtle velocity command[%s]", pubCommand == true? "YES":"NO");
    res.success = true;
    res.message = "change turtle command state!";
    return true;
}

int main(int argc, char** argv)
{
    ros::NodeHandle nh;
    ros::ServiceServer command_service = nh.advertiseService("/turtle_command",commandCallBack);
    
    turtle_vel_pub = nh.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",10);
    ros::Rate loop_rate(10);
    
    while(ros::ok())
    {
        ros::spineOnce();
        if(pubCommand)
        { 
           geometry_msgs::Twist vel_msg;
           vel_msg.linear.x = 0.5;
           vel_msg.angular.z = 0.2;
           turtle_vel_pub.pub(vel_msg);
        }
        loop_rate.sleep();
    }

}

//CMakeLists.txt 中编译
add_excutable(turtle_command_server src/turtle_command_server.cpp)
target_link_libraries(turtle_command_server ${catkin_LIBRARIES});

//3. 编译运行
catkin_make
roscore
rosrun turtlesim turtlesim_node

//启动第三个终端
source ./devel/setup.bash
rosrun learning_service turtle_command_server
rosservice call/turtle_command"{}"












4.action的订阅、发布、action自定义

5.TF变换

6.param文件 param,node,group,rosparam

参数命令

rosparam list 列出当前所参数

rosparam get param_key //显示某个参数值

rosparam set param_key param_value // 设置某个参数值

rosparam dump file_name // 保存参数到文件

rosparam load file_name // 从文件中读取参数

rosparam delete param_key // 删除参数

用法:

//1.创建包
cd ~/catkin_ws/src
catkin_create_pkg learning_parammeter roscpp rospy std_srvs

//2.在learning_parameters的src下创建parameter_config.cpp文件,内容如下:
#include<string>
#include<ros/ros.h>
#include<std_srvs/Empty.h>

int main(int argc, char** argv)
{
   ros::init(argc, argv, "parameter_config");
   ros::NodeHandle nh;
   
   int red, green, blue;
   ros::param::get("/turtlesim/background_r",red);
   ros::param::get("/turtlesim/background_r",green);
   ros::param::get("/turtlesim/background_r",blue);

   ros::param::set("/turtlesim/background_r",red);
   ros::param::set("/turtlesim/background_r",green);
   ros::param::set("/turtlesim/background_r",blue);


   ros::service::waitForService("clear");
   ros::ServiceCLient clear_background = nh.serviceCLient<std_srvs::Empty>("/clear");
   std_srvs::Empty srv;
   clear_background.call(srv);
}


//2.在CMakeLists.txt中
add_executable(learning_parammeter  src/learning_parammeter.cpp)
target_link_libraries(learning_parammeter ${catkin_LIBRARIES)};

//3.编译运行
//3.1启动第一个终端
roscore
//3.2启动第二个终端
rosrun turtlesim turtlesim_node
//3.3启动第三个终端
source devel/setup.bash
rosrun learning_parameter parameter_config

7.launch文件

launch 文件格式为

<launch>
    ...
</launch>

1. roslaunch 命令

roslaunch [package] [filename.launch]

   package是一个包名,file.launch是一个launch文件名字。通常一个pkg包含了多个可执行文件,而多个可执行文件可以用launch文件同时启动。比如启动 小乌龟 roslaunch learning_tf start_turtle.launch

roslaunch中<>类型主要有以下几种

<launch>
    <node .../>
    <rosparam .../>
    <remap .../>
    <machine .../>
    <param .../>
    <include .../>
    <env .../>
    <arg .../>
    <test .../>
    <group>  </group>
</launch>

  1. node
<node pkg ="learning_tf" type = "turtle_tf_broadcaster" args = "/turtle1" name ="turtle1_tf_broadcaster" respawn="true" output="sceen"/>

pkg为包名,

type为节点名字,也就是ros::init()第三个参数的名字,

name为可执行文件名字,

args为传入的参数

respawn 是否重新启动,如果设置为true,则非自然退出后会自动重启

output 是否将节点信息输出到屏幕,如果不设置该属性,则节点信息会被写入到日志文件;

node 标签下页可以嵌套使用以下标签:

  • env:为节点设置环境变量
  • remap:为节点设置重映射参数
  • rosparam:为节点加载 rosparam 文件
  • param:为节点设置参数

2.rosparam

<param name="flush_frequency" type="double" value="1.0">

name表示参数名

type表示参数类型

value表示参数值

<remap from="A" to="B">

    from:原始名称
    to:新名称

A和B数据类型相同,可以将A简单地替换为B,从而订阅B话题。

<launch>
    <machine name="foo" address="foo-address" env-loader="/opt/ros/kinetic/env.sh" user="someone">
    <node machine="foo" name="footalker" pkg="test_ros" type="talker.py">
</launch>

主要参照这一

ROS-Launch的使用方式_roslaunch-CSDN博客

8.如何用在实际中?
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/2301_80395245/article/details/139304457

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uniapp实现图片上传——支持APP、微信小程序

uniapp实现图片、视频上传 文章目录 uniapp实现图片、视频上传效果图组件templatejs 使用 相关文档&#xff1a; 结合 uView 插件 uni.uploadFile 实现 u-upload uploadfile 效果图 组件 简单封装&#xff0c;还有很多属性…&#xff0c;自定义样式等…根据个人所需调整 te…

DNF手游攻略:勇士进阶指南!

在即将到来的6月5日&#xff0c;《DNF手游》将迎来一场盛大的更新&#xff0c;此次更新带来了大量新内容和玩法&#xff0c;极大丰富了游戏的体验。本文将为广大玩家详细解析此次更新的亮点&#xff0c;包括新增的组队挑战玩法“罗特斯入门团本”、新星使宠物的推出、宠物进化功…

ADB日常使用命令

【ADB全称 Android Debug Bridge】 是Android SDK中的一个命令行工具adb命令可以直接操作管理Android模拟器或真实的Android设备&#xff08;手机&#xff09; 建立PC和模拟器连接 # 建立连接 adb connect 127.0.1: 模拟器端口号〈逍遥模拟器21503〉 # 验证是否连接成功 adb d…

NFS p.1 服务器的部署以及客户端与服务端的远程挂载

目录 介绍 应用 NFS的工作原理 NFS的使用 步骤 1、两台机子 2、安装 3、配置文件 4、实验 服务端 准备 启动服务&#xff1a; 客户端 准备 步骤 介绍 NFS&#xff08;Network File System&#xff0c;网络文件系统&#xff09;是一种古老的用于在UNIX/Linux主…

使用 Apache Commons Exec 管理外部进程

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

基于 Apache Doris 的实时/离线一体化架构,赋能中国联通 5G 全连接工厂解决方案

作者&#xff1a;田向阳&#xff0c;联通西部创新研究院 大数据专家 共创&#xff1a;SelectDB 技术团队 导读&#xff1a; 数据是 5G 全连接工厂的核心要素&#xff0c;为支持全方位的数据收集、存储、分析等工作的高效进行&#xff0c;联通 5G 全连接工厂从典型的 Lambda 架…

使用PNP管控制MCU是否需要复位

这两台用到一款芯片带电池&#xff0c;希望电池还有电芯片在工作的时候插入电源不要给芯片复位&#xff0c;当电池没电&#xff0c;芯片不在工作的时候&#xff0c;插入电源给芯片复位所以使用一个PNP三极管&#xff0c;通过芯片IO控制是否打开复位&#xff0c;当芯片正常工作的…

在长窗口时代,RAG技术是否仍然必要?

自从谷歌推出 Gemini 1.5 Pro&#xff0c;行业内部对于 RAG 的讨论就不绝于耳。 Gemini 1.5 Pro 的性能确实令人瞩目。根据谷歌公布的技术文档&#xff0c;该系统能够稳定处理长达 100 token 的内容&#xff0c;相当于一小时的视频、十一小时的音频、超过三万行的代码或七十万…

Spring Cloud Alibaba-09-Seata分布式事务

Lison <dreamlison163.com>, v1.0.0, 2024.5.03 Spring Cloud Alibaba-09-Seata分布式事务 文章目录 Spring Cloud Alibaba-09-Seata分布式事务分布式事务基础事务本地事务分布式事务分布式事务的场景 分布式事务的解决方案全局事务可靠消息服务最大努力通知TCC事务 Se…

Java实现数据结构---数组

文章目录 概念存储原理数组的操作完整代码 概念 数组是&#xff08;Array&#xff09;是有限个相同类型的变量所组成的有序集合&#xff0c;数组中的每一个变量为称为元素。数组是最简单、最常用的数据结构。 数组下标从零开始。 存储原理 数组用一组连续的内存空间来存储一…

蓝桥杯第17135题 不完整的算式 C++ Java Python

目录 题目 思路和解题方法 步骤 1&#xff1a;识别缺失的部分 步骤 2&#xff1a;根据已知条件计算或推断 步骤 3&#xff1a;处理特殊情况和验证 c 代码 Java 版本 Python 版本&#xff08;仅供参考&#xff09; 代码和解题细节&#xff1a; 题目 题目链接&#xff…

STM32自己从零开始实操03:输出部分原理图

一、继电器电路 1.1指路 延续使用 JZC-33F-012-ZS3 继电器&#xff0c;设计出以小电流撬动大电流的继电器电路。 &#xff08;提示&#xff09;电路需要包含&#xff1a;三极管开关电路、续流二极管、滤波电容、指示灯、输出部分。 1.2数据手册重要信息提炼 联系排列&…

神经网络与深度学习——第3章 线性模型

本文讨论的内容参考自《神经网络与深度学习》https://nndl.github.io/ 第3章 线性模型 线性模型 线性模型&#xff08;Linear Model&#xff09;是机器学习中应用最广泛的模型&#xff0c;指通过样本特征的线性组合来进行预测的模型&#xff0c;给定一个 D D D维样本 x [ x …

解锁 GPT-4o 背后数据带来的情绪价值

GPT-4o 可以说已经是一个富有情感、通人性的智能语音助手&#xff0c;或者更准确地说&#xff0c;是一个越来越接近人类交互的 “新物种”。这个强大的模型同时具备文本、图片、视频和语音理解和合成方面的能力&#xff0c;甚至可以被视为 GPT-5 的一个未完成版。 01 富有情感的…

lipo制作通用版本静态库

文章目录 目的了解多架构的maclipo如何利用lipo编译通用版本静态库lipo 命令整理扩展目的 主要是使用lipo命令在macOS上创建通用版本的静态库(.a文件),来支持多种架构,如arm64,x86_64。 学习目的: 了解mac 不同架构arm64, x86_64了解lipo命令了解多架构的mac 随着appl…

Linux - 文件管理高级1

0.管道 | 将前面命令的标准输出传递给管道作为后面的标准输入 1.文件查找 find find 进行文件查找时&#xff0c;默认进行递归查找&#xff0c;会查找隐藏目录下的文件 1.1 用法 # find 查找路径 查找条件... -type // 文件类型 f 普通文件 b 设备 d …

数据目录用处如此之大?四个步骤教你构建数据目录

在数字化浪潮的推动下&#xff0c;数据已成为企业决策的核心。然而&#xff0c;随着数据量的爆炸性增长&#xff0c;如何高效地管理和利用这些宝贵的数据资产&#xff0c;成为了一个日益严峻的挑战。企业需要一个强大的工具来组织、索引和解释其数据&#xff0c;以便快速发现和…

代理IP怎么检测?如何判断IP好坏?

当我们的数字足迹无处不在&#xff0c;隐私保护显得愈发重要。而代理IP就像是我们的隐身斗篷&#xff0c;让我们在各项网络业务中更加顺畅。 我们常常看到别人购买了代理IP服务后&#xff0c;用在线检测网站检查IP&#xff0c;相当于一个”售前检验““售后质检”的作用。但是…

图书管理系统——Java实现

文章目录 Java实现图书管理系统问题分析框架搭建业务实现项目测试代码演示BookioperationUserMain&#xff08;默认包&#xff09; Java实现图书管理系统 学习了前六篇的SE语法&#xff0c;我们现在要用它们实现一个简单的图书管理系统项目&#xff0c;深入了解各个知识点的应…

【CH32V305FBP6】4. systick 配置

配置 main.c void SYSTICK_Init_Config(u_int64_t ticks) {SysTick->SR & ~(1 << 0);//clear State flagSysTick->CMP ticks - 1;SysTick->CNT 0;SysTick->CTLR 0xF;NVIC_SetPriority(SysTicK_IRQn, 15);NVIC_EnableIRQ(SysTicK_IRQn); }中断计数 …