【说在前面的话】
接下来,让我们先预览微信小程序中将要实现的两个界面。如下图所示,
功能介绍到此为止,现在,我们将开始着手编写微信小程序的代码。
【编写前的准备】
首先,要在电脑上安装微信开发者工具,如下图
接着,打开下面的网站
https://developers.weixin.qq.com/miniprogram/dev/framework/device/bluetooth.html
划到最下面,有一个示例代码,如下图所示
点击在开发者工具中预览效果就可以打开这个代码,如下
点击导入即可。
【添加device界面】
打开之后,只有一个index界面,所以我们要在添加一个新的界面,取名为device,如下图
注意:微信小程序的一个界面是由4个文件组成的(后缀名不同),所以大家要新建4个文件。
添加文件直接点击加号就可以,如下图所示
然后在app.json文件里面添加"index/device",如下图,这样新建的界面就添加进来了。
【页面跳转】
那怎么从index界面跳转到device界面呢?
在微信小程序中,使用wx.navigateTo 来跳转页面,所以在蓝牙连接成功后进行跳转,如下图
【修改device界面布局】
首先,我们在device界面添加输入框和发送按键,程序如下
其中
文本框
<text>请输入单词:</text>
<text>就是文本框,会在界面中显示文本 请输入单词:
输入框
<input type="text" id="wordInput" placeholder="请输入单词" bindchange="wordchange" />
<input 就是输入框
type="text"就是输入类型为字符串
id="wordInput"就是给输入框起个名字
placeholder="请输入单词"就是输入框默认会显示 请输入单词
bindchange="wordchange"就是当输入框有字符输入时,会调用wordchange这个函数
按键
输入框就讲到这里,接下来在讲一下按键。
<button bindtap="sendWord" >发送</button>
其中 bindtap="sendWord" 就是当按键按下时,就会调用sendWord函数
【js程序修改】
界面布局修改好后,就来看看js的程序怎么修改。
添加变量
首先,我们需要把输入框输入的字符保存到变量中,此时就需要定义一个变量了,如下图
其中,myword用来保存英文单词,
myhzword用来保存单词释义。
变量赋值
那怎么把输入框的字符保存到这两个变量中呢?
此时就需要用到输入框bindchange="wordchange"声明的函数了,我们在wordchange函数中给变量赋值。
程序如下
这样,就把输入框输入的数据保存到变量myword中了,
同样的,保存到myhzword变量中的函数如下
hzwordchange: function(e) { // 更新数据,使得输入框的内容与data中的myhzword同步 this.setData({ myhzword: e.detail.value }); },
数据都保存好了,那该怎么发送呢?
【ble发送数据】
此时就需要编写发送按键按下时的sendWord函数了,如下图
函数内容如下
sendWord: function (e) { let arr = []; // 将myword字符串转换为 数组 for (let i = 0; i < this.data.myword.length; i++) { arr.push(this.data.myword.charCodeAt(i)); } //====================================== let arr2 = []; // 将myhzword字符串转换为Unicode值数组 for (let i = 0; i < this.data.myhzword.length; i++) { arr2.push(this.data.myhzword.charCodeAt(i)); } // 创建足够大的ArrayBuffer let buffer = new ArrayBuffer(arr.length + arr2.length * 2 + 3); let dataView = new DataView(buffer); dataView.setUint8(0, 2); dataView.setUint8(1, arr.length); dataView.setUint8(2, arr2.length); // 将myword的Unicode值存储到DataView中 for (let i = 0; i < arr.length; i++) { dataView.setUint8(i+3, arr[i]); } // 将myhzword的Unicode值存储到DataView中,每个Uint16值需要2个字节 for (let i = 0; i < arr2.length; i++) { dataView.setUint16(i * 2 + arr.length+3, arr2[i], true); // true表示使用小端字节序 } wx.writeBLECharacteristicValue({ deviceId: this._deviceId, serviceId: this._serviceId, characteristicId: this._characteristicId, value: buffer, success (res) { console.log('writeBLECharacteristicValue success', res.errMsg) }, fail (err) { console.log('writeBLECharacteristicValue fail', err.errMsg) } }) },
简单讲解一下这段代码,如下
第一个字节设置为2(表示发送单词的标识)。
第二个字节设置为arr数组的长度(myword字符串的长度)。
第三个字节设置为arr2数组的长度(myhzword字符串的长度)。
那为什么要把英文和中文字符串分别放到两个数组中(arr、arr2)呢?
那是因为一个汉字需要两个字节来保存,所以要分开,
在往DataView放数据时,汉字也是要用setUint16这个函数,而英文字符用setUint8
好了,到这里我们的小程序就修改完成了。
点击预览按键,如下,就可以生成此微信小程序的二维码了
然后用微信扫一扫就可以下载并使用这个小程序了。
【修改STM32WBA55CG程序】
接下来,就该修改开发板的代码了。
【修改接收数据的长度】
首先我们使用官方的BLE_p2pServer这个代码来修改,打开stm32CubeMx进行配置。
因为我们传输的是字符串,原代码接收数据的个数为2,显然太小了,我们修改成40,如下所示
然后生成代码就可以了。
【处理接收到的字符串】
在生成的代码中,我们要处理蓝牙ble接收到的字符串数据,所以在接收函数中增加一个数据拷贝的函数,
把接收到的字符串拷贝出来进行显示,程序如下
ble_data_copy函数如下
void ble_data_copy( unsigned char *data){ for(int i = 0; i < 40; i++){ my_ble_rx_data.data[i] = data[i]; } my_ble_rx_data.flag = 1; }
当我们接收到ble数据时,会把my_ble_rx_data.flag 变量置1,通知显示函数进行处理。
ble数据显示函数如下所示
void show_my_ble_rx_data(void *pTarget, const arm_2d_tile_t *ptTile, arm_2d_region_t my_region, bool bIsNewFrame){ if(1 == my_ble_rx_data.flag){ my_ble_rx_data.flag = 0; if(my_ble_rx_data.data[0] == 2){ draw_string_2d( iX,iY,16, &my_ble_rx_data.data[3], pTarget, ptTile); } } }
首先我们判断如果接收到的数据第一个字节为2,说明收到了单词数据,
然后把接收到的字符串显示出来就可以了。
到此,你以为一切都很正常,屏幕中会显示我们接收到的字符串
然而。。。
这个代码还是有一些问题的。
那是因为微信小程序发送过来的汉字字符是用unicode编码的,而我们的字符显示程序汉字是用的GBK编码的,
所以,显示汉字的时候会出现乱码。
那该怎么办呢?
【处理显示乱码】
此时,你好像想到了直接让微信小程序发送GBK编码的汉字不就可以了吗?
但是微信小程序好像不提供这样的转换(可能是我不熟悉)
所以这个方案暂时就否定掉。
那我们还可以在STM32WBA55CG开发板上进行编码集的转换。
没错,就用这个方案。
这种编码集的转换有很多方法,我们采用查表的方式进行转换,由于这个数组很大,代码就不贴了,到时候放到附件中。
其大概的代码如下
const WCHAR uni2oem[] = { /* Unicode - OEM, Unicode - OEM, Unicode - OEM, Unicode - OEM */ 0x00A4, 0xA1E8, 0x00A7, 0xA1EC, 0x00A8, 0xA1A7, 0x00B0, 0xA1E3, //。。。 } unsigned short ff_convert ( /* Converted code, 0 means conversion error */ unsigned short chr, /* Character code to be converted */ unsigned int dir /* 0: Unicode to OEM code, 1: OEM code to Unicode */ ) { //。。。 }
函数ff_convert就是编码集转换函数,
哈哈,有了这个函数就可以处理显示乱码的问题了。
转换程序如下
for( j = 0; j < my_ble_rx_data.data[2];j++){ my_utogbk.str[0] = my_ble_rx_data.data[j*2 + 3+my_ble_rx_data.data[1]]; my_utogbk.str[1] = my_ble_rx_data.data[j*2 + 1 + 3+my_ble_rx_data.data[1]]; my_utogbk.chr = ff_convert(my_utogbk.chr,0); my_icon_list.chinese_str[j*2] = my_utogbk.str[1]; my_icon_list.chinese_str[j*2 + 1] = my_utogbk.str[0]; //i+=2; }
这样我们就把my_ble_rx_data.data中的Unicode汉字转换成GBK码了,
并把转换后的字符赋值给chinese_str,然后在给屏幕显示就不会有乱码了。
到此,我们就完成了微信小程序通过蓝牙发送数据给开发板,并在oled屏幕中显示的功能了。
不过,开发板上蓝牙程序和arm-2d屏幕显示是怎么做到共存的呢?
哈哈哈,这个也简单,直接上代码,如下
int main(void) { //。。。。 while (1) { /* 这里运行蓝牙程序 */ MX_APPE_Process(); /* 这里运行arm-2d显示程序 */ while( arm_fsm_rt_cpl != disp_adapter0_task() ); } }
是不是很简单,原来他俩都是基于状态机模型编写的代码,天生就可以共存。
要驱动屏幕显示的小伙伴是不是的赶快动手试试arm-2d了。
移植arm-2d的文章如下
【STM32WBA55CG开发板】移植arm-2d驱动单色oled屏幕-电子产品世界论坛
简单使用arm-2d的文章如下
【STM32WBA55CG开发板】使用arm-2d制作电子书界面-电子产品世界论坛
好了,到这里我们今天的文章就结束了。下面附件是微信小程序的代码和Unicode转GBK的代码,如下