如何通过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
相关产品推荐
相关产品推荐

