STM32 RW问题请教

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32 RW问题请教相关的知识,希望对你有一定的参考价值。

参考技术A RW段中存放的一般是静态变量,包括全局静态变量和局部静态变量,初始化或未初始化的。按你描述的,在函数调用的时候,也就是正常运行的时候,这个0x20000044内存值有变化。但是在单步调试的时候,不变。我个人觉得可能是你当前这个跟踪的函数以外,有什么地方改变了它。在全速运行时,花不了多长时间就会发现值变了,但是单步调其实是很慢的,很难复现这个情况。这样,你先查查0x20000044这个是被编译器分配来做什么用的,是不是中断向量表的一部分,还是说是什么静态变量的存储地址。接着再往下查,是静态变量的话,它是什么变量,在代码中查查被哪些地方读写过,有没有可能是被“多线程”方式改变了。另外也比较怀疑是做IAP时有点问题,IAP过程如果用到中断向量表(这几乎是一定要用到的),一定要注意中断向量表重映射的问题,你说的0x20000044和0x20000000很近,0x20000000可能就是你这个STM32
CPU的RAM,重映射中断向量表的时候,一般要重映射到RAM中,不知道是不是IAP相关的代码影响到了这个内存值的变化,注意查查这个问题

RW007系列综合实战1STM32+RW007实现BLE透传功能


本期文章将分为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.串口调试软件(xshellSSCOM 等)

要实现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模块的SCLPA1连接到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/document/site/application-note/driver/i2c/i2c-mpu6050.rar下载后的软件包中包含的文件如下图

在工程目录中刷新后可以显示添加的文件。

添加mpu6050软件包后需要适当修改SConscript 脚本

添加mpu6050软件包后需要适当修改drv_mpu6050.c 文件中的 MPU6050_I2CBUS_NAMEi2c1

然后编译工程,烧录测试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_NAMEserial的声明。

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};
 9
10    rt_err_t ret;
11
12    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));
40
41            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));
45
46            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));
50
51            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));
55
56            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));
60
61            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;
12
13}

说明:上面代码实现RW007 BLE 功能作为主机初始化并设置相关回调的功能,rw007_ble_resp_handlerw007_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);
 9
10    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;
 9
10    conn_handle = 1;
11    char_value = 1;
12
13    uuid.type = BLE_UUID_TYPE_16;
14    sscanf("0xfff1", "%x", &uuidint);
15    uuid.uuid.uuid16 = uuidint & 0xFFFFu;
16
17    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);
12
13            char *pcBegin = NULL;
14            char *pcEnd = NULL;
15            char cRes[15]={0};
16
17            //Here to solve Data
18             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;
10
11}
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.cowtransfer.com/s/274a38fde4b543

????RW007购买链接:

https://item.taobao.com/item.htm?&id=587364858221

口令(复制至X宝打开):5嘻6bLxXVYVZEv嘻 https://m.tb.cn/h.4rai8N8?sm=35e672  RW007 高速WIFI模块 SPI  物联网 透传模块 无线模块

你可以添加微信17775982065为好友,注明:公司+姓名,拉进 RT-Thread 官方微信交流群!

???????????? 点击阅读原文进入RT-Thread官网

以上是关于STM32 RW问题请教的主要内容,如果未能解决你的问题,请参考以下文章

请教STM32F4 的DSP库 FFT运算的问题.求高手指点

请教STM32的 SPI 同时中断收发问题

请教stm32的i2c接收问题

请教STM32F103RBT6的A/D转换问题

请教stm32F407以太网发送和接收帧的格式

请教现在学习单片机是学习51还是stm32开始