本帖最后由 x789o 于 2023-5-13 23:05 编辑
因为天问STC15系统库未提供需要的选项和更丰富的功能,第三方库占用FLASH空间较大,需要自行用C语言实现。将其进一步封装成“图形编程”所用的库,对促进分享和社区的发展都是有利的。坛中已有高人记载了图形界面的主要操作流程,但对“预处理”、“执行等代码生成的解释尚不详细。因此,我在摸索出扩展库创建流程的同时,也在此简要记录扩展库开发的常用代码,希望对同有需要的朋友带来帮助。 一、新建库 点击“天问Block”软件左下角的“添加扩展”,点击顶部最后一个按钮“新建库”,即可打开库编辑窗口。在这里,“图形编程”所用的一个个图形积木块被称为一个个“模块”。通过“删除”按钮可以删除一个模块。目前没有一键清空功能,如果后续需要开发多个扩展库,可以点击“生成库”按钮保存一个干净的自定义库作为模板。 当前的“生成库”按钮中的配置会在下次打开库编辑窗口时丢失,因此每隔一段时间应重新点击“生成库”按钮导出一次,后续可通过“导入库”-“导入本地库”恢复,以防写好的库名称和说明丢失。在生成库的窗口中,还需要点击“XML文件编辑”旁边的“编辑”按钮,点击“导入编辑区代码”,以确保模块内容被正常配置。点击“天问Block”软件左下角的“添加扩展”,点击顶部“用户库”按钮,再点击“本地导入”,即可导入生成的库进行测试。目前暂未发现更简单的同步调试方案,而且自定义扩展库总是在下方,希望后续这些问题能得到改善。 每拼上一个模块,天问Block就会在必要的位置生成对应的代码。自定义扩展库是配置每个模块的过程。相比于每个模块本身的显示方式,每个模块的输入参数、“在哪里生成什么代码”更加重要。接下来将介绍这些内容。 二、模块输入参数 模块输入是在图形编程时可指定的内容,这些内容通常会影响生成的代码。 1、“输入” “输入”定义了在模块右侧能够嵌合的图形模块的类型和数量,共有三种形式。“假输入”没有任何可以接收模块的凹槽,只能在模块本身上填写内容。“值输入”在右侧定义一个小凹槽,可以接收一个值,每添加一个“值输入”,小凹槽增加一个。“语句输入”在右侧定义一个大凹槽,可以接收多条语句,通常用于定义函数体。 “输入”下方还定义有两种连接方式,尝试一下即可明白。 2、“领域” “领域”是嵌入在模块“输入”中可修改的内容。 3、“输入”和“领域”对应的变量 “输入”和“领域”部分的每个可配置内容都对应了一个变量,以便在下方的代码生成中使用。其中: “值输入”对应的变量名为“value_名称”,“语句输入”对应的变量名为“statements_名称”; “领域”中,文本、数字、角度、下拉、选项、颜色、变量对应的变量名分别为“text_名称”、“number_名称”、“angle_名称”、“dropdown_名称”、“checkbox_名称”、“colour_名称”、“variable_名称”。 这里的“名称”在库编辑窗口提示为“套接字”,我觉得使用“名称”更加直观。所有名称都是小写的。 三、生成代码 “生成代码”是模块对应C代码的生成器,用JavaScript实现,在库编辑窗口的右下角可以查看。可以利用高级编程方法计算需要配置的数值,如使用“整数变量.toString()”、“小数变量.toFixed(小数点位数)”将数字转换为字符串进行拼接。 即使一个文件中的函数不全被使用,SDCC编译器不能像GCC那样自动剔除未用到的部分。如果一股脑儿导入全部库代码,所有函数都会得到保留,就会使得编译后的体积增大。因此,对于小容量的单片机,生成的代码应根据模块的输入参数自动配置,有效利用图形编程模式自动维护字符模式代码的不同部分,而不需要在运行阶段动态判断。通常直接套入文本代码无法达成此目的,而需要通过库编辑窗口的两种“自定义代码”实现。 1、预处理代码 “预处理代码”共有5类,格式分别如下: 宏定义:Blockly.Arduino.definitions_['define_宏名'] = '#define 宏名 宏体' 头文件:Blockly.Arduino.definitions_['include_头文件名'] = '#include "myLib/xxx.h"' 变量定义:Blockly.Arduino.definitions_['var_declare_变量定义语句'] = '变量类型 变量名;' 类定义:Blockly.Arduino.definitions_['var_declare_类定义语句'] = '类名 实例名(类参数);' 初始化(setup函数中添加的内容):Blockly.Arduino.setups_['初始化名称_init'] = '初始化语句;' 因此,实际上的预处理代码只有2类,并且模块的共同内容(由字典的键决定)在字符模式中只会被生成一遍。通过“自定义行”,可以将字符串与“输入”和“领域”对应的变量拼接,动态生成代码。如果减小体积是很重要的目的,可以根据将用到的功能函数的具体实现作为预处理代码行,而无需包含C文件,甚至头文件。 2、执行代码 若执行代码不为空,则执行代码会被放置到如下代码段中: - var code = 内容;
- return code;
复制代码其中,“内容”是手动设置的“自定义代码”框中的内容,或者其他字符串拼接的框中的内容。最后得到的类型需要是字符串类型。如果内容具有多行,可以使用``括起来形成模板字符串,实现自由换行。当然也可以使用'内容1\n内容2\n内容3'的形式,或['内容1','内容2','内容3'].join('\n')的形式。 四、总结 根据以上记录,可以将写好的C库包装为图形模块。 以上记录仅供参考,若有不到之处,还请包涵。
|