ioctl() для проверки состояния rs232 (почему нужно писать !!(arg & TIOCM_...);)

Модератор: Модераторы разделов

Alexander_a
Сообщения: 6

ioctl() для проверки состояния rs232

Сообщение Alexander_a »

Я пробую разобраться в коде программы statserial.
Для проверки состояния пинов интерфейса RS232, используют ioctl() функцию:

Код: Выделить всё

        .......
        fd = open(device, O_RDONLY);
        ......
        status = ioctl(fd, TIOCMGET, &arg);
        printf ("Печатаем состояние на пине RTS: %d\n", !!(arg & TIOCM_RTS));
        ......


Я никак не могу разобраться почему чтобы увидеть правильное значение, нужно помещать в скобки
(arg & TIOCM_RTS), а перед скобками два восклицаетльных знака?
Что здесь означают & и !! - поразрядная конъюнкция и двойное отрицание?

Помогите, как разобраться в этом?
Спасибо сказали:
Sfunx
Сообщения: 47

Re: ioctl() для проверки состояния rs232

Сообщение Sfunx »

Alexander_a писал(а):
26.02.2006 02:25
Я пробую разобраться в коде программы statserial.
Для проверки состояния пинов интерфейса RS232, используют ioctl() функцию:

Код: Выделить всё

        .......
        fd = open(device, O_RDONLY);
        ......
        status = ioctl(fd, TIOCMGET, &arg);
        printf ("Печатаем состояние на пине RTS: %d\n", !!(arg & TIOCM_RTS));
        ......


Я никак не могу разобраться почему чтобы увидеть правильное значение, нужно помещать в скобки
(arg & TIOCM_RTS), а перед скобками два восклицаетльных знака?
Что здесь означают & и !! - поразрядная конъюнкция и двойное отрицание?

Помогите, как разобраться в этом?


& - поразрядная конъюнкция
!! - двойное отрицание

Подозреваю, что "правильное значение" это 0 или 1. Так ?
Если так, то все просто.

Выражение (arg & TIOCM_RTS) выдает 0 или 4 (TIOCM_RTS=4, см файл /usr/include/asm/termios.h).

С помощью !! его приводят к виду "0" или "1".

В случае, когда (arg & TIOCM_RTS) равно 0 - !(arg & TIOCM_RTS) равно 1.
В случае, когда (arg & TIOCM_RTS) равно 4 - !(arg & TIOCM_RTS) равно 0.

То есть это выражение приводит арифметику (0, 4) к логике (1, 0).

Второй "!" - инвертирует логическое значение и тем самым приводит (1,0) к (0,1)

В случае, когда (arg & TIOCM_RTS) равно 0 - !!(arg & TIOCM_RTS) равно 0.
В случае, когда (arg & TIOCM_RTS) равно 4 - !!(arg & TIOCM_RTS) равно 1.

както немного путано получилось.

В общем суть этого выражения - когда в разраде TIOCM_RTS стоит 0 - вывести 0, когда там 1 - вывести 1.
Спасибо сказали:
Alexander_a
Сообщения: 6

Re: ioctl() для проверки состояния rs232

Сообщение Alexander_a »

Ситуация начала было прояснятся, но я написал прогу чтобы понять как производится счет и совсем запутался:

Код: Выделить всё

.....
status = ioctl(fd, TIOCMGET, &arg);
printf("Печатаем arg: %d\n", arg);
printf("Печатаем TIOCM_CTS: %d\n", TIOCM_CTS);
printf("Печатаем TIOCM_RTS: %d\n", TIOCM_RTS);
printf("Печатаем TIOCM_DSR: %d\n", TIOCM_DSR);
printf("Печатаем TIOCM_CAR: %d\n", TIOCM_CAR);
printf("Печатаем TIOCM_DTR: %d\n", TIOCM_DTR);
printf("Печатаем TIOCM_RNG: %d\n", TIOCM_RNG);
cts_status = (arg & TIOCM_CTS);
printf("Печатаем cts_status = (arg & TIOCM_CTS): %d\n", cts_status);
cts_status = !(arg & TIOCM_CTS);
printf("Печатаем cts_status = !(arg & TIOCM_CTS): %d\n", cts_status);
cts_status = !!(arg & TIOCM_CTS);
printf("Печатаем cts_status = !!(arg & TIOCM_CTS): %d\n", cts_status);
.....


Вот что получилось:
(К RS232 подключен UPS)

Код: Выделить всё

Печатаем arg: 16486
Печатаем TIOCM_CTS: 32
Печатаем TIOCM_RTS: 4
Печатаем TIOCM_DSR: 256
Печатаем TIOCM_CAR: 64
Печатаем TIOCM_DTR: 2
Печатаем TIOCM_RNG: 128
Печатаем cts_status = (arg & TIOCM_CTS): 32
Печатаем cts_status = !(arg & TIOCM_CTS): 0
Печатаем cts_status = !!(arg & TIOCM_CTS): 1


Значения TIOCM_CTS соответствуют указаным в /usr/include/asm/termios.h

А что храниться в переменной arg?

Получается, что (16486 & 32) == 32 ?
Что то я не соображу, а если инвертируем, то получается 0?
Здесь нужно что как-то по другому думать/считать? А ля в двоичном коде?
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: ioctl() для проверки состояния rs232

Сообщение Zeus »

Alexander_a писал(а):
26.02.2006 11:33
Получается, что (16486 & 32) == 32 ?
Что то я не соображу, а если инвертируем, то получается 0?
Здесь нужно что как-то по другому думать/считать? А ля в двоичном коде?

Вообще-то сишник почитать неплохо было бы.
! - не двоичное отрицание, а логическое!
В С - любое не 0 значение = true, 0 = false.
!32 = 0.
Спасибо сказали:
Alexander_a
Сообщения: 6

Re: ioctl() для проверки состояния rs232

Сообщение Alexander_a »

Zeus писал(а):
26.02.2006 13:46
Alexander_a писал(а):
26.02.2006 11:33

Получается, что (16486 & 32) == 32 ?
Что то я не соображу, а если инвертируем, то получается 0?
Здесь нужно что как-то по другому думать/считать? А ля в двоичном коде?

Вообще-то сишник почитать неплохо было бы.
! - не двоичное отрицание, а логическое!
В С - любое не 0 значение = true, 0 = false.
!32 = 0.

Спасибо за разъяснение!
Значит вся информация о состоянии порта содержится в переменной arg? (потому, что значения TIOCM_*, не меняются)
А что такое по-существу значения TIOCM_*? Это что области памяти где хранятся данные о состоянии логических уровней на пинах RS232?
Т.е. этой операцией !!(arg & TIOCM_*) из числа 16486 (0х4066, 100000001100110) выделяются нужные параметры?
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: ioctl() для проверки состояния rs232

Сообщение Zeus »

Alexander_a писал(а):
26.02.2006 15:57
Zeus писал(а):
26.02.2006 13:46

Alexander_a писал(а):
26.02.2006 11:33

Получается, что (16486 & 32) == 32 ?
Что то я не соображу, а если инвертируем, то получается 0?
Здесь нужно что как-то по другому думать/считать? А ля в двоичном коде?

Вообще-то сишник почитать неплохо было бы.
! - не двоичное отрицание, а логическое!
В С - любое не 0 значение = true, 0 = false.
!32 = 0.

Спасибо за разъяснение!
Значит вся информация о состоянии порта содержится в переменной arg? (потому, что значения TIOCM_*, не меняются)
А что такое по-существу значения TIOCM_*? Это что области памяти где хранятся данные о состоянии логических уровней на пинах RS232?
Т.е. этой операцией !!(arg & TIOCM_*) из числа 16486 (0х4066, 100000001100110) выделяются нужные параметры?

Честно говоря, я читаю эту ветку только в рамках синтаксиса C.
В h-никах не копаюсь и разъясняю только суть Сишных операций.
Описанной операцией, пользуясь попустительским :) подходом Сишника к переходу от логических и числовым переменным, выделяют значение того или иного бита в переменной arg.
Можно было бы тоже самое сделать битовыми сдвигами, а если нужно просто узнать 0 или не 0 в данном бите, то вообще можно ничего никуда не сдвигать: arg & TIOCM_* и так сгенерит 0 или не 0, который можно подсунуть в условный оператор.
Спасибо сказали: