Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.63/8: Рейтинг темы: голосов - 8, средняя оценка - 4.63
1 / 1 / 0
Регистрация: 12.02.2014
Сообщений: 76

Как отловить КЗ на шине CAN?

29.12.2018, 09:59. Показов 1844. Ответов 12

Студворк — интернет-сервис помощи студентам
Всем привет! Всех с НГ.

Вопросик такой.
Есть код обмена по шине CAN.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
 while(!stop)
    {
        try
        {
            if(ss[0]!=-1)
            {
                try
                {
                    close(ss[0]);
                }
                catch(...){}
                ss[0] = -1;
            }
            if(pthread_mutex_trylock(&can_data->mutex_lock)==0)
            {
                stop = can_data->stopThread;
                pthread_mutex_unlock(&can_data->mutex_lock);
                if(stop)
                    break;
            }
            if((ss[0] = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
            {
                generateSignal(signoCan1Red);
                can_data->error = socketError::socket_create_error;
                if(can_data->eventHandler!=0)
                    can_data->eventHandler->onCanStart(socketError::socket_create_error);
                nanosleep(&sp, NULL);
                continue;
            }
 
            if(fcntl(ss[0], F_SETFL, SOCK_NONBLOCK)<0)
            {
                generateSignal(signoCan1Red);
                pthread_mutex_lock(&can_data->mutex_lock);
                can_data->error = socketError::socket_setnonblock_error;
                pthread_mutex_unlock(&can_data->mutex_lock);
                if(can_data->eventHandler!=0)
                    can_data->eventHandler->onCanStart(socketError::socket_setnonblock_error);
                nanosleep(&sp, NULL);
                continue;
            }
 
           strcpy(ifr.ifr_name, can_data->name.data());
 
            ioctl(ss[0], SIOCGIFINDEX, &ifr);
 
            addr.can_family  = AF_CAN;
            addr.can_ifindex = ifr.ifr_ifindex;
 
            if(bind(ss[0], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
                generateSignal(signoCan1Red);
                pthread_mutex_lock(&can_data->mutex_lock);
                can_data->error = socketError::socket_bind_error;
                pthread_mutex_unlock(&can_data->mutex_lock);
                if(can_data->eventHandler!=0)
                    can_data->eventHandler->onCanStart(socketError::socket_bind_error);
                nanosleep(&sp, NULL);
                continue;
            }
 
        }
        catch(...)
        {
            generateSignal(signoCan1Red);
            if(can_data->eventHandler!=0)
                can_data->eventHandler->canOperationError(socketError::socket_unknown_error);
            continue;
        }
 
        if(can_data->eventHandler!=0)
            can_data->eventHandler->onCanStart();
 
        while(!stop)
        {
            try
            {
                if(pthread_mutex_trylock(&can_data->mutex_lock)==0)
                {
                    stop = can_data->stopThread;
                    pthread_mutex_unlock(&can_data->mutex_lock);
                    if(stop)
                        break;
                }
 
                FD_ZERO(&read_fs);
                FD_SET(ss[0], &read_fs);
 
                FD_ZERO(&write_fs);
                FD_SET(ss[0], &write_fs);
 
                FD_ZERO(&error_fs);
                FD_SET(ss[0], &error_fs);
 
                if ((ret = select(ss[0]+1, &read_fs, &write_fs, &error_fs, &timeout_config)) <= 0)
                {
                    continue;
                }
 
                if (FD_ISSET(ss[0], &read_fs))//проверяем дескриптор на готовность к чтению
                {
                    frame_read = new can_frame;
                    frame_read->can_id = 0;
                    frame_read->can_dlc = 0;
                    auto numBytes = read(ss[0], frame_read, CAN_MTU);
                    if(numBytes>0)
                    {
                      if(can_data->eventHandler!=0)
                          can_data->eventHandler->newCanFrame(frame_read);
                      continue;
                    }
                }
 
                if (!can_data->queueIn.isEmpty() && FD_ISSET(ss[0], &write_fs))//проверяем дескриптор на готовность к записи
                {
                    frame_write = can_data->queueIn.dequeue();
                    if(frame_write != 0)
                    {
                        auto numBytes = sendto(ss[0], frame_write, sizeof(struct can_frame),
                                               0, (struct sockaddr*)&addr, sizeof(addr));
 
                        delete frame_write;
                        frame_write = 0;
                        if(numBytes == 0)
                        {
                            generateSignal(signoCan1Red);
                            pthread_mutex_lock(&can_data->mutex_lock);
                            can_data->error = socketError::socket_write_error;
                            pthread_mutex_unlock(&can_data->mutex_lock);
                            if(can_data->eventHandler!=0)
                                can_data->eventHandler->canOperationError(socketError::socket_write_error);
                            break;
                        }
                        else
                        {
                            generateSignal(signoCan1GreenPulse);
                            continue;
                        }
                    }
                }
 
                if (FD_ISSET(ss[0], &error_fs))//проверяем дескриптор на наличие ошибок
                {
                    generateSignal(signoCan1Red);
                    pthread_mutex_lock(&can_data->mutex_lock);
                    can_data->error = socketError::socket_error;
                    pthread_mutex_unlock(&can_data->mutex_lock);
                    if(can_data->eventHandler!=0)
                        can_data->eventHandler->canOperationError(socketError::socket_error);
                    break;
                }
 
            }
            catch(...)
            {
                generateSignal(signoCan1Red);
                if(can_data->eventHandler!=0)
                    can_data->eventHandler->canOperationError(socketError::socket_unknown_error);
                break;
            }
        }
        if(ss[0]!=-1)
        {
            try
            {
                close(ss[0]);
            }
            catch(...){generateSignal(signoCan1Red);}
            ss[0] = -1;
        }
    }
Всё это работает.
Но не получается отследить ситуацию КЗ на шине. Т.е. замыкаем, а никаких ошибок и исключений не вылазит...
Выскочить из внутреннего цикла во внешний не получается.
Кто-нить знает, должна ли вылезать ошибка в if (FD_ISSET(ss[0], &error_fs)) ?
Понятно что можно накрутить проверку что если какое-то колво раз не выбран ни один дескриптор, то это значит, что что-то не в порядке. Но это частная ситуация, когда ты уверен что обмен идет не прерываясь и запросы по кан гуляют постоянно. А если кан тупо простаивает без регулярного обмена, то как отмониторить КЗ?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
29.12.2018, 09:59
Ответы с готовыми решениями:

Как программно подключиться к шине PCI?
Доброе время суток! Как программно подключиться к шине PCI? Добавлено через 3 часа 39 минут Вернее у меня есть мое устройство...

Как подключить сайт к корпоративной шине?
Добрый вечер. Подскажите пожалуйста как подключить сайт к корпоративной шине? Дожна быть БД сайта, Сервер БД, и Веб сервер на котором...

Как отследить адрес на 16 битной шине данных?
Имеется GameBoy. У него игры на катриджах, на катридж выведена шина данных. ...

12
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
29.12.2018, 10:50
Цитата Сообщение от 051Demon Посмотреть сообщение
то-нить знает, должна ли вылезать ошибка в if (FD_ISSET(ss[0], &error_fs)) ?
Нет.
Нужно через setsockopt() установить интересующие вас флаги (незнаю что будет для KЗ, может BUSOFF или BUSERROR) в CAN_RAW_ERR_FILTER и анализировать CAN_ID каждого полученного фрейма на предмет флага CAN_ERR_FLAG
0
1 / 1 / 0
Регистрация: 12.02.2014
Сообщений: 76
29.12.2018, 10:56  [ТС]
спасибо, надо поизучать...
но тут сразу вопрос возникает - а какие могут быть фреймы при кз???
обмен-то обрывается аварийно... линии нет.
т.е. это должна быть либо служебная посылка от системного драйвера CAN, либо чего??
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
29.12.2018, 11:01
Цитата Сообщение от 051Demon Посмотреть сообщение
т.е. это должна быть либо служебная посылка от системного драйвера CAN,
Угу. Они генерируются
драйвером.
1
1 / 1 / 0
Регистрация: 12.02.2014
Сообщений: 76
29.12.2018, 11:08  [ТС]
Еще тогда вопросик, может вы знаете, есть ли способ драйвер системный рестартануть на горячую из программы.
На данный момент, я искусственно попытался прерывать цикл, чтобы выполнить переинициализацию сокета, при прекращении КЗ. Но не получается так. Связи нет.
Приходится рестартовать устройство, чтобы драйвер очухался...
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
29.12.2018, 11:19
Честно говоря не знаю. Если помогает что-то типа ip link set canN type can restart из консоли, то можно посмотреть что именно они делают и повторить руками.
0
1 / 1 / 0
Регистрация: 12.02.2014
Сообщений: 76
29.12.2018, 11:24  [ТС]
спасибо, будем изучать...
0
 Аватар для weterok
36 / 28 / 9
Регистрация: 11.11.2018
Сообщений: 163
05.01.2019, 11:58
а зачем Вам отлавливать КЗ на шине? может шина заизолирована будет и в этом нет необходимости.
0
1 / 1 / 0
Регистрация: 12.02.2014
Сообщений: 76
09.01.2019, 08:10  [ТС]
ага, действительно, а зачем )))) а вдруг авось да небось
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
09.01.2019, 13:33
051Demon, если будут результаты, напишите сюда пожалуйста - вдруг самому когда пригодиться.
0
1 / 1 / 0
Регистрация: 12.02.2014
Сообщений: 76
06.11.2019, 12:48  [ТС]
prik, получилось примерно так

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
socketError err = socketError::socket_no_error;
can_err_mask_t err_mask=CAN_ERR_MASK; 
setsockopt(ss[0], SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &err_mask, sizeof(err_mask));
....
....
if (FD_ISSET(ss[0], &read_fs))//проверяем дескриптор на готовность к чтению
{
       frame_read = new can_frame;
       frame_read->can_id = 0;
       frame_read->can_dlc = 0;
       auto numBytes = read(ss[0], frame_read, CAN_MTU);
       if(numBytes>0)
       {                        
            if(frame_read->can_id & CAN_ERR_FLAG)
            {
                    if(frame_read->can_id & CAN_ERR_BUSOFF) //кз на шине
                          err = socketError::socket_error_can_bus_short; 
                     ......
             }
             else
             {
                  ......
             }
 
       }
}
1
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 643
07.11.2019, 08:07
Это то прозрачно, а на этот вопрос решение нашли?
Цитата Сообщение от 051Demon Посмотреть сообщение
есть ли способ драйвер системный рестартануть на горячую из программы.
0
1 / 1 / 0
Регистрация: 12.02.2014
Сообщений: 76
07.11.2019, 08:09  [ТС]
prik, в настройках can указывается таймаут на рестарт

up ip link set up can0 type can bitrate 500000 restart-ms 100
т.е. при сбое, в том числе при кз, драйвер будет каждые 100 мс рестартовать.

в моем варианте работает отлично. всё ок
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
07.11.2019, 08:09
Помогаю со студенческими работами здесь

Как будет работать схема на операционном усилителе, если его вход минус подключить к общей шине
Как будет работать схема на операционном усилителе, если его вход минус подключить к общей шине, а на вход плюс подать синусоидальное...

Как отловить событие снятия галочки как во внутренних Checkbox компонента
Есть такой составной компонент,предок которому TREEVIEW,надо обработать события снятия галочки как во внутренних Checkbox так и во...

Как остановить ролик из основной сцены, и как отловить окончание ролика?
в ролике я могу прописать stop() но я хочу что б весь код был только на основной сцене по этому подскажите как остановить ролик после его...

Как написать свой Shift? ( или как отловить клавиши )
И снова Здравствуйте!) Уже 3-й день сижу над Клавиатурным хуком ) KeyboardHook И никак не могу понять как же отловить Shift (Шифт) ? ...

Можно ли как-то отловить NetSend, до того как он высветится
Мне нужно отловить NetSend и отобразить его содержание у себя в программе, а само окно Службы сообщений, показывать не надо. Кто знает...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
Программный контроль заполнения реквизита табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать контроль заполнения реквизита табличной части. . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Функция заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru