TI教室 >
应用与设计 >
工业应用 >
工厂自动化与控制系统 >
Logistics Robots >
TI-RSLK 模块 4 - 使用 MSP432 进行软件设计 > TI-RSLK 模块 4 - 讲座视频 - 设计
- 本课程为精品课,您可以登录eeworld继续观看:
- TI-RSLK 模块 4 - 讲座视频 - 设计
- 登录
- 课程目录
- 相关资源
- 课程笔记
大家好,
我是 John Valvano。
在本模块中,我们将讨论软件设计。
我们首先介绍一下模块化设计这个概念。
模块是什么,它是系统的一个子集,
它同时包含软件和硬件,而且具有完整的任务。
所以我们会将它视为一个完整的任务。
当我们把这些模块放在一起时,
我们可以从不同的角度来看待它们。
其中一个角度叫做调用图。
这意味着,如果SwitchMain 中的软件
可以调用针对不同模块的 switch 中的函数,
我们将会绘制这样一个调用图箭头。
这个箭头表示,这将是高级别,
这将是低级别。
类似地,如果SwitchMain 中的软件
可以调用 LaunchPad 中的软件,我们将会
绘制一个调用图箭头,来表示
高级别函数与低级别函数之间的
因果关系--层次结构关系。
而且,我们会将与一个事件相关的
所有任务--
例如,与开关相关的所有函数,
以及与 LaunchPad相关的所有函数--
封装在独立的模块中。
我们将要解决的问题
并不复杂,我们将在一个输入上
配备一个开关。
如果按下开关,
则会将发光二极管切换到另外一种
状态。
另一种在互连情况下看待这些模块的方法
称为数据流图。
数据流图显示了连接情况。
这是一个硬件模块。
这里的所有其他模块都是软件模块。
关于开关是否关闭的布尔信息
被编码在数据流图的箭头中。
所以,数据是向这个方向流动的。
即使是 SwitchMain调用 switch,
数据实际上也是在向另一个方向流动。
而在这里,数据则是从 main 向 LaunchPad 流动,
因为我想要开关 LED。
然后,在物理层面上,我在数据流图中包含了
可以发光的 LED。
而且,通过这个数据流图,
我们可以定义模块化意味着什么。
系统的模块化,如果您愿意,
这也是系统的精华所在--
是多个模块的函数。
因此,我们希望最大限度地增加模块数量,
同时尽量减少它们之间的互连。
特别是,我们可以查看带宽之类的
东西,它是每秒跨屏障传输的
字节数。
因此,我们希望最大限度地增加模块数量,
同时尽量减少它们之间的互连。
针对互联的一个简单的定量测量方式是,
测量每秒从一个模块流到另一个模块的
字节数。
这便是我们将会在这里采用的理念。
那么,让我们开始吧。
当我们讨论如何制造一些复杂的东西--
换句话说,模块化系统的
整体思路就是能够提高复杂性。
可让我们做到这一点的一种方法是使用多个线程。
线程是由正在执行的软件引起的操作。
所以,引发线程的是软件的行为。
我们将会得到一个多线程环境,
其中有一个主程序。
而且,我们将会有多个中断。
例如,我可能会有硬件触发的中断。
当我触摸开关时,将会触发一个中断。
我们将会在多个模块中介绍这种中断的
实际工作方式。
但是在这里,我们只需要了解一点就足够了,
那就是,当您触摸开关时,系统会
运行与这个触摸操作相关的软件。
然后,如果我们想要周期性地执行
某个操作,我们将需要另外一种中断。
我们将会使用一个频率为,比如说 100 赫兹的计时器中断。
而且,我们将从这个层面上执行软件。
我在这里绘制一个主程序。
然后绘制初始化。
然后,我们在这里绘制一些东西。
然后就有了一个循环。
我们之所以将其称为线程,
是因为我们可以将正在执行的软件想象成
一条单一的轨迹。
即使这是一个函数--
即使这个初始化是一个函数,
我们仍然可以绘制一条--
我们可以
一笔画出一条代表其执行顺序的直线。
这便是我们将其称为线程的原因。
一系列指令,由这些指令
引起的操作,这便是线程。
但是中断是特殊的。
中断是硬件触发的软件
操作。
在这里,我们将打断这个线程,
从这里开始,因为我们触摸了开关,
执行该软件,然后再次打断该线程,
然后重新返回这里。
所以线程是由正在执行的软件引起的
操作。
在本课程中,我们将使用一个
单一的前台线程、一个主程序,以及多个
在特定事件时执行的中断线程。
这是增加系统复杂性的一种方法。
您要做的最困难的事情之一是,
确定从哪里开始。
我要告诉您一个很不幸的消息。
您可能也在其他地方听到过这个
说法--
需要花费 1 万小时的时间,
才能熟练掌握一个技能。
我并不是要打击您。
如果您坐在电脑前,
编写尽可能优秀的代码,在大约一个小时的时间里,
您可能能够写出 100 行代码。
如果您将这两个数字相乘,
达到一百万行代码的分界线后,
您将会成为一名优秀的软件设计师。
说这些也不是为了打击您。
我的意思是,行动起来。
说这些是为了鼓励您马上加入进来并编写许多
许多的代码。
这张幻灯片讨论的是,在开始写代码之前,
如何完成软件构想。
这涉及到了状态这个概念。
我将状态定义为:您知道什么?
如果您有一个系统,您可能知道什么?
或者有时候是,您认为自己知道什么,
或者您认为什么是真实的,这便是状态。
例如,我可能在这条路上有一个机器人。
我的机器人在这里。
我觉得它在沿着这条路移动的过程中离右侧
墙壁太近了。
离右侧墙壁太近--
这便是我认为真实的事情。
您现在要做的是
考虑这个问题,
并写下您的系统可能处于的
所有状态。
我在一个小圈子里。
我处于停滞状态。
我撞到墙上了。
我走错方向了。
我赢了比赛。
我到达了终点。
所以,我将会考虑所有的状态。
有些状态是相互排斥的,
有些则不是。
例如,您可能会有一个绿色 LED
闪烁的状态。
这个状态可能会与机器人离墙太近的状态并存。
所以,状态之间不一定是相互排斥的。
但是,您需要将它们都写下来,
考虑哪些事情是您的系统需要知道或
认为是真实的。
这样做后,您可以问自己以下几个问题。
我们从哪里开始?
初始状态是什么?
或者是下面的这个也比较简单的问题--
我需要知道什么?
我要得到什么信息,才能认为
我离墙壁太近?
在这种情况下,我可以写下所有的传感器--
输入传感器。
然后它不单单是一个数据收集器,
更是一个嵌入式系统。
所以它有输出。
我该怎么做?
我会采取哪些操作?
我想移动。
我想转弯。
我想停下来--
诸如此类。
我将会使用哪些操作,为了执行
这些操作,我需要生成什么输出?
我们将会看到,我们有两个电机。
我们将必须单独驱动每个电机。
然后更难的是,如何从一个状态转变到另一个
状态?
换句话说,如果我离右侧墙壁太近,
我想要移到中间位置,我怎样才能从一个不佳的位置
移动到理想位置?
然后,很明显,我们想知道,
我们如何在完成后获知已经完成?
所以,这种状态本质上是一种
在实际坐下来开始写代码前,
构想您的软件和硬件系统的方法。
另一种思考问题的方法是
将其分解成模块。
下面我们将介绍这种方法。
用于讨论将系统分解成
模块化部分的术语共有三个。
它们具有大致相同的含义。
逐次求精、逐步求精
和系统分解--在这个背景下,
它们都指的是相同的事情。
那就是,我们将会从任务开始。
让我们进行赛跑。
我想要在跑道上尽可能快地奔跑。
但这太复杂了,我不知道究竟该怎么办。
因此,求精的整体思路就是将其分解成
多个片段。
比如,我可能想要移动。
我可能想要进行感测。
我可能想要进行思考。
然后对于上面的每个任务,我想要
将其分解为更小的部分,因为这会涉及到
我如何在完成后获知已经完成。
所以,如果我把一个任务分解成一个子任务,
然后子任务非常简单,
我知道该如何完成--然后我将会完成该子任务。
我将会实施该子任务,并进行测试和记录。
然后,我可以将其重新组装回去。
但如果它仍然太复杂,
我将再次进行分解。
所以我们可以讨论诸如停止、直行和转弯之类的任务。
我可以分解模块。
我可以将其分解成子模块。
如果它们太复杂,
我将再次进行分解。
例如,对于线路传感器--
这是我可能会用到的传感器之一。
如果我不知道如何实施线路传感器,
我将会将其分解成多个部分,比如,实施输出,
等待一毫秒,
实施输入,然后进行思考。
现在我将这个线路传感器
分解成了多个子模块,简化到了我能够完成的程度。
然后,我将会实施这四个步骤,
然后将其重组回去。
需要注意的是,有时您遇到一个问题--
这是一个问题--
我将其分成两部分--
A1 和 A2。
然后我向前走,哒哒,我走对了。
但是还有一种可能,在您将 A 分成两部分后,
这部分,A1,可能实际上比原来的部分更难了。
因此,将一个对象分成两半,并不代表
它就会变简单。
这整整 1 万小时,或者说一百万行的代码
真的能让您擅长回答,如何才能
更有效且更高效的完成这项工作?
但是现在,我想让您考虑这个问题,
如果在将问题分解后,它变得比开始时
更复杂了,我将会将其重组回去,
并使用另外一些方式对其进行分解,
我将会持续尝试不同的分解方法,
直到子部分比初始任务更简单为止。
然后,我们会将这些子部分全部都重组回去。
我们知道,不管是对于数据流图,
还是调用图--这是一个数据流图,
我们知道,我们的工作是将其分解为
不同的部分,从而得到尽可能多的模块。
但是,我们会有较小的带宽。
也就是说,模块之间的
信息传输速率应尽可能低。
最终,与这个性质类似的是,
接口将会变得至关重要。
对于数据流图,是由这个接口
来传递数据。
对于调用图,模块 A调用模块 B。
同样,这个接口将会非常重要。
所以,当我将某个东西分解成子模块时,
这些模块如何重新连接对于确保系统的
有效性和高效性至关重要。
因此,让我们找出一种定义接口的方法。
如果该接口
非常重要,我们将会
收集有关该接口的所有信息,
并将其存储在一处。
这便是我们的头文件。
同样,系统的模块化性质--
该模块的开关--将具有两个文件--
一个是 switch.c,包含实施信息,
另一个是 switch.h,包含公有函数的
原型。
也就是说,该文件包含接口。
它包含一个可以在该模块中
调用的函数的列表。
这样,我们就可以将该模块的功能分离出来。
比如,这是一个简单的模块,您可以
从开关进行输入。
您可以将其打开,然后您可以输入。
您将把这一点与它实际的工作方式分离。
它连接到什么端口,电压是什么,
它是正逻辑还是负逻辑--
所有这些低层次细节都将被分离出来。
这种分离将会对降低系统的
复杂性大有帮助。
这便是我们在这里提到的
复杂性抽象。
换句话说,我们将分离并隐藏
所有的低层次细节,并暴露给其他模块
一个可用于使用该模块的简单接口。
同样,包含在头文件中的是
公有函数的原型以及关于头文件--
也就是该模块的功能和使用方式的注释。
未包含在该模块中的是该模块的工作方式。
模块内容的细节不包含在这里。
我们不会将任何变量放在头文件中。
这种私有概念全部属于内部运作。
注意这个头文件--实际上,
本课程中的所有头文件--
都使用了这种奇异的语法,其中这是参数,
这是返回参数,
这是有关其功能的简短解释。
这种语法实际上叫做 doxygen。
doxygen 最厉害的地方就在于,它会自动
为整个机器人系统生成用户手册--
一种软件文档。
您将会看到,大多数这种文档
都代表了您需要在本课程中编写的函数。
我们将会为您提供几个函数,
来支持您开始编写自己的函数。
所以这个 doxygen 流程可帮助我们
创建一个美观的 HTML 页面,用来介绍
软件的所有功能--
也就是说,介绍它的功能,
而不介绍它的实际工作方式。
一个模块具有一个 .c 文件和一个 .h 文件。
我们说过,.h 文件中包含的是
公有函数的原型。
代码文件中包含的是实际的实施。
我们将会在下面的模块中讨论端口的
实际工作方式。
但是在这里,我们只需要知道 c 文件中包含的是
实际的工作方式,实际的实施是在
这里。
我们需要变量。
它在 c 文件中。
如果我们有任何特殊私有函数,
它也会在 c 文件中。
c 文件中的注释会介绍该函数的工作方式,
它是如何进行测试的,或者您可以如何更改该函数。
一定要非常谨慎地对待其他模块的
私有性质。
不要尝试访问其他模块的
私有信息或私有函数。
如果您在 Code ComposerStudio 中查看该项目,
您将会看到与该项目关联的所有文件。
但是如果您查看文件中的内容--
例如,这里的这个文件,它是一个高级文件。
这段代码便是在该文件中。
最终,这里的这些 include 文件
实际上等效于或者将为您绘制
调用图。
如果这个函数包含那个函数的头文件,
那么我们便可以调用它的公有函数。
由于这里的这个 main c文件包含 LaunchPad.h,
所以它可以调用后者的公有函数。
所以这个 include文件是这个箭头。
这里的这个 include 文件--
这是这个箭头。
所以这种将某个事物分解成模块的做法
对于简化非常复杂的系统大有帮助。
所以,当我们组建成我们的机器人时,
您会发现它包含数十个模块,所有模块均融入到
这个层次结构中。
最后总结一下,我们定义了模块化,
这是一个增加
模块总数的过程。
但是我们希望最大限度地减小带宽,互联,
每秒在不同模块之间
传输的字节数。
我们讨论了头文件。
头文件中包含的是接口--
数据的流动方式,或者调用函数的
方式。
通过这种方式,我们可以分离其功能--
高级交互--
分离其功能和工作方式。
这样,我们将能够打造一个非常复杂的系统。
所以随着向后面的部分推进,我们需要考虑该模型。
在本课程开始时,可能会很简单,
这时您实际上还不需要使用模块。
但是,当后面变得越来越复杂,
您将会看到使用模块化设计的好处。
好的。
在下一个模块中--
下一个讲座中,我们将讨论一些 C 语法,
然后,我们将讨论一些调试方法。
好的。
稍后回来。
课程介绍
共计5课时,1小时11分51秒
猜你喜欢
换一换
推荐帖子
- while ((IFG1 & UTXIFG0)==0); 停止怎么解决?
- 初始化函数: void S_Init() { P6SEL&=~(SCK+SDA+SVCC); //选择P6.3 P6.4 为IO端口输出, P6.5输入 P6DIR|=(SCK+SVCC); P6DIR&=~SDA; BCSCTL1...
- BADBOSS 微控制器 MCU
- TMS320C6678 ZYNQ OpenAMP 双核ARM 通信案例开发手册之echo_test案例
- 目录 前 言 1 echo_test案例 1 案例功能 2 操作说明 3 关键代码 3.1 linux_demo代码说明 3.2 freertos_demo代码说明 3.3 baremetal_demo代码说明 前 言 本文主要介绍ZYNQ基于OpenAMP框架的双核ARM通信案例的使用说明,CPU0(Master)运行Linux系统...
- 别打牛牛 DSP 与 ARM 处理器
- 开关电源变压器的检测方法
- 1、通过观察变压器的外貌来检查其是否有明显异常现象。如线圈引线是否断裂,脱焊,绝缘材料是否有烧焦痕迹,铁心紧固螺杆是否有松动,硅钢片有无锈蚀,绕组线圈是否有外露等。 2、绝缘性测试。用万用表R×10k挡分别测量铁心与初级,初级与各次级、铁心与各次级、静电屏蔽层与衩次级、次级各绕组间的电阻值,万用表指针均应指在无穷大位置不动。否则,说明变压器绝缘性能不良。 3、线圈通断的检测。将万用表置...
- qwqwqw2088 模拟与混合信号
- MSP430ADC采集的滤波算法怎么实现
- 我在用MSP430F169做一个ADC采集,读取的数据有一点波动,想用多次测量取平均值来实现,但是不知道怎么实现?求指教...
- Rephontil 微控制器 MCU
推荐文章
- 德州仪器推出新款实时微控制器系统 可在汽车与工业应用中实现更智能的处理流程 2024年11月15日
- 据外媒报道,当地时间11月11日,德州仪器(Texas Instruments,TI)宣布推出两款全新的实时微控制器系列——TMS320F28P55x系列和F29H85x系列,旨在帮助工程师在汽车和工业应用中,实现更智能、更安全的处理流程。TI的TMS320F28P55x系列MCU是业内首款集成了神经处理单元(NPU)的实时微控制器,可实现高精度、低延迟的故检测功能。F29H...
- MCU今年的重点:NPU和64位 2024年11月13日
- 今年非常流行一句话,叫做“无AI,不终端”。在MCU领域,也正在进行着边缘AI和TinyML的革命。 对于MCU来说,跑AI也是非常重点的应用之一。前两天,就连实时控制派系的MCU TI C2000都开始搭载NPU和64位化。可见,MCU正在加速向AI进化。 带NPU的C2000:能干什么 TI在最近推出的两款MCU,第一款是业界首款具有集成神经处理单元(NPU)...
- 实时控制技术如何实现可靠且可扩展的高压设计 2024年11月04日
- 随着功率水平需求的提升和现代电源系统的日趋复杂,对高压系统的需求也发生了重大变化。为了有效满足这些需求,有必要采用实时 MCU 或数字电源控制器来控制先进的电源拓扑,通过这些出色的拓扑来同时满足精细的规格和各种电源要求。本文将讨论数字电源控制在高压应用中的一些优势,并演示其如何助力先进电源系统的安全高效运行。 提高系统可靠性并保护电力电子设备 可靠性对于确保高压系...
- PLD入门其实不难!TI带你解锁无代码逻辑设计新体验 2024年10月29日
- 随着电子产品小型化和功能集成度的不断提升,传统分立逻辑器件的局限性日益显现。德州仪器(TI)于近日发布了全新的可编程逻辑器件(TPLD)系列产品,旨在通过创新的低门槛、高集成度方案,为设计工程师提供更加高效、灵活、简单的逻辑器件和设计工具。 为什么TI选择进入PLD市场? 当我们片面的认为PLD市场是由Intel(Altera),AMD(Xilinx),Lattic...