电玩圈游戏网 搜一搜

安卓手游去频道 >

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

安卓应用去频道 >

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

游戏视频去频道 >

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

资讯攻略去频道 >

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

专题合集去频道 >

游戏专题 应用专题

排行榜单去频道 >

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

首页>资讯>游戏攻略>深圳SHENZHENIO第11关变色电子烟笔攻略

深圳SHENZHENIO第11关变色电子烟笔攻略

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

深圳IO是一款硬核的编程游戏,有着严谨的游戏内容,那么一起来看看第11关的变色电子烟笔的攻略吧。

主界面

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

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

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

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

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

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

第11关:变色电子烟笔

关卡展示

本关的 C2S-RF901 元件会不定期地发送一些长度为 4 的数据包,数据包里的前三个数表示一个颜色的 RGB 值(不过范围不是 0~255 而是 0~100),第四个数表示当前颜色的持续时长。如果在当前颜色的时间范围内收到了新的数据包,那么立刻停止计时,切换到新的颜色上。

我们很轻易地就能设计出这样的一个算法:

1,从 C2S-RF901 元件读入当前时钟周期内的首数字。

2,首数字不是 -999 时,说明要将变色笔置为新的颜色。将当前数据包里的前三个数分别传给右侧原件的 R、G、B 通道,然后将第四个数表示的持续时长传入芯片的 acc 寄存器。

3,判断剩余时间是否减到了 0。若未减到 0,则令 acc -1(剩余时间 -1)。若减到了 0,则将变色笔的颜色清除。

4,做完以上操作后,休眠一秒,进入下一个时钟周期。

由于变色笔由三个 p 口组成,且不是只有 0/100 两种数字,所以本例里我们无法使用 DX-300,我们只能这样做:其中一块芯片传输 R、B 两个颜色通道的值,对于剩下的 G 通道,我们将值通过 x 口传给另一块芯片,委托它用自己的 p 口把收到的数据传给 G 通道。

代码如下:

这里,我们接触到了一条新的指令:等待唤醒指令 slx。它的用法如下:

slx P,作用是令芯片在收到端口 P 的信号前一直保持睡眠。我在第 9 关的攻略里说过,芯片间使用 x 口传输数据时,必须在同一个时钟周期内,一方发送数据的同时,另一方接收等长的数据,通讯才能完成。一旦不满足以上任意一个条件(包括只发不收、只收不发、发送和接收的长度不一致),就会导致运行时阻塞。那么问题来了,接收方不知道自己什么时候会收到数据,不知道自己该等待到哪个时钟周期时接收怎么办?我又不能主动去读,读不到数据的话一样会阻塞。

slx 指令就是为了解决这样的问题而存在的。它的作用是,我来随时监视外面有没有数据进来,我叫你读你再读,我不叫你的时候你就给我老老实实等着。只要我叫你的时候你立刻读就一定没有问题(除非唤醒了以后又 slp 睡过去了,或者读的长度和发的长度不一致,那样的话仍然会阻塞)

那么,这道题里,左边的芯片不会每秒钟都告诉右边芯片,现在的 G 通道值是多少。只有当颜色改变的时候,才会通知右边的芯片改写掉 G 通道。因此,右边的芯片的确不知道自己该什么时候去读 x0 口的数据。所以右边的这块芯片里,我们需要在代码的开头加入一条 slx x0 指令,相当于为 x0 端口安排一个监控哨兵,告诉哨兵:“我现在睡了,啥时候 x0 口传过来数据了就叫醒我,这时候我读这个值肯定不会阻塞。然后,我把 G 通道改写成这个值以后就继续睡了,等有新数据了再重新叫醒我。”

右边的芯片虽然只有两条指令,但这两条指令里却有这么多的学问。

现在我们回过头来看左边的芯片。首先,我们之前提到过,x 口的数据只能读一次,不像 p 口那样可以在同一秒内反复读。那么,对于可能需要多次读取的数据,我们就必须先把读入的数据放到寄存器里暂存一下。像这道题里,首数字是 -999 则无视(只读一次),首数字大于 -999 则将首数字的值发给 R 通道(读了两次),首数字是存在读两次的可能性的,所以必须将首数字暂存到 dat 里,然后在 dat 上做文章,仅当 dat 大于 -999 时才将 dat 写到 R 通道里。而对于非首数字,因为只读一次就够了,所以就没必要暂存到寄存器里了,直接将 x0 的值传走就 OK。

然后我们来逐行分析左边芯片里的代码:

1: mov x0 dat # 将首数字存入 dat 备用

2: tcp dat -999 # 检查首数字是否大于 -999。首数字为 -999 时跳到第 7 行

3:+ mov dat p1 # 首数字不为 -999 时需要更换变色笔的颜色。将首数字发到 R 通道

4:+ mov x0 x3 # 将第二个数字发给右边的芯片,委托它把该值发送到 G 通道

5:+ mov x0 p0 # 将第三个数字发到 B 通道

6:+ mov x0 acc # 将第四个数字表示的持续时长存入 acc 寄存器

7: teq acc 0 # 检查当前颜色的剩余时长是否为 0

8:- sub 1 # 若不为 0,则令剩余时间 -1

9:+ mov 0 p1 # 若为 0,则将三个颜色通道全部置 0

a:+ mov 0 x3

b:+ mov 0 p0

c: slp 1 # 做完以上任务后,休眠一秒,进入下一个时钟周期

点击左下角的【模拟】,稍等片刻,便会弹出结算界面:

优化电量和代码行数

我们将“剩余时间不为 0 时令剩余时间 -1”的逻辑改为“首数字为 -999 时剩余时间 -1”,这样,当某一刻颜色清零时,倒计时仍然会继续进行下去变成负数,不会停在 0。之前的方案里,倒计时到达 0 时就不会继续计时了,这就导致长时间不来新的颜色信号时,teq acc 0 这条判断始终成立,就会导致“反复清零”的负面效果。经过以上改进后,倒计时只会在来颜色信号时重置为某个数,而永远不会停止,程序也只会在倒计时到达 0 的那一刻执行一次清零效果,而当倒计时到达负数时,不做任何操作。这样就节省了电量。

现在,我们将第 2 行的 tcp dat -999 改为 tcp dat -1,然后将第 8 行的 - sub 1 挪到第 2 行代码后面。代码变成了下面的样子:

而对于代码行数的优化,则需要用到我在第 10 关里提到过的一个技巧:【读一个只写 p 口时会读到恒 0 数据,同时之前写入该 p 口的数据也会被清零】。这一关里,因为左边 MC6000 的 p0 和 p1 口连接的是只写的 R、B 通道,所以

mov 0 p0

mov 0 p1

这两行代码可以合并为一行:

mov p0 p1

最终代码如下:

点击左下角的【模拟】,稍等片刻,便会弹出结算界面:

代码减少了一行,电量也由 507 骤降到 378。

第1关:安全摄像头

第2关:信号放大器

第3关:脉冲发生器

第4关:动画 ESPORTS 标志

第5关:游戏积分器

第6关:调谐最优化引擎

第7关:被动红外感应器

第8关:仿真蜂鸣器

第9关:无线游戏控制器

第10关;真人cs

评论 (0)

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

上拉或点击查看更多