本期文章将分为5篇连载,前2篇将围绕模块功能详解展开,其后3篇将为大家讲解基于RW007相关DEMO的实现,文章目录如下:
今天我们将使用STM32F411-NUCLEO
通过 RW007
BLE 功能读取来自KT6368A
蓝牙模块的MPU6050
传感器数据,实现BLE
透传功能,算是学习 RW007 模块 BLE 功能的一个综合Demo实战哈!!!
硬件准备
1.STM32F411-NUCLEO
开发板,RW007 EVB
模块
2.PC
电脑
3.USB
数据线
4.BLE
数据透传模块(如HC-08
模块、KT6368A
蓝牙模块等)
5.STM32F401-NUCLEO
开发板,MPU6050
模块
6.USB-TTL
模块(如CH340
等)
7.杜邦线若干条
软件准备
1.RT-Thread Studio IDE
软件
2.串口调试软件(xshell
、SSCOM
等)
要实现MPU6050
传感器数据BLE透传的功能,需要分为发送端设备和接收端设备。
发送端设备:
由 STM32F401-NUCLEO
读取 mpu6050
传感器数据配合KT6368A蓝牙模块
数据透传。
可以分为以下的 7 个步骤:
- 步骤1:创建 RT-Thread Studio IDE 工程
- 步骤2:项目工程配置
I2C
设备框架和硬件IO 引脚配置及硬件连接 - 步骤3:添加
mpu6050
软件包,测试mpu6050
数据获取 - 步骤4:项目工程配置开启
uart6
串口配置和硬件连接 - 步骤5:测试
uart6
串口功能 - 步骤6:把获取的
mpu6050
数据通过uart6
串口输出 - 步骤7:把
KT6368A蓝牙模块
的RXD
引脚接在uart6
串口配置的TXD
其中各个步骤的具体操作如下:
步骤1:创建 RT-Thread Studio IDE 工程
由于使用RT-Thread Studio IDE
如何创建STM32F401-NUCLEO
的工程,这个在官方的文档中心中有相关的文档说明,这里只作简单说明。
(1)通过点击新建RT-Thread
项目,选择基于开发板,型号选择STM332F401-NUCLEO
,输入工程名称,点击完成按钮开始创建工程。
步骤2:项目工程配置 I2C
设备框架和硬件IO 引脚配置及硬件连接
在配置I2C
设备框架前,先确定使用那组硬件 IO 引脚,在这里使用 PA4
连接到mpu6050
模块的SCL
,PA1
连接到mpu6050
模块的SCK
.由于使用的是软件模拟的 I2C
功能,只需确保对应的IO
引脚没有被复用即可。
配置完成后,编译工程烧录到板子上,通过串口验证是否I2C
设备框架正常工作。
注意:如果程序下载过程中提示 Warning: The core is locked up,需要在属性中配置为 system Reset 的复位模式
如图,通过list_device
可以查看到有i2c1
这个 device
,表明配置已经生效。
步骤3:添加mpu6050
软件包,测试 mpu6050
数据获取
关于 mpu6050
软件包的使用,可以参考官方文档关于mpu6050
传感器的使用,在这里仅是说明如何使用从官网相关文档中下载的mpu6050
驱动包,获取数据。
mpu6050
软件驱动包的下载连接:https://www.rt-thread.org/doc...
在工程目录中刷新后可以显示添加的文件。
添加mpu6050软件包
后需要适当修改SConscript
脚本
添加mpu6050软件包
后需要适当修改drv_mpu6050.c
文件中的 MPU6050_I2CBUS_NAME
为 i2c1
。
然后编译工程,烧录测试mpu6050
的功能。
步骤4:项目工程配置开启 uart6
串口配置和硬件连接
由于默认创建的工程中没有开启uart6
串口的配置,需要使用CubeMX
开启 uart6
的串口功能配置。
由于默认的图形化配置中没有UART6
的配置,需要手动修改添加。
修改 Kconfig
添加 UART6
的配置后,需要图形化配置。
如图,默认USART6
串口功能的RXD
引脚是PC7
,TXD
引脚是PC6
.
此时,可以使用一个 USB-TTL
串口模块的与STM32F401-NUCLEO
进行连接测试uart6
的功能。
步骤5:测试 uart6
串口功能
关于 uart
通信的示例,在官网的文档中心中有相关详细的说明,这里就不进行详细的描述。
直接从相关文档中参考一小段代码进行测试。
1#define SAMPLE_UART_NAME "uart6" /* 串口设备名称 */ 2static rt_device_t serial; /* 串口设备句柄 */ 3char str[] = "hello RT-Thread!\r\n"; 4struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 配置参数 */ 5/* 查找串口设备 */ 6serial = rt_device_find(SAMPLE_UART_NAME); 7 8/* 以中断接收及轮询发送模式打开串口设备 */ 9rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);10/* 发送字符串 */11rt_device_write(serial, 0, str, (sizeof(str) - 1));
把上面的代码添加到工程里面的main.c
文件中,通过MSH
命令启动测试。
此时通过 SSCOM
串口调试工具观察 USB-TTL
串口模块接收来自STM32F401-NUCLEO
串口 UART6
发送的数据。
到此,验证uart6
串口功能正常。
步骤6:把获取的mpu6050
数据通过 uart6
串口输出
这里需要把获取的mpu6050
数据通过uart6
串口输出,需要适当修改代码,主要是添加 uart6
串口的初始化还有把mpu6050
数据通过uart6
输出。
在main.c
文件中,添加BLE_UART_NAME
和serial
的声明。
1#define BLE_UART_NAME "uart6" /* 串口设备名称 */2static rt_device_t serial; /* 串口设备句柄 */
在main
函数中,添加 uart6
串口的初始化代码。
1 /* 查找系统中的串口设备 */2 serial = rt_device_find(BLE_UART_NAME);3 if (!serial)4 {5 rt_kprintf("find %s failed!\n", BLE_UART_NAME);6 return RT_ERROR;7 }8 rt_kprintf("open uart6 ok...\n");9 rt_device_open(serial, RT_DEVICE_FLAG_INT_RX)
在mpu6050_thread_entry
函数中,添加把mpu6050
数据通过uart6
输出的功能代码。
1void mpu6050_thread_entry(void *parameter) 2{ 3 rt_int16_t temp; //温度 4 rt_int16_t gx,gy,gz; //三轴加速度 5 rt_int16_t ax,ay,az; //三轴角速度 6 7 char TempStr[15] = {0}; 8 //char Gx[10] = {0}; 910 rt_err_t ret;1112 while(1)13 {14 ret = mpu6050_temperature_get(&temp);15 if (ret != RT_EOK)16 {17 rt_kprintf("mpu6050 : get temperature error\r\n");18 }19 ret = mpu6050_accelerometer_get(&ax, &ay, &az);20 if (ret != RT_EOK)21 {22 rt_kprintf("mpu6050 : get acc error\r\n");23 }24 ret = mpu6050_gyroscope_get(&gx, &gy, &gz);25 if (ret != RT_EOK)26 {27 rt_kprintf("mpu6050 : get gyro error\r\n");28 }29 if (ret == RT_EOK)30 {31 //rt_kprintf("mpu6050: temperature=%-6d gx=%-6d gy=%-6d gz=%-6d ax=%-6d ay=%-6d az=%-6d\r\n",temp/100,gx,gy,gz,ax,ay,az);32 sprintf(TempStr,"55temp=%dAA",temp/100);33 rt_device_write(serial, 0, TempStr, (sizeof(TempStr) - 1));34 memset(TempStr,0,sizeof(TempStr)/sizeof(char));35 rt_thread_delay(rt_tick_from_millisecond(500));36 sprintf(TempStr,"55gx=%dAA",gx);37 rt_device_write(serial, 0, TempStr, (sizeof(TempStr) - 1));38 memset(TempStr,0,sizeof(TempStr)/sizeof(char));39 rt_thread_delay(rt_tick_from_millisecond(500));4041 sprintf(TempStr,"55gy=%dAA",gy);42 rt_device_write(serial, 0, TempStr, (sizeof(TempStr) - 1));43 memset(TempStr,0,sizeof(TempStr)/sizeof(char));44 rt_thread_delay(rt_tick_from_millisecond(500));4546 sprintf(TempStr,"55gz=%dAA",gz);47 rt_device_write(serial, 0, TempStr, (sizeof(TempStr) - 1));48 memset(TempStr,0,sizeof(TempStr)/sizeof(char));49 rt_thread_delay(rt_tick_from_millisecond(500));5051 sprintf(TempStr,"55ax=%dAA",ax);52 rt_device_write(serial, 0, TempStr, (sizeof(TempStr) - 1));53 memset(TempStr,0,sizeof(TempStr)/sizeof(char));54 rt_thread_delay(rt_tick_from_millisecond(500));5556 sprintf(TempStr,"55ay=%dAA",ay);57 rt_device_write(serial, 0, TempStr, (sizeof(TempStr) - 1));58 memset(TempStr,0,sizeof(TempStr)/sizeof(char));59 rt_thread_delay(rt_tick_from_millisecond(500));6061 sprintf(TempStr,"55az=%dAA",az);62 rt_device_write(serial, 0, TempStr, (sizeof(TempStr) - 1));63 memset(TempStr,0,sizeof(TempStr)/sizeof(char));64 }65 rt_thread_delay(rt_tick_from_millisecond(1000));66 }67}
说明:由于 BLE
设备单次发送的数据长度有限制,需要拆分mpu6050
的数据,并在发送的一帧数据前加上55
作为数据头,在一帧数据后添加AA
作为数据尾,这样方便接收方解析数据。
步骤7:把KT6368A蓝牙模块
的RXD
引脚接在uart6
串口配置的TXD
基于前面的步骤,这里距离蓝牙数据透传功能的实现仅需要进行最后一步,把KT6368A蓝牙模块
的RXD
引脚接在uart6
串口配置的TXD
,由于KT6368A蓝牙模块
一旦被连接后,就自动进入了透传模式,这时候可以参考上面的使用手机调试的方法,尝试读取数据。
到此,STM32F401-NUCLEO
读取 mpu6050
传感器数据配合KT6368A蓝牙模块
数据透传的功能完成。
接收端设备:
STM32F411-NUCLEO
通过 RW007
BLE 功能读取mpu6050
传感器数据。
可以分为以下的 2 个步骤:
- 步骤1:创建 RT-Thread Studio IDE 工程
- 步骤2:添加
BLE
功能读取mpu6050
传感器数据并解析的功能实现代码
步骤1:创建 RT-Thread Studio IDE 工程
这里可以参考前面 使用
STM32F411-NUCLEO通过
RW007BLE 功能测试
BLE蓝牙模块数据传输功能
这部分的内容,进行创建工程,在这个工程的基础上,只需要添加一小部分代码就可以实现读取mpu6050
传感器数据的功能。这里在 application
目录下添加ble_example.c
文件,并修改applications
目录下的SConscript
脚本,把ble_example.c
添加到工程编译。
步骤2:添加BLE
功能读取mpu6050
传感器数据并解析的功能实现代码
在ble_example.c
文件中添加BLE
功能读取mpu6050
传感器数据并解析的功能实现代码,主要参考rw007
软件包中的ble_cmd_rw007.c
里面关于ble
命令的使用。
(1)添加RW007
BLE 功能初始化
1static int ble_example_init(void) 2{ 3 rt_kprintf("ble_example_init\n"); 4 rt_uint8_t roles = 0; 5 roles = RW007_BLE_INIT_ROLE_CENTRAL; 6 7 rw007_ble_init(roles); 8 9 rw007_ble_resp_handle_cb_reg(rw007_ble_resp_handle);10 rw007_ble_ntf_handle_cb_reg(rw007_ble_ntf_handle);11 return 0;1213}
说明:上面代码实现RW007
BLE 功能作为主机初始化并设置相关回调的功能,rw007_ble_resp_handle
和 rw007_ble_ntf_handle
函数可以直接参考ble_cmd_rw007.c
文件里面的,具体的可以查询相关的代码。
(2)添加RW007
BLE 功能通过addr
连接指定的BLE
设备由于前面的步骤中,明确了需要连接的BLE
设备的addr
(即mac
地址),这里就使用了。
1static int ble_example_connect(void) 2{ 3 rt_kprintf("ble_example_connect\n"); 4 ble_addr_t addr; 5 addr.type = RW007_BLE_ADDR_PUBLIC; 6 rt_kprintf("str_addr: %s\n", "ee:dd:ff:ee:cc:aa"); 7 8 _hexstrtoaddr("ee:dd:ff:ee:cc:aa", addr.val); 910 rt_kprintf("mac addr: %2x:%2x:%2x:%2x:%2x:%2x\n", addr.val[0], addr.val[1],11 addr.val[2], addr.val[3],12 addr.val[4], addr.val[5]);13 rw007_ble_connect(&addr);14 return 0;15}
说明:上面代码实现通过BLE
设备的addr
(即mac
地址)进行连接。
(3)添加RW007
BLE 功能通过UUID
接收数据在前面的步骤中,知道可以通过 UUID=0XFFF1
来接收BLE
设备的数据。
1static int ble_example_gatt_notify_change_by_uuid(void) 2{ 3 rt_kprintf("ble_example_gatt_notify_change_by_uuid\n"); 4 rt_uint16_t conn_handle = 0; 5 rt_uint16_t char_value = 0; 6 7 int uuidint; 8 rw007_ble_uuid_t uuid; 910 conn_handle = 1;11 char_value = 1;1213 uuid.type = BLE_UUID_TYPE_16;14 sscanf("0xfff1", "%x", &uuidint);15 uuid.uuid.uuid16 = uuidint & 0xFFFFu;1617 rw007_ble_gatt_notify_change_by_uuid(conn_handle, &uuid, char_value);18 return 0;19}
说明:上面的代码中实现,通过设置UUID=0XFFF1
来接收BLE
设备的数据\`
(4)添加数据解析部分的功能通过前面的测试中,可以知道BLE_TEST
设备会把数据通过NOTIFY
发送,此时只需要在RW007_BLE_NTF_TYPE_NOTIFY_RX
中进行处理,把接收的数据解析(去掉数据头55、数据尾AA)
1 case RW007_BLE_NTF_TYPE_NOTIFY_RX: 2 { 3 struct rw007_ble_gap_event_notify_rx *notify_rx; 4 5 rt_kprintf("RW007_BLE_NTF_TYPE_NOTIFY_RX\n"); 6 7 notify_rx = (struct rw007_ble_gap_event_notify_rx *)data; 8 rt_kprintf("conn_handle:%d, attr_handle:%d, rcv (%s) length:%d, data:\n", 9 notify_rx->conn_handle, notify_rx->attr_handle,10 notify_rx->indication ? "indication":"notification", notify_rx->length_data);11 hex_dump((const rt_uint8_t *)(notify_rx + 1), notify_rx->length_data);1213 char *pcBegin = NULL;14 char *pcEnd = NULL;15 char cRes[15]={0};1617 //Here to solve Data18 pcBegin = strstr((const rt_uint8_t *)(notify_rx + 1),"55");19 pcEnd = strstr((const rt_uint8_t *)(notify_rx + 1),"AA");20 if(pcBegin == NULL || pcEnd == NULL || pcBegin > pcEnd)21 {22 rt_kprintf("data not found!!!\n");23 }24 else {25 pcBegin += strlen("55");26 rt_memcpy(cRes, pcBegin, pcEnd-pcBegin);27 rt_kprintf("data:%s\n",cRes);28 }29 break;30 }
(5)添加启动测试命令
在调试过程中,可以把启动的函数导出到msh
命令中执行。
1static int ble_example_start(void) 2{ 3 ble_example_init(); 4 rt_thread_delay(1000); 5 ble_example_connect(); 6 rt_thread_delay(5000); 7 ble_example_gatt_notify_change_by_uuid(); 8 9 return 0;1011}12MSH_CMD_EXPORT(ble_example_start,ble_example_start)
说明:把ble_example_start
函数导出到msh
命令行中执行,代码中添加一些适当的延时是考虑到BLE
设备执行连接需要等待一些时间。
(6)工程编译与下载按照上面的步骤操作后,重新编译工程下载到板子上,在STM32F411-NUCLEO
的调试串口上输入ble_example_start
的命令进行通过 RW007
BLE 功能读取mpu6050
传感器数据。
到此,STM32F411-NUCLEO
通过 RW007
BLE 功能读取mpu6050
传感器数据功能完成。
常见问题
1.下载程序过程中提示Warning: The core is locked up
,导致程序烧录失败。
一般在属性设置中重新配置工程的复位模式即可解决。
🔗RW007资料链接:
奶牛网盘 https://realthread.cowtransfe...
🔗RW007购买链接:
https://item.taobao.com/item....
口令(复制至X宝打开):5嘻6bLxXVYVZEv嘻 https://m.tb.cn/h.4rai8N8?sm=... RW007 高速WIFI模块 SPI 物联网 透传模块 无线模块
推荐阅读
【AI简报20210514期】开源项目树莓派复古相机、L4自动驾驶新闻速递
【RW007系列连载1】RW007-BLE主机通信使用学习示例与综合Demo
当“树莓派”遇上RT-Thread Smart——应用编程入门
原文链接:RTThread物联网操作系统
作者: yingjian