#gtk #serial-communication
#gtk #последовательная связь
Вопрос:
Эта программа предназначена для обмена данными по ненадежному последовательному каналу через USB-конвертер PL2303 с удаленным микроконтроллером. Основной цикл использует g_io_add_watch для прослушивания данных с микроконтроллера. Затем он вызывает g_io_read_chars для чтения данных и g_io_write_chars для отправки однобайтового подтверждения. Микро повторяет это. Чтение и запись вызываются из ReadStationMessage. Если микропроцессор медленно отвечает, функция ReadStationMessage() вызывается дважды, один раз для чтения данных и еще раз для получения эха. Однако, если он отвечает немедленно, ReadStationMessage() вызывается только один раз, и байт echo добавляется к данным. Я не понимаю, как это возможно, когда g_io_write_chars не отправляет подтверждение до тех пор, пока g_io_read_chars не вернется, и микро ничего не делает, пока не получит подтверждение.
#include <gtk/gtk.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
int set_interface_attribs(int fd, int speed)
{
struct termios tty;
if (tcgetattr(fd, amp;tty) < 0) {
g_print("Error from tcgetattr: %sn", strerror(errno));
return -1; }
cfmakeraw(amp;tty);
cfsetospeed(amp;tty, (speed_t)speed);
cfsetispeed(amp;tty, (speed_t)speed);
tty.c_cc[VMIN] = 0; tty.c_cc[VTIME] = 1;
if (tcsetattr(fd, TCSANOW, amp;tty) != 0) {
g_print("Error from tcsetattr: %sn", strerror(errno));
return -1; }
return 0;
}
static gboolean ReadStationMessage( GIOChannel *channel, GIOCondition condition, guchar* user_data )
{
guchar buf[128];
gsize bytes_read, bytes_written;
gint i;
g_print("nentering ReadStationMessagen");
g_io_channel_read_chars( channel, buf, 128, amp;bytes_read, NULL );
for( i=0; i<bytes_read; i ) g_print("%u ", buf[i]);
buf[0] = 0;
g_io_channel_write_chars( channel, buf, 1, amp;bytes_written, NULL );
return TRUE;
}
int main( int argc, char *argv[] )
{
char *portname = "/dev/ttyUSB0";
gint fd;
GIOChannel *channel;
static guchar user_data[128];
GError *error=NULL;
guint EventSource_id;
fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC );
set_interface_attribs(fd, B9600);
channel = g_io_channel_unix_new(fd);
g_io_channel_set_encoding(channel, NULL, amp;error); // raw data, no encoding
GIOCondition condition = G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
gtk_init (amp;argc, amp;argv);
EventSource_id = g_io_add_watch( channel, condition, (GIOFunc) ReadStationMessage, user_data );
return 0;
}
Ответ №1:
Исправлено! Мне нужно выполнить сброс канала ввода-вывода после записи.