电玩圈游戏网 搜一搜

安卓手游去频道 >

角色扮演 射击枪战 棋牌卡牌 体育运动 角色扮演 赛车竞速 休闲益智 音乐舞蹈 模拟经营 战棋塔防 推理解谜 策略战争

安卓应用去频道 >

社交通讯 系统工具 影音视听 拍摄美化 效率办公 学习教育 生活服务 旅游出行 资讯阅读 金融理财 网络购物 游戏助手

游戏视频去频道 >

动作冒险 射击枪战 棋牌卡牌 体育运动 角色扮演 赛车竞速 音乐舞蹈 模拟经营 战棋塔防 推理解谜 策略战争 休闲益智

资讯攻略去频道 >

手游资讯 手游攻略 手游问答 游戏资讯 游戏杂谈 游戏攻略 软件教程 软件资讯

专题合集去频道 >

游戏专题 应用专题

排行榜单去频道 >

游戏排行 应用排行
首页 游戏 应用 视频 资讯 专题 榜单

首页>资讯>游戏攻略>深圳SHENZHENIO阿瓦隆城第1关冷库机器人攻略

深圳SHENZHENIO阿瓦隆城第1关冷库机器人攻略

作者:佚名来源:百度2022/06/16

深圳IO是一款硬核的编程游戏,有着严谨的游戏内容,那么一起来看看阿瓦隆城第1关冷库机器人的攻略吧。

主界面

由于游戏过分硬核,先放个手册中的图看看冰山一角:

不过这也正对应了嵌入式开发中会遇到的海量数据手册,相当程度上还原了嵌入式日常开发的情景。

游戏中设计到部分的编程有些类似于汇编语言,这里上手还是有一些些难度的,大家请做好准备,继续直接扔核弹:

不用害怕,在游戏过程中,会逐步引导你学会使用新的指令,对于新的器件,也是随着主线的进行逐步开放的

在游戏中,你不仅可以完成指定的基本目标,还可以挑战全网玩家,看谁能达成最佳优化目标。

鱼和熊掌不可兼得,多数情况下想要达成更好的性能就要增加成本啦,不过这正是优秀的嵌入式开发人员的意义所在——比你好,还比你的便宜。

阿瓦隆城第1关:冷库机器人

关卡展示

欢迎进入地狱模式。当你开启了阿瓦隆城的大门后,相信你对深圳 IO 这款“单片机模拟器”已经有了较为深入的了解。

本关要求你控制一个电机,随时将新的食物放入冷库,或者将已经在冷库中的食物拿出。C2S-RF901 会不定期地发送一些长度为 2 的数据包。当你收到以 1 开头的数据包时,控制电机将对应编号的食物放入冷库;当你收到以 2 开头的数据包时,控制电机将冷库中对应编号的食物取出。

电机的控制规则如下:

①【伸出】信号为 0 表示电机的爪子处于收缩状态,100 表示电机的爪子处于伸出状态。

②【抓握】信号为 0 表示电机的爪子处于放开状态,100 表示电机的爪子处于抓握状态。

③【电机】信号用于控制电机的水平移动。平时是 50 信号,给电机发送 a 秒的 0 信号可令电机左移 a 格,给电机发送 b 秒的 100 信号可令电机右移 b 格。移动完毕后需要将电机信号还原成 50。

④电机初始在第 0 格,新食物也总会在第 0 格出现。当你收到 1 开头的数据包时,需要将新食物放入冷库。首先令电机【伸出】1 秒,然后让电机【抓握】住食物,并【向右移动】,找到冷库中的第一个空位后,令电机【伸出】1 秒,把爪子【放开】,将食物送入冷库。最后,令电机【向左移动】回到原点待命。

⑤当你收到 2 开头的数据包时,令电机【向右移动】,找到对应的食物后,令电机【伸出】1 秒,然后让电机【抓握】住食物,并【向左移动】到原点,将食物运送到出口。到达原点后,令电机【伸出】1 秒,把爪子【放开】,释放食物。

这个题目要实现的程序逻辑相当复杂,至少需要 4 块芯片分工合作。

第一块芯片是总监,用于监测数据包,然后给其余芯片发送调度指令;

第二块芯片是一个数据库管理员,它的工作是不停地修改冷库中的食物存放状态。当它收到第一块芯片发来的调度任务后,根据任务的种类执行不同的操作:当收到了【存】任务时,在 RAM 中寻找第一个空位,并将对应的空位置为新的食物编号;当收到了【取】任务时,在 RAM 中寻找存着对应食物的位置,并将对应位置重置为空。做完这些后,把要到达的目标位置发送给后面的芯片,由后面的芯片来控制电机的移动,它自己不负责这些工作;

第三块芯片在收到第二块芯片告知的目标位置时,控制电机的移动;

第四块芯片用于控制电机的伸缩和抓握。这两块芯片是勤劳的工人。

电路图和代码如下:

上方居中的芯片是和不断提供数据包的 C2S-RF901 直接连接的芯片,它是任务的调度者,也就是我们所说的第一块芯片。我们先来分析它的代码:

C2S-RF901 的首数字有三种可能性:-999、1、2。因此首先肯定是一个三态判定(tcp x1 1)。当首数字是 -999 时,什么事都不用做,直接跳到最后睡觉(- jmp 9)。当首数字是 1 或 2 时,说明收到了新任务,我们首先要给 p0 口设置状态值,0 为存,100 为取;其次要给左边的芯片发两个数字,第一个数字是“要找的食物的编号是多少”,第二个数字是“要将对应位置的编号置为多少”。我们依次来分析。

首数字是 2 时,说明收到的是【取】任务,我们首先要将 p0 口的值置为 100 供下方芯片使用(+ mov 100 p0),然后我们需要找的食物编号是和数据包的第二个数字一致的,所以我们往左边芯片发送的第一个数字即为该数字(+ mov x1 x0)。找到对应的食物后,需要将对应的格子清零,所以我们往左边芯片发送的第二个数字为 0(+ mov 0 x0, + jmp 9)。

首数字是 1 时,说明收到的是【存】任务,我们首先要将 p0 口的值置为 0 供下方使用(mov 0 p0),同时我们要找的食物编号也为 0(寻找冷库中的第一个空位),往左边芯片发送的第一个数字是 0(mov 0 x0)。这里就可以用我们之前提到的“多处清零”技巧,将 mov 0 p0 和 mov 0 x0 两条指令合并成一条(mov p0 x0)。找到空位后,我们将对应的格子置为新的食物编号,所以往左边芯片发送的第二个数字为数据包里的第二个数字(mov x1 x0)。做完以上操作后,休眠一秒,进入下一个时钟周期(slp 1)。

当你读只写的 p0 时,会读到 0,同时之前写入 p0 口的数据也会被清除。与此同时,你将读到的 0 赋给 acc,这样就成功用一条指令将两处存储置零了(节省了电量,甚至还可能因此省下关键的一行代码,正好够放在一块 4000 或 6000 里)。

这是我从第 10 关开始提的,后续也反复提到的“多处清零,一举两得”的技巧。但是,曾经使用这样的技巧只是为了省电和省行数。而在这一关里,我们使用了该技巧,将原先的 10 行代码压缩到了 9 行,使得代码正好能够装在一块 MC4000 里,连成本也省了下来,属于是这条技巧的高光时刻了。

我们为什么要将存/取的状态值存入 p0 口呢?我们观察电路图可以发现,第一块芯片的 p0 口是和其正下方芯片的 p0 口相接的,后面我们会说到,正下方的这块芯片是用于控制电机移动的“第三块芯片”。观察时序图我们发现,【存】任务里我们需要“先抓取食物,再移动电机”;【取】任务里我们需要“先移动电机,再抓取食物”。为了确保电机的正常工作,这一块芯片有必要知道当前的任务类型是什么。所以我们需要将存/取状态值提前放入 p0 口。

第一块芯片将调度指令发给第二块芯片,将任务类型通过 p0 口告知第三块芯片后,它的任务就完成了。接下来我们看位于左上方的第二块芯片——数据库管理员——的代码:

虽然只有 9 行代码,但因为用到了 dat 寄存器,所以用 MC6000 不亏。去掉 dat 的难度比去掉一行代码的难度大多了,甚至很多情况下根本不可能。

首先这块芯片需要等待其右侧的调度芯片发送调度任务(slx x3)。收到调度任务后,我们将发来的第一个“要找的食物”的数字暂存到 dat 中(mov x3 dat),然后开始遍历 RAM,寻找值为 dat 的格子(mov x1 acc, teq x0 dat, - jmp 3)。找到后,acc 存储的是对应格子的地址,我们将指针定位到该地址(mov acc x1),然后接收调度芯片发来的第二个数字,将对应位置处的数字改写成收到的新数字(mov x3 x0)。

由于 RAM 中的地址是以 0 起始的,而冷库中的位置编号是以 1 起始的,所以冷库地址 = RAM 地址 +1。而恰好,我们在读/写 RAM 后,地址会自增 1。因此我们可以直接将自增后的 RAM 地址作为“冷库目标地址”,发给右边的第三块芯片,让第三块芯片开始控制电机(mov x1 x2)。操作完毕后,我们将 RAM 地址归零,等待下一次调度(mov 0 x1)。

做完这些工作后,第二块芯片的任务也结束了。接下来我们看第三块和第四块芯片——勤劳的工人们——的代码:

先看左边的,控制电机移动的芯片。首先,我们需要将电机的初始电平信号置为 50(mov 50 p1)。设置完毕后,等待数据库管理员发送目标位置信号(slx x0)。收到位置信号后,我们将位置值暂存到 acc 中(mov x0 acc)。这时候,我们需要判定调度芯片告知我们的任务种类是什么(tcp p0 50)。

如果任务类型是【存】

也就是 p0 的值为 0,那激活的是 - 号指令。我们需要先在 0 位置完成伸出、抓握的动作后再向右移动,此时需要直接通知右边的芯片开始伸出、抓握。同时因为电机移动的过程中,电机要保持抓握状态不能松开,所以我们需要将移动时长(也就是目标位置)发送给右边的芯片,让右边的芯片“保持抓握”这么长时间后再松开(- mov acc x3)。初始的伸出、抓握动作需要耗费两秒钟(- slp 2),两秒钟过后,我们令电机持续右移 acc 秒(mov 100 p1, slp acc)。到达目标位置后,将电机的电平信号还原成 50(mov 50 p1)并休眠两秒(slp 2),等待右边的芯片完成伸出、放手动作后,我们再令电机持续左移 acc 秒回到原点(mov 0 p1, slp acc)。做完这些后,回到第一行,将电机的电平信号还原成 50(mov 50 p1)后就完成了任务,耐心等待下一次任务调度即可(slx x0)。

如果任务类型是【取】

也就是 p0 的值为 100,那激活的是 + 号指令。我们需要先向右移动到目标位置后(mov 100 p1, slp acc)后再通知右边的芯片伸出、抓握(+ mov acc x3)。接下来的动作和上面完全一样,耗费两秒钟等待伸出、抓握的动作完成(mov 50 p1, slp 2),向左移动 acc 秒回到原点(mov 0 p1, slp acc),完成任务等待下一次调度(mov 50 p1, slx x0)。

再看最右边的控制伸出、抓握的芯片。收到左边芯片的信号后(slx x0),将“保持抓握”的时长存入 acc(mov x0 acc),然后令爪子伸出 1 秒(gen p1 1 0),抓握 1 秒(mov 100 p0, slp 1)后,电机会(存时向右,取时向左)移动 acc 秒,在此期间电机要保持抓握的姿势不变(slp acc)。到达目的地后,令爪子伸出 1 秒(mov 100 p1, slp 1)后放手(mov p0 p1,将伸出和抓握信号同时清除)。至此,本次的抓、放任务就完成了。

这是一个“大家分工合作,一起共同创造美好生活”的典型案例。

点击左下角的【模拟】,运行程序。

注意观察屏幕右下角的动图,看清楚电机的工作过程。稍等片刻,便会弹出结算界面:

评论 (0)

相关阅读
网友评论0条评论

上拉或点击查看更多