掌上单片机实验室 – 基于框架编写第一个程序(9)

掌上单片机实验室 – RT-Thread + ROS2 初探(25) 得知 ROS 升级为 ROS2 后,将 rosserial 升级为可以在单片机上运行的 Micro_ROS,大大提升了性能。关键是 RT-Thread 中包含了 Micro_ROS 软件包,正好可以尝试一下,。于是有了文中的经历。 阅读详情

一、背景

        编程学习的目的是为了日后在工作中可以有相应的能力,应对现实需求。在学习阶段编程的目的和工作不同,工作中编程目的是为了解决问题,而学习阶段编程的目的是掌握编程技能,培养良好的编程习惯,解决问题的需求只是载体,并非目的,和学数学时的应用题性质一样。

        为编程学习构建程序框架,目的就在于此。

        程序框架及配套的PC机UI操控界面已经完成,现在就尝试一下基于程序框架编写第一个应用:将前面激活硬件的三个程序纳入到框架中,作为测试程序的三个功能。

二、需求

        这个应用很简单,需求为:

        1、将三个测试程序的功能整合到框架程序中,可以分别执行。

        2、测试功能选择通过串口命令、借助于PC界面实现。

三、尝试

3.1 构思

        在程序框架设计时,预设了两个应用任务:主任务、其它任务。

        主任务设计是作为应用管理的,其它任务设计是为了示意,编写具体应用时,取代之。

        将第一个应用作为硬件测试应用,增加的任务命名为:测试任务,取代“其它任务”。

        将前面三个激活硬件的测试程序作为测试任务的三个功能,串口接收任务收到操作命令后转发给主任务,主任务将命令转发给测试任务。同时通过数据发送任务应答,告知命令收到。

        测试任务根据收到的操作命令执行,并定时反馈测试工作状态。

        主任务支持读状态命令,可以返回测试任务当前的工作状态。

        要修改的是相关变量的定义(用Test取代Other),以及增加的变量定义。基础任务(串口命令接收、串口数据发送、调试信息输出、看护任务)基本不变,只是涉及到Other的改为Test。

        主要修改的是主任务任务,需要编写的是测试任务。

3.2 实施

3.2.1 定义操作命令

        将三个测试功能定义为:

        1)测试A(TestA):执行原来的激活程序1,因为可以用命令操作,增加了三个操作参数:左侧电机PWM、右侧电机PWM、运行时间。原来这些是写在程序中的常量,原来程序是两侧分别正、反转,小车原地打转,现在可以通过设置左右侧PWM,让小车原地打转或前进、后退。

        2)测试B(TestA):执行原来的激活程序2,因为可以用命令操作,增加了三个操作参数:左侧电机PWM、右侧电机PWM、运行脉冲数。这个测试是先左侧运转设定脉冲数,再右侧运转设定脉冲数。

        3)测试C(TestC):执行原来的激活程序3,同样支持三个参数:左侧电机PWM、右侧电机PWM、运行脉冲数。和测试B区别在于 — 两侧同时运转,一侧运转到脉冲数则停止,两侧运转的脉冲数一样。同时在运转时采集两侧的电机供电电压和电流,通过调试信息通道输出,目的是测试一下模拟量采集功能的Arduino实现。

        具体操作确定后,定义操作命令(读、写内存命令不变):

        A)命令3:读工作状态命令(Key = 3,Len = 0)

                0x03 0x00 0x00

        应答内容:

                0x03 0x04 0x00 左侧电机PWM(1字节) 右侧电机PWM(1字节)剩余工作时间或脉冲数(2字节)

        PWM 为 1字节有符号数,范围 -100 ~ 100,正数前进,负数倒退,0 - 停止

        B)命令4:测试动作A(Key = 4,Len = 4,Val:1字节左侧 PWM,1字节右侧 PWM,2字节时间)

                0x04 0x04 0x00 左侧电机PWM(1字节) 右侧电机PWM(1字节)2字节运行时间

        PWM 为 1字节有符号数,范围 -100 ~ 100,正数前进,负数倒退,0 - 停止

        运行时间单位:秒

        应答内容:

                0x04 0x04 0x00 左侧电机PWM(1字节) 右侧电机PWM(1字节) 剩余工作时间(2字节)

        C)  命令5:测试动作B(Key = 5,Len = 4,Val:1字节左侧 PWM,1字节右侧 PWM,2字节脉冲数)  

                0x05 0x04 0x00 左侧电机PWM(1字节) 右侧电机PWM(1字节)2字节运行脉冲数

        PWM 为 1字节有符号数,范围 -100 ~ 100,正数前进,负数倒退,0 - 停止

        脉冲数单位:个

        应答内容:

                0x05 0x04 0x00 左侧电机PWM(1字节) 右侧电机PWM(1字节)剩余脉冲数(2字节)

        D)  命令6:测试动作C(Key = 6,Len = 4,Val:1字节左侧 PWM,1字节右侧 PWM,2字节脉冲数)

                0x06 0x04 0x00 左侧电机PWM(1字节) 右侧电机PWM(1字节)2字节运行脉冲数

        PWM 为 1字节有符号数,范围 -100 ~ 100,正数前进,负数倒退,0 - 停止        

        脉冲数单位:个

        应答内容:

                0x04 0x04 0x00 左侧电机PWM(1字节) 右侧电机PWM(1字节)剩余脉冲数(2字节)

        此测试只是增加了运转时工作电压和电流的输出,暂定用 Dump 通道。

        提示:上述命令的返回内容一样,针对常见的设备操作命令,一般均可以将关注的工作状态作为应答内容,用统一的帧格式处理,虽说可能会冗余一点,但对应接收端的数据解析编程而言,会方便很多,也减少了出错概率。

3.2.2 定义相关数据

        重新定义触发事件名(将Other 改为 Test):

         定义操作命令:

        定义主任务和测试任务之间的交互数据:

         定义相关硬件资源(放在BoardConfig.h文件中):

3.2.3 修改主任务的命令解析

        对主任务的命令解析执行部分做相应修改,支持新定义的命令:

        其中,读工作状态处理函数完成将测试任务返回的工作状态数据填入发送数据区:

         转发给测试任务操作命令的函数 SetOpData 完成从串口命令数据中提取命令及参数,填入主任务与测试任务的交互数据结构中:

        虽说三个操作处理一样,但此处仍使用了Switch结构,主要是为了便于扩充。

3.2.4 构建测试任务

        测试任务将原来三个测试程序均包含在内,故首先要完成硬件初始化,这部分就用到了程序框架设计中的初始化同步机制,将测试相关的硬件初始化放置在测试任务的初始化部分:

        测试任务的核心操作是控制电机,为便于处理,增加程序可读性和可维护性,构建电机操作函数(完整函数见程序):

         应用任务基本处理模式为:

        1)接收主任务消息,解析执行。

        2)定时唤醒,处理自身正在执行的操作。

        此处,对主任务的响应如下:

        根据命令启动相应的操作,如测试A(完整处理见附件):

         注意:前面设计框架时提过 —— 任务内不能有长时间的“逗留”,应尽快执行完操作后进入阻塞等待状态。但测试A的操作是电机运行一段时间后停止,该如何处理?

        通常处理方式有两种:

        A)启用硬件定时器,时间到后执行停止电机操作,完成当前命令。

        B)定时唤醒程序,执行软计时,时间到后停止电机、完成当前命令。

        因本篇目的是将原来的激活程序纳入到程序框架中,看看是否可以方便的实现基于程序框架的编程模式,并非以程序实现功能为主题,故不希望加入太多额外的内容,尽量使用 RTOS 所提供的资源。所以采用第二种方式:软计时。

        每个OS都有一个Tick,即操作系统周期性处理的最小时间,Free RTOS同样有,并且提供了一个钩子函数,以便应用编程可以方便的加入自己的内容。

        在程序框架设计中,串口接收任务及看护任务均利用了Tick,测试任务也用Tick计时。首先在Tick的钩子函数中增加唤醒测试任务的消息:

        在测试任务中响应此消息,执行软件计时操作,完成测试命令A:

        这种方式可以运用到应用中的很多场景,只要是计时要求不是很高(tick通常是ms级别,本程序框架为5ms),都可以应对,包括一些可以查询方式处理的操作,如串口接收任务中的命令接收,因为有串口硬件接收缓冲,不会丢失输出,程序只是在应用层面处理,无很强的时间要求。

        周期性将测试状态发送给主任务也是基于Tick的软计时处理:

        测试任务处理流程已完整实现,主任务的如何响应测试任务发来的数据呢?

3.2.5 主任务接收测试任务数据

        测试任务在执行操作时,定时将当前工作状态发送给主任务,以便主任务在相应读状态命令时,可以及时返回当前状态。

        因为定义了相应的任务间传输数据结构,故处理很简单:

        至此,第一个应用程序全部完成,上述实现顺序就是设计构思的流程。学习编程者很多会感觉开始时无处下手,其实并不难,只要梳理好以下几点即可:

        1)需求:到底要实现什么?

        2)现实世界的实现过程:撇开程序,假设是你自己在做,应该一步步怎么做?

        3)将自己做的过程映射到程序步骤中。

        4)梳理约束条件,用已有资源化解,如上述计时问题。

3.3 调试

        从上面的程序截图中可以看到,程序中有许多 Println 语句,那些就是调试信息输出,因为基于RTOS编程是多任务模式,每个任务相当于一个人,各自在做自己的事情,通过交互实现协调,共同完成一个任务,通过合理的设置信息输出,就可以方便的观察到程序中一个命令的执行流程:

        串口接收->帧检测->命令转发->命令接收->解析->派发->执行->返回

        为了清晰的看出是哪个任务发送的信息,在每条信息开始都标注了ID:

        CR:串口接收任务

        TX:数据发送任务

        WD:看护任务

        MT:主任务

        TT:测试任务

        上电后的输出信息:

        读内存命令的执行信息输出:

        测试命令A的执行信息输出:

        从上述输出信息可以清晰地看出程序的执行流程。

        在调试程序过程中,可以根据需要增减相应的输出,从而观察自己程序的执行是否符合设计,查找出现问题的原因。

3.4 PC操作界面

        作为辅助手段的 PC 操作界面,在每次增加功能时都要对应编写,似乎觉得有点麻烦,但如果考虑到做此事的目的就是学习编程,则这个过程所耗费的时间远比找一个可以凑合用的软件、摸索使用方法所耗费的时间值!

        PC 测试程序的框架设计上考虑了便于扩展,此处只需增加一个页面的处理即可,因为主题是单片机编程,对PC程序有兴趣可以研究代码。

        测试任务PC操作界面: 

 四、结语

        这个程序只是一个基于程序框架编程的示例,重点是演示如何在框架中添加相应的具体任务?以及如何实现操作?程序的处理流程是怎样的?

        其实编程并无唯一的正确方式,只要遵循基本的要求(可靠性、可读性、可扩展性)即可,关键是要自己培养一个合适的习惯,一套处理问题的方式。

        此程序框架只是众多可选方式的一种。

        后面从趣味性和实用性角度考虑,构思一些有趣的应用,作为素材,尝试在程序框架下编写相应的解决方案,从而为编程学习者提供应对不同需求的参考例程。

————————————

文中程序下载:

链接:https://pan.baidu.com/s/1V8TVDMe9WwCuMTEZJLW_EQ 

提取码:trgy

掌上单片机实验室 – 走出屏幕的 ROS 小海龟(27) 在上一步的基础上,完成了使用 turtle_teleop_key 节点控制虚拟和现实两个小海龟,将基于 micro_ros 软件包实现单片机和 ROS2 主机通讯的流程全部打通,后面就可以进一步尝试ROS2 的功能了。 阅读详情

相关推荐

掌上单片机实验室 – RT-Thread 激活程序1(15)

在掌上单片机实验室硬件平台上,尝试应用 RT-Thread,这是第一个程序,使用 RT-Thread 官方的 RT-Thread Studio 开发环境,完成电机 PWM 驱动,涉及 PIN及 PWM 组件。

embedream的专栏 505

单片机面向对象编程思路和方法--框架01

的形式重命名了。

2302_79069463的博客 1251

掌上单片机实验室 – 基于 RT-Thread 框架的第一个应用(18)

基于 RT-Thread 应用程序框架,将前面实现的 RTT 激活程序加入到框架中,作为硬件测试功能,创建一个测试线程,将三个硬件激活功能作为基本测试操作,用串口指令操作执行。目的是感受一下 RT-Rhread 的多线程应用,以及线程间的同步、通讯功能。

embedream的专栏 263

单片机框架式编程

框架式编程的分层: 上层,主文件,主函数对各子程序的轮回调用,主函数负责个程序的数据分配。 中层,各功能的实现,只能被主函数调用,不能调用其他的中层函数但是能调用共享数据。 能够直接使用下层驱动函数。 下层,硬件驱动,只跟匹配的硬件相关。负责与独立的硬件交换数据。 框架式编程的代码书写要求: A)文件管理上,要求名字书写格式统一。 B)函数名称上,要求按上、中、下分成命名。 C)每个文件,都设计输出变量或者输入变量。 D)不同文件的对外变量之间可

weixin_57068250的博客 473

掌上单片机实验室 – RT-Thread 激活程序2(16)

本篇继续完成激活程序的后两部分,涉及 IO 中断及模拟量采集,IO中断所用的 Pin 组件已经由工程模板帮助安装了,此处按前一篇的方式添加 ADC 组件,验证一下前面总结的是否正确。

embedream的专栏 415

掌上单片机实验室 – RT-Thread 下实现运动功能(19)

基于 RTT 应用框架,将电机驱动按实际应用需求编入程序中,尝试用 C++ 的类方式定义电机驱动功能,因为两侧电机的驱动功能相同,用一个类即可。

embedream的专栏 393

单片机框架编程整理

单片机裸机编程框架 指导思想 每一个电路模块单独编写驱动 程序。 使用定时器或者cpu来进行时间调度(使用mcu编程框架) 实现非阻塞式的程序调度体系。 文件分层、同级之间不可以互相调用数据 这样可以降低功能模块之间的耦合度,在统一平台下移植或者删减不同的功能模块之时,不会影响其他模块的功能。 各个子文件建立自己的缓冲数据域,使用函数接口的方式来实现缓冲数据的访问。 详细的原因在下面展开叙述。 规范代码书写要求,统一变量和函数的命名格式方便阅读。 某个硬件不正常工作,不能影响其他的硬件。

extern_valuable的博客 1542

【编程之美】详论单片机固件模块化架构设计

关注、星标嵌入式客栈,干货及时送达ID:嵌入式客栈作者:逸君[导读] 为什么写本文?最近遇到一些初学单片机的同学,刚刚入手做单片机开发,还没有涉及到使用RTOS,且刚入手直接上RTOS可...

李肖遥的专栏 2186

单片机开发常用的软件架构

** \brief 主函数* \param[in] 无* \retval 无*/int main()whlie(1)if(FLAG0)App_Task();FLAG0=0;/** \brief 定时器中断* \param[in] 无* \retval 无*/timCount++;//这里用条件编译,方便代码书写。

qq_40311272的博客 2632

单片机编程框架

有利于建立裸机编程架构,梳理流程,分时轮询任务

Unraid小白必看:5分钟搞定OpenWrt软路由安装(附iStoreOS配置技巧)

本文为Unraid新手提供了一份详尽的OpenWrt软路由安装与配置指南。通过虚拟机技术,在Unraid系统上快速部署基于iStoreOS的软路由,详细讲解了旁路由与主路由两种模式的网络配置、性能优化技巧及常见故障排查方法,帮助用户充分利用闲置硬件,打造高性能、可定制的家庭网络中枢。

wine的专栏 485

掌上单片机实验室 – 构想(1)

一、背景 突如其来的疫情,打乱了大学生的正常学习氛围,传统的校园学习模式无法实施,虽说网上教学做了相应的弥补,但对于多数工科课程,只靠线上教学很难完成,单片机课程就是其中之一。 单片机这类工科课程有较强的实践需求,纸上谈兵很难达到预期的效果,所以开设这门课程的学校均建立有相应实验室。 而经典的实验室设备很难让学生个人拥有,在家独立完成实验,因为实验设备的设计及实验内容的编制均未考虑到这样的场景。 能否设计一款适合学生单独拥有,且可以自己完成实验的单片机学习实验装置呢? 本文尝试用我设计的第四.

embedream的专栏 395

TortoiseGit之配置密钥

基于github的开发必须要用到rsa密钥,因此需要用到TortoiseGit的putty key generator工具,来生成既适用于github的rsa密钥也适用于TortoiseGit的ppk密钥。

欧文的博客 2078

掌上单片机实验室 – 用PC作为UI (8)

前面构建掌上实验室程序框架时,提出了用串口作为单片机人机交互界面的概念,并在框架中将串口命令接收、串口数据发送作为基础功能编写完成。 程序框架具备了串口作为 UI 的能力,就需要有相应的外设与其配合,以实现所需的人机交互功能。前面提过,PC是可选的设备之一。本篇就以 PC 为载体,配合前述程序框架的串口收发功能,实现初步的人机交互,即:UI。

embedream的专栏 723

FPGA远程更新实战:Multiboot双镜像配置与Flash分区策略

本文详细介绍了FPGA远程更新中Multiboot双镜像的配置与实现,重点对比了XDC约束和ICAPE2原语两种配置方案的优缺点及适用场景。提供了基于W25Q128 Flash的非对称分区策略、MCS文件生成与烧写方法,并深入探讨了远程更新的流程容错处理与可靠性优化建议,帮助开发者构建稳定可靠的FPGA远程更新系统。

ss78901的博客 837

十一、Cadence ic 617以及assura使用总结

1.617的端口和514不同,没有网络属性,使用时不能直接放在原理图上,如果要直接放在图上要接线并且放上标签。2.617的端口也不能直接放在线上,514中将端口直接放在线上是可以使端口和线连接,但617看似连接,但拉出来线没有交点,实际上没有连接。这里set switches里的选项表示不同的模块,也就是选择一个就只对这一部分进行DRC验证,要验证整个版图的DRC就要把所有的选项选中,然后一个个改正。LVS中也是一样,要全部选中改正。

0 2295

掌上单片机实验室 – 尝试RT Thread(14)

前面介绍了掌上单片机实验室的构想,以及以 Arduino、Free RTOS为基础的学习过程,如果针对非计算机专业的学生而言,所述内容作为单片机或嵌入式的课程素材,应该够了,因为他们只有大约40~60学时,能把前述的学习内容消化实施,再在此基础上做些拓展,结合自己的兴趣,做些个性化的应用尝试,已经能初步掌握单片机的应用技能。RT-Thread是开源的,完全可以在实际应用中,遇到问题或想提高性能或代码效率时,用单步调试方式,跟踪到系统代码中,琢磨如何结合应用的需求去优化。期待国人自己的OS能做的更好。

embedream的专栏 284

Claude Code 源码一夜流出:会看热闹的人很多,会读源码的人很少

摘要:Claude Code源码意外泄露后,作者分享了高效的源码学习方法:1)Fork仓库保存代码;2)使用Qoder的Repo Wiki功能生成结构化文档和UML图;3)基于Wiki创建可复用的Skill。这种方法比直接让AI总结代码更系统深入,并推荐了可视化学习项目辅助理解。文章强调实践的重要性,提供了具体工具和操作指南。

719

掌上单片机实验室 – RT-Thread 应用程序框架(17)

通过跟踪调试,发现发送方式基本是阻塞完成的,故默认按阻塞逻辑处理,功能是实现了,后续再仔细分析一下。1)RT-Thread 创建线程多了一个参数:Slice,按说明是在轮流执行时,线程的执行时间,单位为 Tick,也就是说,RT-Thread 可以定义每个线程在轮流执行时的时间,而非每次Tick都转换线程。我觉得:就RT-Thread的学习而言,单个功能的示例官方已经提供,缺少的是结合实际需求(或接近实际的需求)的编程示例,比如说多文件的编程,因为随着代码增加,放在一个文件中会导致阅读费力,调试困难;

embedream的专栏 612

Calibre:LVS 快速debug short/open技巧

用Fix Suggestion和Short Isolate两种方法debug LVS问题

m0_61544122的博客 7456

嵌入式系统开发笔记112:通过有人云测试MQTT

项目中使用到“有人”公司的WH-LTE-7S0模块,本文讲解通过有人云进行MQTT测试的方法。

snmplink的博客 997

掌上单片机实验室 – 实现PID自整定(11)

上一篇实现了小车运动控制,在程序框架下,基于FreeRTOS编写了驱动任务,包含电机控制、测速、PID调速、行走距离控制等和运动相关的功能。但 PID 调速只是完成了算法,并未真正实现调速,因为 PID 调速的核心是PID 参数的确定,即整定!而整定是 PID 最富挑战的内容,调速效果的好坏完全取决于参数。 本篇目的是尝试使用 Arduino 分享的自整定库实现 PID 参数自整定。

embedream的专栏 6806

【异常】插入Milvus时出现无法插入的情况提示io.milvus.exception.ParamException: The field: meta is not provided.

在使用 Milvus 进行向量搜索时遇到 io.milvus.exception.ParamException: The field: meta is not provided 错误通常意味着在创建集合(Collection)或者插入数据(Insert)时,某些必需的元数据字段没有被正确提供。检查集合创建,确保在创建集合时,你已经定义了所有必需的字段,并且正确地使用了 SchemaField 来定义这些字段。例如,如果你在创建集合时没有正确设置元数据字段,就会出现这个错误。请严格按照这个表结构创建。

奶爸的编程之路,也就一周冷个三天 923

掌上单片机实验室 – 检验自整定适应性(12A)

在另一个不同的小车底盘上,验证 PID 参数自整定的适应性,从而确定 PID 自整定库是否实用。 检验的结果应该说相当满意!至少对于直流电机调速而言是可用的。

embedream的专栏 490

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

掌上单片机实验室 – 单片机课可以这样开(23)

提出一个单片机课程建议,将教学和实验融为一体,将用作为教学核心,通过实践掌握基本的单片机应用技能。

embedream的专栏 232

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

掌上单片机实验室 – RT-Thread 下实现PID自整定(20)

将基于 Arduino+FreeRTOS 实现的 PID 自整定功能移植到 RT-Thread 下,看看是否可行。实施结果:OK!基于 RT-Thread 完美实现了 PID 调速。顺带验证了基于 Serial V1 版本的发送阻塞验证,发送数据时并未阻塞,暂时可以不升级到 Serial V2.

embedream的专栏 1366

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

上一篇: 掌上单片机实验室 – 用PC作为UI (8)
下一篇: 掌上单片机实验室 - 实现运动功能(10)
嵌入之梦
博客等级 码龄21年 134粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值