You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过BlueZ与Arduino建立持续蓝牙连接并实现数据收发?

问题解决:蓝牙通信无法接收返回值及连接快速断开

核心问题分析

你的PC端C程序存在3个关键错误,导致无法接收Arduino返回数据且连接直接断开:

  • 错误调用服务器端API:PC作为主动连接的蓝牙客户端,不需要调用listen()——该函数仅用于服务器端监听连接请求,客户端直接用已建立的socket通信即可。
  • 未初始化的client变量:read(client, ...)中的client未赋值,是随机垃圾值,导致读取操作失败,程序直接执行close(s)终止连接。
  • 发送数据格式不匹配:Arduino用readStringUntil('\n')读取数据,你发送的"8"没有换行符,虽Arduino可能因超时完成读取,但规范发送"8\n"能确保数据被立即处理。

修正后的PC端代码

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>

int main(int argc, char **argv)
{
    struct sockaddr_rc addr = { 0 };
    int s, status;
    char dest[18] = "98:DA:60:03:F2:92";

    // 分配蓝牙socket
    s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
    if (s < 0) {
        perror("socket creation failed");
        return 1;
    }

    // 设置连接目标参数
    addr.rc_family = AF_BLUETOOTH;
    addr.rc_channel = (uint8_t) 1;
    str2ba(dest, &addr.rc_bdaddr);

    // 建立连接
    status = connect(s, (struct sockaddr *)&addr, sizeof(addr));
    if (status < 0) {
        perror("connection failed");
        close(s);
        return 1;
    }
    printf("Connected to Arduino\n");

    // 发送带换行符的指令,匹配Arduino的读取逻辑
    char cmd[] = "8\n";
    status = write(s, cmd, sizeof(cmd)-1); // 不发送字符串终止符'\0'
    if (status < 0) {
        perror("write failed");
        close(s);
        return 1;
    }

    // 读取Arduino返回的数据
    char buf[1024] = { 0 };
    ssize_t bytes_read = read(s, buf, sizeof(buf)-1);
    if (bytes_read > 0) {
        buf[bytes_read] = '\0'; // 手动添加字符串终止符
        printf("Received: [%s]\n", buf);
    } else if (bytes_read == 0) {
        printf("Arduino closed connection\n");
    } else {
        perror("read failed");
    }

    // 延迟关闭连接(可选,避免立即断开)
    sleep(1);
    close(s);
    return 0;
}

额外调试与开发建议

  • Arduino调试优化:增加串口日志,方便确认数据收发情况:
    if (BTSerial.available() > 0) {
        String input = BTSerial.readStringUntil('\n');
        int c = input.toInt();
        BTSerial.write(c);
        Serial.print("Received: ");
        Serial.println(input); // 串口监视器查看输入
        if(c == 8) {
          Buzzing(SOS);
          BTSerial.println("eight");
          Serial.println("Sent 'eight' response");
        }
    }
    
  • BlueZ工具调试:用Linux自带的rfcomm命令快速测试蓝牙连接:
    • 建立连接:rfcomm connect /dev/rfcomm0 98:DA:60:03:F2:92 1
    • 发送指令:echo "8" > /dev/rfcomm0
    • 接收返回:cat /dev/rfcomm0
  • UI开发方向:若要实现带按钮和地图的图形界面,C语言可选用GTK或Qt框架,它们提供了成熟的串口/蓝牙通信封装,能更便捷地实现异步交互逻辑。

内容的提问来源于stack exchange,提问作者Jenő Fekete

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 16:35:34