这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 【STM32WBA55CG开发板】蓝牙传书(使用微信小程序传输中英文字符串)

共8条 1/1 1 跳转至

【STM32WBA55CG开发板】蓝牙传书(使用微信小程序传输中英文字符串)

菜鸟
2024-12-30 22:05:33     打赏

【说在前面的话】

首先,我想介绍一下STM32WBA55CG开发板,这是一款专为蓝牙通信设计的硬件平台。要实现与该开发板的蓝牙通信,我们需要一个相应的蓝牙通信应用程序。

接下来,我将分享如何通过修改微信小程序的代码来实现与开发板之间的字符串传输。鉴于视频教程中已经展示了使用微信小程序进行蓝牙通信的方法,我们只需在此基础上进行一些调整即可。

由于这是我首次涉足微信小程序的开发,我将详尽记录下整个修改过程的每一个步骤。

如果你也是微信小程序开发的新手,希望这篇文章能为你解决在开发过程中遇到的问题提供一些帮助。

对于那些已经是微信小程序开发领域的高手,如果你在阅读文章时发现了任何不足之处,欢迎提出宝贵的意见和建议。非常感谢!

同时,我也会把这个小程序的代码上传到附件,供大家参考。


【微信小程序界面

接下来,让我们先预览微信小程序中将要实现的两个界面。如下图所示,02.png

第一个界面是蓝牙扫描界面。在此界面中,当程序成功探测到我们的设备(设备名为“p2ps_17”)后,用户只需点击该设备,即可建立连接。一旦连接成功,界面将自动跳转至第二个界面。

第二个界面是用于发送字符串的。在这个界面上,用户可以输入单词及其释义,然后点击发送按钮。这样,用户输入的单词就会被发送到我们的STM32WBA55CG开发板。

开发板接收到这些字符串后,会将其显示在OLED屏幕上,效果如下图所示。

01.png

功能介绍到此为止,现在,我们将开始着手编写微信小程序的代码。

【编写前的准备】

首先,要在电脑上安装微信开发者工具,如下图

04.png

接着,打开下面的网站  

https://developers.weixin.qq.com/miniprogram/dev/framework/device/bluetooth.html

划到最下面,有一个示例代码,如下图所示

05.png

点击在开发者工具中预览效果就可以打开这个代码,如下

1735464261253867.png

点击导入即可。

【添加device界面】

打开之后,只有一个index界面,所以我们要在添加一个新的界面,取名为device,如下图

07.png

注意:微信小程序的一个界面是由4个文件组成的(后缀名不同),所以大家要新建4个文件。

添加文件直接点击加号就可以,如下图所示

17.jpg

然后在app.json文件里面添加"index/device",如下图,这样新建的界面就添加进来了。

08.png

【页面跳转】

那怎么从index界面跳转到device界面呢?

在微信小程序中,使用wx.navigateTo 来跳转页面,所以在蓝牙连接成功后进行跳转,如下图

09.png

【修改device界面布局】

首先,我们在device界面添加输入框和发送按键,程序如下

1735477263202891.png

其中

文本框

<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的程序怎么修改。


添加变量

首先,我们需要把输入框输入的字符保存到变量中,此时就需要定义一个变量了,如下图

11.png

其中,myword用来保存英文单词,

myhzword用来保存单词释义。


变量赋值

那怎么把输入框的字符保存到这两个变量中呢?

此时就需要用到输入框bindchange="wordchange"声明的函数了,我们在wordchange函数中给变量赋值。

程序如下

12.png

这样,就把输入框输入的数据保存到变量myword中了,

同样的,保存到myhzword变量中的函数如下

 hzwordchange: function(e) {
     // 更新数据,使得输入框的内容与data中的myhzword同步
     this.setData({ 
        myhzword: e.detail.value
     });
 },

数据都保存好了,那该怎么发送呢?

【ble发送数据】

此时就需要编写发送按键按下时的sendWord函数了,如下图

13.png

函数内容如下

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)      
          }    
      })   
},

简单讲解一下这段代码,如下

  1. 定义了一个空数组arr,用于存储myword字符串的Unicode值。

    使用一个for循环遍历myword字符串,将每个字符的Unicode值(通过charCodeAt方法获得)添加到arr数组中。

  2. 定义了一个空数组arr2,用于存储myhzword字符串的Unicode值。

    使用另一个for循环遍历myhzword字符串,将每个字符的Unicode值添加到arr2数组中。

  3. 创建了一个ArrayBuffer,其大小足以容纳arr和arr2数组中所有值的总和,再加上3个字节的空间(用于存储一些额外的信息)。

  4. 创建了一个DataView对象,用于操作ArrayBuffer中的数据。

  5. 在DataView中设置了前三个字节的值:

    1. 第一个字节设置为2(表示发送单词的标识)。

    2. 第二个字节设置为arr数组的长度(myword字符串的长度)。

    3. 第三个字节设置为arr2数组的长度(myhzword字符串的长度)。

  6. 使用for循环将arr数组中的Unicode值(英文单词)存储到DataView中,从索引3开始(因为前三个字节已经被设置)。

  7. 使用另一个for循环将arr2数组中的Unicode值(单词释义)存储到DataView中,每个Uint16值需要2个字节,从arr数组长度加3的位置开始,并且使用小端字节序。

  8. 调用微信小程序的wx.writeBLECharacteristicValue接口,将ArrayBuffer作为值发送给STM32WBA55CG开发板

那为什么要把英文和中文字符串分别放到两个数组中(arr、arr2)呢?

那是因为一个汉字需要两个字节来保存,所以要分开,

往DataView放数据时,汉字也是要用setUint16这个函数,而英文字符用setUint8

好了,到这里我们的小程序就修改完成了。

点击预览按键,如下,就可以生成此微信小程序的二维码了

1735546441859576.png

然后用微信扫一扫就可以下载并使用这个小程序了。

【修改STM32WBA55CG程序

接下来,就该修改开发板的代码了。

【修改接收数据的长度】

首先我们使用官方的BLE_p2pServer这个代码来修改,打开stm32CubeMx进行配置。

因为我们传输的是字符串,原代码接收数据的个数为2,显然太小了,我们修改成40,如下所示

1735547184257815.png

然后生成代码就可以了。

【处理接收到的字符串】

在生成的代码中,我们要处理蓝牙ble接收到的字符串数据,所以在接收函数中增加一个数据拷贝的函数,

把接收到的字符串拷贝出来进行显示,程序如下

1735553039118958.png

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的代码,如下

minicode-1.zip

u_to_gbk.zip





关键词: ble    

专家
2024-12-30 22:22:22     打赏
2楼

感谢分享


高工
2024-12-30 23:05:23     打赏
3楼

这个还是蛮高级的样子嘛!

话说现在嵌入式工程师都要会开发微信小程序了吗?


高工
2024-12-31 00:06:14     打赏
4楼

谢谢分享


工程师
2024-12-31 10:22:24     打赏
5楼

6666


菜鸟
2024-12-31 18:28:51     打赏
6楼

感谢分享。


院士
2025-01-01 16:31:23     打赏
7楼

谢谢分享。


菜鸟
2025-01-02 17:22:49     打赏
8楼

微信小程序添加文件还有一个简单的办法,如下图

20.png


共8条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]