Я работаю над прошивкой сенсорной платы ATMEL (акселерометр и гироскоп) и пытаюсь прочитать данные на платформе в Ubuntu.
На данный момент прошивка такая:
Ubuntu отправляет символ «D», а прошивка в ответ отправляет обратно 20 байтов данных, которые заканчиваются на «\n», затем ubuntu использует serialport_read_until(fd, buff, '\n') и предполагает, что buff[0] является нулевым байтом и так далее. Частота сбора 200 Гц. НО, используя этот метод, иногда я получаю поврежденные значения, и он не работает должным образом. Также в Ubuntu много ошибок «Невозможно записать на последовательный порт».
Я нашел пример кода от ATMEL для прошивки и там данные отправляются разными пакетами и непрерывно (не дожидаясь, пока компьютер их запросит) структура такая:
void adv_data_send_3(uint8_t stream_num, uint32_t timestamp,
int32_t value0, int32_t value1, int32_t value2)
{
/* Define packet format with 3 data fields */
struct {
adv_data_start_t start; /* Starting fields of packet */
adv_data_field_t field [3]; /* 3 data fields */
adv_data_end_t end; /* Ending fields of packet */
} packet;
/* Construct packet */
packet.start.header1 = ADV_PKT_HEADER_1;
packet.start.header2 = ADV_PKT_HEADER_2;
packet.start.length = cpu_to_le16(sizeof(packet));
packet.start.type = ADV_PKT_DATA;
packet.start.stream_num = stream_num;
packet.start.time_stamp = cpu_to_le32(timestamp);
packet.field[0].value = cpu_to_le32(value0);
packet.field[1].value = cpu_to_le32(value1);
packet.field[2].value = cpu_to_le32(value2);
packet.end.crc = 0x00; /* Not used */
packet.end.mark = ADV_PKT_END;
/* Write packet */
adv_write_buf((uint8_t *)&packet, sizeof(packet));
}
но я не знаю, как я могу постоянно читать данные, которые отправляются в структуре, подобной приведенной выше.
Извините, если это тривиальный вопрос. Я не программист, но мне нужно это решить, и я не смог найти решение (которое я могу понять!) после поиска в течение нескольких дней.
Функция чтения, которую я использую в Linux:
int serialport_read_until(int fd, unsigned char* buf, char until){
char b[1];
int i=0;
do {
int n = read(fd, b, 1); // read a char at a time
if( n==-1) return -1; // couldn't read
if( n==0 ) {
usleep( 1 * 1000 ); // wait 1 msec try again
continue;
}
buf[i] = b[0]; i++;
} while( b[0] != until );
buf[i] = 0; // null terminate the string
return 0;}
Новая функция чтения:
// Read the header part
adv_data_start_t start;
serial_read_buf(fd, reinterpret_cast<uint8_t*>(&start), sizeof(start));
// Create a buffer for the data and the end marker
std::vector<uint8_t> data_and_end(start.length - sizeof(start));
// Read the data and end marker
serial_read_buf(fd, data_and_end.data(), data_and_end.size());
// Iterate over the data
size_t num_data_fields = (data_and_end.size() - sizeof(adv_data_end_t)) / sizeof(adv_data_field_t);
adv_data_field_t* fields = reinterpret_cast<adv_data_field_t*>(data_and_end.data());
for (size_t i = 0; i < num_data_fields; i++)
std::cout << "Field #" << (i + 1) << " = " << fields[i].value << '\n';
Пакеты данных, которые отправляются из прошивки:
typedef struct {
uint8_t header1; // header bytes - always 0xFF5A
uint8_t header2; // header bytes - always 0xFF5A
uint16_t length; // packet length (bytes)
uint32_t time_stamp; // time stamp (tick count)
} adv_data_start_t;
typedef struct {
int32_t value; // data field value (3 VALUES)
} adv_data_field_t;
typedef struct {
uint8_t crc; // 8-bit checksum
uint8_t mark; // 1-byte end-of-packet marker
uint16_t mark2; // 2-byte end-of-packet marker (Added to avoid data structure alignment problem)
} adv_data_end_t;
end
, помните, что последовательная связь может быть ненадежной, и поэтому вам нужна некоторая проверка для этого (например, два поля заголовка, длина, (необязательно?) поле CRC и маркер конца пакета) . Вы должны проверить, что эти поля в порядке. 23.07.2013