我有两个蓝牙设备(来自 bluegiga 的 bled112)。其中之一连接到 RPI 并从其他设备接收 RSSI 和硬件地址。它在 Windows 和 ubuntu 上运行良好,但在树莓派上,从设备文件 (/dev/ttyACM0) 读取时出现问题。
我正在使用 Wheezy 3.6.11,全部更新,安装了 bluez。
那是我的程序,我用来阅读的内容:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include "cmd_def.h"
volatile int serial_fd;
void output(uint8 len1, uint8* data1, uint16 len2, uint8* data2)
{
int written;
written = write(serial_fd, data1, len1);
if(written < 0) {
fprintf(stderr, "ERROR: Writing data. %d\n", (int)errno);
exit(-1);
}
printf("WRITE1: %d bytes ; ", written);
written = write(serial_fd, data2, len2);
if(written < 0) {
fprintf(stderr, "ERROR: Writing data. %d\n", (int)errno);
exit(-1);
}
printf("WRITE2: %d bytes\n", written);
}
int read_message()
{
int rread;
const struct ble_msg *apimsg;
struct ble_header apihdr;
unsigned char data[256];//enough for BLE
//read header
printf("\t\tread_message entered\n");
rread = read(serial_fd, (unsigned char*)&apihdr, 4);
if(rread < 0) {
return errno;
} else if(!rread) {
return 0;
}
printf("READ: header %d bytes ; ", rread);
//read rest if needed
if(apihdr.lolen)
{
rread = read(serial_fd, data, apihdr.lolen);
if(rread < 0) {
return errno;
}
}
printf("READ: data %d bytes ; ", rread);
apimsg=ble_get_msg_hdr(apihdr);
if(!apimsg)
{
fprintf(stderr, "ERROR: Message not found:%d:%d\n",(int)apihdr.cls, (int)apihdr.command);
return -1;
}
apimsg->handler(data);
return 0;
}
int main(int argc, char *argv[] )
{
char* portname;
portname = "/dev/ttyACM0";
serial_fd = open(portname, O_RDWR | O_SYNC);
if (serial_fd < 0)
{
fprintf (stderr, "error %d opening %s: %s", errno, portname, strerror (errno));
return -1;
}
bglib_output = output;
//stop previous operation
ble_cmd_gap_end_procedure();
//get connection status,current command will be handled in response
ble_cmd_connection_get_status(0);
//Message loop
while(1)
{
if(read_message())
{
fprintf(stderr, "Error reading message\n");
break;
}
}
return 0;
}
RPI 的输出为:
$ sudo scanApp
WRITE1: 4 bytes ; WRITE2: 0 bytes
WRITE1: 5 bytes ; WRITE2: 0 bytes
read_message entered
在这部分之后,它在 read-function 中无限运行。如果有人能告诉我,我会非常感激,为什么它在树莓派上不起作用?
编辑: 找到了 uart 的解决方案:
#include <termios.h>
int serial_handle;
int uart_open(char *port){
struct termios options;
int i;
serial_handle = open(port, (O_RDWR | O_NOCTTY));
if(serial_handle < 0)
return -1;
tcgetattr(serial_handle, &options); //get the current options for the port...
cfsetispeed(&options, B115200); //set Baud rate to 115200
cfsetospeed(&options, B115200); //enable the receiver and set param...
options.c_cflag &= ~(PARENB | CSTOPB | CSIZE | CRTSCTS | HUPCL);
options.c_cflag |= (CS8 | CLOCAL | CREAD);
options.c_lflag &= ~(ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHONL | ECHOCTL | ECHOPRT | ECHOKE | IEXTEN);
options.c_iflag &= ~(INPCK | IXON | IXOFF | IXANY | ICRNL);
options.c_oflag &= ~(OPOST | ONLCR);
for ( i = 0; i < sizeof(options.c_cc); i++ )
options.c_cc[i] = _POSIX_VDISABLE;
options.c_cc[VTIME] = 0;
options.c_cc[VMIN] = 1;
//set new opt for the port
tcsetattr(serial_handle, TCSAFLUSH, &options);
return 0;
}
int uart_close(){
close(serial_handle);
}
//write to uart_port
int uart_tx(int len, unsigned char *data){
ssize_t written;
while(len){
written = write(serial_handle, data, len);
if(!written)
return -1;
len -= written;
data += len;
}
return 0;
}
//read from uart_port
int uart_rx(int len, unsigned char *data, int timeout_ms){
int l=len;
ssize_t rread;
struct termios options;
tcgetattr(serial_handle, &options);
options.c_cc[VTIME] = timeout_ms/100;
options.c_cc[VMIN] = 0;
tcsetattr(serial_handle, TCSANOW, &options);
while(len){
rread = read(serial_handle, data, len);
if(!rread){
return 0;
} else if(rread < 0) {
return -1;
}
len-=rread;
data+=len;
}
return l;
}
int main(){
char* portname = "/dev/ttyACM0";
serial_fd = uart_open(portname);
if (serial_fd < 0){
fprintf (stderr, "error %d opening %s: %s", errno, portname, strerror (errno));
return -1;
}
bglib_output = output;
//reset dongle
ble_cmd_system_reset(0);
uart_close();
do{
usleep(500000);
//and start again
}while(uart_open(portname));
//stop previous operation
ble_cmd_gap_end_procedure();
//get connection status,current command will be handled in response
ble_cmd_connection_get_status(0);
//Message loop
while(1){
if(read_message()){
fprintf(stderr, "Error reading message\n");
break;
}
}
uart_close();
return 0;
}
在输出()中使用:
written = uart_tx(len1, data1);
written = uart_tx(len2, data2);
在 read_message() 中:
rread = uart_rx(sizeof(apihdr), (unsigned char*)&apihdr, 1000);
rread = uart_rx(apihdr.lolen, data, 1000);