andron_h 0 Posted August 25, 2021 · Report post Доброго дня! Есть задача не пропускать в панель приборов определенные пакеты по CAN шине. Создал проект шлюза на STM32F107RTB6 с двумя кан. Но столкнулся с тем, что при запуске двигателя шлюз затыкается пропадают пакеты и панель приборов загорается как новогодняя елка, если двигатель глушу, оставляя только включенным зажигание, то все восстанавливается. Попробовал в качестве шлюза использовать проект Canny7.2 duo он справляется с передачей, но запихать планируемую обработку в диаграмму невозможно, очень сложные расчеты. На стм же не получается даже прокинуть сообщения из кана в кан без обработки. Гляньте, может у меня где по коду затык. /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2020 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ CAN_HandleTypeDef hcan1; CAN_HandleTypeDef hcan2; /* USER CODE BEGIN PV */ CAN_TxHeaderTypeDef TxHeader; CAN_RxHeaderTypeDef RxHeader; uint8_t TxData[8] = {0,}; uint8_t RxData[8] = {0,}; uint32_t TxMailbox = 0; uint8_t MessageTrigger = 0; uint8_t FilterStatus = 0; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_CAN1_Init(void); static void MX_CAN2_Init(void); /* USER CODE BEGIN PFP */ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan); void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ __enable_irq (); // разрешить прерывания. /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ __enable_irq (); // разрешить прерывания. /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_CAN1_Init(); MX_CAN2_Init(); /* USER CODE BEGIN 2 */ HAL_CAN_Start(&hcan1); HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING |CAN_IT_TX_MAILBOX_EMPTY); HAL_CAN_Start(&hcan2); HAL_CAN_ActivateNotification(&hcan2,CAN_IT_RX_FIFO1_MSG_PENDING |CAN_IT_TX_MAILBOX_EMPTY); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.Prediv1Source = RCC_PREDIV1_SOURCE_HSE; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL8; RCC_OscInitStruct.PLL2.PLL2State = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { Error_Handler(); } /** Configure the Systick interrupt time */ __HAL_RCC_PLLI2S_ENABLE(); } /** * @brief CAN1 Initialization Function * @param None * @retval None */ static void MX_CAN1_Init(void) { /* USER CODE BEGIN CAN1_Init 0 */ CAN_FilterTypeDef sFilterConfig; /* USER CODE END CAN1_Init 0 */ /* USER CODE BEGIN CAN1_Init 1 */ /* USER CODE END CAN1_Init 1 */ hcan1.Instance = CAN1; hcan1.Init.Prescaler = 4; hcan1.Init.Mode = CAN_MODE_NORMAL; hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ; hcan1.Init.TimeSeg1 = CAN_BS1_13TQ; hcan1.Init.TimeSeg2 = CAN_BS2_2TQ; hcan1.Init.TimeTriggeredMode = DISABLE; hcan1.Init.AutoBusOff = ENABLE; hcan1.Init.AutoWakeUp = ENABLE; hcan1.Init.AutoRetransmission = DISABLE; hcan1.Init.ReceiveFifoLocked = DISABLE; hcan1.Init.TransmitFifoPriority = DISABLE; if (HAL_CAN_Init(&hcan1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN CAN1_Init 2 */ sFilterConfig.FilterBank = 0; sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; sFilterConfig.FilterIdHigh = 0x0000; sFilterConfig.FilterIdLow = 0x0000; sFilterConfig.FilterMaskIdHigh = 0x0000; sFilterConfig.FilterMaskIdLow = 0x0000; sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0; sFilterConfig.FilterActivation = ENABLE; //sFilterConfig.SlaveStartFilterBank = 14; if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) { Error_Handler(); } /* USER CODE END CAN1_Init 2 */ } /** * @brief CAN2 Initialization Function * @param None * @retval None */ static void MX_CAN2_Init(void) { /* USER CODE BEGIN CAN2_Init 0 */ CAN_FilterTypeDef sFilterConfig; /* USER CODE END CAN2_Init 0 */ /* USER CODE BEGIN CAN2_Init 1 */ /* USER CODE END CAN2_Init 1 */ hcan2.Instance = CAN2; hcan2.Init.Prescaler = 4; hcan2.Init.Mode = CAN_MODE_NORMAL; hcan2.Init.SyncJumpWidth = CAN_SJW_1TQ; hcan2.Init.TimeSeg1 = CAN_BS1_13TQ; hcan2.Init.TimeSeg2 = CAN_BS2_2TQ; hcan2.Init.TimeTriggeredMode = DISABLE; hcan2.Init.AutoBusOff = ENABLE; hcan2.Init.AutoWakeUp = ENABLE; hcan2.Init.AutoRetransmission = DISABLE; hcan2.Init.ReceiveFifoLocked = DISABLE; hcan2.Init.TransmitFifoPriority = DISABLE; if (HAL_CAN_Init(&hcan2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN CAN2_Init 2 */ sFilterConfig.FilterBank = 15; sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; sFilterConfig.FilterIdHigh = 0x0000; sFilterConfig.FilterIdLow = 0x0000; sFilterConfig.FilterMaskIdHigh = 0x0000; sFilterConfig.FilterMaskIdLow = 0x0000; sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO1; sFilterConfig.FilterActivation = ENABLE; //sFilterConfig.SlaveStartFilterBank = 14; if(HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK) { Error_Handler(); } /* USER CODE END CAN2_Init 2 */ } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); } /* USER CODE BEGIN 4 */ void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef*hcan) { //HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_12); } void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan2) == 0); HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxHeader, RxData); HAL_CAN_AddTxMessage(&hcan2, &RxHeader,RxData,&TxMailbox); } void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) { while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1) == 0); HAL_CAN_GetRxMessage(&hcan2, CAN_RX_FIFO1, &RxHeader, RxData); HAL_CAN_AddTxMessage(&hcan1, &RxHeader,RxData,&TxMailbox); } /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Hunveibin 0 Posted August 25, 2021 · Report post Не совсем понятно - CAN вообще не работает или отваливается только при запуске двигателя? Если первое, проверьте настройки таймингов CAN-интерфейса. Вот вроде неплохой калькулятор:http://www.bittiming.can-wiki.info/ Попробуйте без строчек вида while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan2) == 0); Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
andron_h 0 Posted August 25, 2021 · Report post Отваливается только при запуске двигателя, количество пакетов вырастает. После остановки двигателя, но с включенным зажиганием, обмен приходит в норму. Без этой строчки отваливается быстрее, т.е. вот вообще сразу с запуском двигла, со строкой 3-4 секунды рабочего двигателя пропускаются. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Hunveibin 0 Posted August 25, 2021 · Report post 31 минуту назад, andron_h сказал: Отваливается только при запуске двигателя, количество пакетов вырастает. После остановки двигателя, но с включенным зажиганием, обмен приходит в норму. Без этой строчки отваливается быстрее, т.е. вот вообще сразу с запуском двигла, со строкой 3-4 секунды рабочего двигателя пропускаются. Можно предположить, что проблема может быть в функции HAL_CAN_AddTxMessage Точнее, МК просто не успевает отправить сообщения. Попробуйте функциюHAL_CAN_GetTxMailboxesFreeLevel Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
andron_h 0 Posted August 25, 2021 · Report post 4 минуты назад, Hunveibin сказал: Можно предположить, что проблема может быть в функции HAL_CAN_AddTxMessage Точнее, МК просто не успевает отправить сообщения. Попробуйте функциюHAL_CAN_GetTxMailboxesFreeLevel Ну дак она и есть сообщением выше. while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan2) == 0); Функция HAL_CAN_GetTxMailboxesFreeLevel(...) возвращает количество свободных ящиков для отправки, то есть она должна вернуть 1, 2 или 3. Если все ящики заняты (сообщения не успели улететь) тогда будет возвращаться 0. Соответственно мы тормозим программу пока не освободится хотя бы один ящик. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Eddy_Em 0 Posted August 25, 2021 · Report post Веселит легкомыслие любителей "хала": они считают, что вообще никакой документации читать не нужно! А, между тем, в отличие от тех, кто пишет без всяких левых библиотек, им приходится помимо RM и DS читать еще и мануалы на "хал" (а в реальности — еще и исходники этого "хала" постоянно листать). А еще у "хала" до сих пор куча дыр (молчу уж об оверхеде). Ну и где здесь выгода? Если нет желания изучать железо, под которое ты пишешь, то, может быть, стоит покинуть профессию? Ну, а ежели ты любитель — оставаться абдуринщиком? Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Hunveibin 0 Posted August 25, 2021 (edited) · Report post 4 часа назад, andron_h сказал: Ну дак она и есть сообщением выше. while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan2) == 0); Функция HAL_CAN_GetTxMailboxesFreeLevel(...) возвращает количество свободных ящиков для отправки, то есть она должна вернуть 1, 2 или 3. Если все ящики заняты (сообщения не успели улететь) тогда будет возвращаться 0. Соответственно мы тормозим программу пока не освободится хотя бы один ящик. Извините, непонятно написал. Я имею ввиду - попробуйте в обработчиках прерывания сделать так: HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxHeader, RxData); while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan2) == 0); HAL_CAN_AddTxMessage(&hcan2, &RxHeader,RxData,&TxMailbox); Иначе говоря, сначала копируете принятое сообщение в буфер, и потом проверяете в цикле, можно ли отправить сообщение. И когда освободится хоть один мейлбокс, отправляете. Согласитесь, разница по сравнению с первоначальным вариантом есть. Ну и учитывайте, что в общем случае делать такие проверки в обработчиках прерывания - не самая лучшая идея. Цитата А еще у "хала" до сих пор куча дыр (молчу уж об оверхеде). Ну и где здесь выгода? Если нет желания изучать железо, под которое ты пишешь, то, может быть, стоит покинуть профессию? Ну, а ежели ты любитель — оставаться абдуринщиком? По первому пункту возражений почти не имею: что-то можно было бы и оптимизировать или даже убрать. Но все же явных косяков не замечал (по сравнению с более ранними версиями). Что касается того, что в холовских функциях вставлено много на первый взгляд лишнего - да, такое тоже есть. Пример этому те же функции работы с интерфейсами через ПДП - куча проверок "включено ли" и "если не включено, включить". С другой стороны, учитывая скорость даже простеньких СТМок, это в большинстве случаев не так критично. Выгода же очевидна - вместо разработки своих библиотек или использования самоделок от неизвестных самоделкиных, конечный пользователь имеет готовое решение от производителя с поддержкой, обновлениями и исправлениями ошибок. Критика в данном случае должна была бы сопровождаться все же и помощью, уж коли Вы хорошо разбираетесь в этой теме. А то так получается как-то не очень красиво. Кроме всего, как такая ситуация - человек жалуется, что у него не работает схема на ОУ. А ему в ответ - рассуждения на тему, как обленились и отупели молодые разработчики. Не могут собрать схему из транзисторов! Edited August 25, 2021 by Hunveibin Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Captain777 0 Posted August 26, 2021 · Report post На HAL удалось только демоверсию сделать. В реальной машине (задача та же BMW G серия) получилось только на SPL. Поток данных от авто к панели значительно выше, чем в обратную сторону, поэтому правильно надо настроить приоритеты. Используйте два буфера FIFO - через один отправляете пакеты не фильтрованные, через второй по маске обрабатываете нужные ID. Не забываем про правильное вычисление контрольных сумм. Могу сказать, что задача эта далеко не такая простая - как кажется на первый взгляд. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Lmx2315 0 Posted August 26, 2021 · Report post А зачем надо в автомобиле не все пакеты к панели пропускать? Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Vasily_ 0 Posted August 26, 2021 · Report post 38 минут назад, Lmx2315 сказал: А зачем надо в автомобиле не все пакеты к панели пропускать? Например тормозить пробег, либо накручивать пробег и тд. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
andron_h 0 Posted August 26, 2021 · Report post 26 минут назад, Lmx2315 сказал: А зачем надо в автомобиле не все пакеты к панели пропускать? Потому как в составе пакета может быть вредная информация. Применительно к моей ситуации например. Так как панель свапнули от другой комплектации панель неправильно воспринимает данные, нужно из одного ID сделать другой и чтоб первый не приходил в приборку, так как получим сообщение о сбое работы на весь дисплей, до перезапуска двигателя. 11 часов назад, Hunveibin сказал: Извините, непонятно написал. Я имею ввиду - попробуйте в обработчиках прерывания сделать так: HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxHeader, RxData); while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan2) == 0); HAL_CAN_AddTxMessage(&hcan2, &RxHeader,RxData,&TxMailbox); Иначе говоря, сначала копируете принятое сообщение в буфер, и потом проверяете в цикле, можно ли отправить сообщение. И когда освободится хоть один мейлбокс, отправляете. Согласитесь, разница по сравнению с первоначальным вариантом есть. Ну и учитывайте, что в общем случае делать такие проверки в обработчиках прерывания - не самая лучшая идея. Спасибо, попробую так сделать, но я все больше прихожу к выводу что нужно делать кольцевой буфер, в него пихать все поступающее данные с обоих канов в прерываниях, а потом в основном цикле этот буфер разгребать. 1 час назад, Captain777 сказал: На HAL удалось только демоверсию сделать. В реальной машине (задача та же BMW G серия) получилось только на SPL. Поток данных от авто к панели значительно выше, чем в обратную сторону, поэтому правильно надо настроить приоритеты. Используйте два буфера FIFO - через один отправляете пакеты не фильтрованные, через второй по маске обрабатываете нужные ID. Не забываем про правильное вычисление контрольных сумм. Могу сказать, что задача эта далеко не такая простая - как кажется на первый взгляд. У меня сейчас в один буфер от машины в панель, в другой из панели в машину. Думаете пропускать через один? Можно взглянуть на реализацию приема передачи, сама оброботка фильтрации и подмены данных мне не интересна. С контрольками под vag я разобрался там crc8H2F с дополнительным числом в зависимости от счетчика и ID. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Eddy_Em 0 Posted August 26, 2021 (edited) · Report post 13 hours ago, Hunveibin said: Критика в данном случае должна была бы сопровождаться все же и помощью На F103 с CAN я не работал (нет смысла, т.к. там одновременно CAN и USB не завести никак). А вот на F0x2 — вполне себе. Вот пример переходника CAN-USB, там есть и фильтрация сообщений (как софтовая, так и аппаратная). Кстати, функция can_setup у меня практически полностью по ST'шным сниппетам сделана! Советую ТСу внимательно почитать мануал на свой камень + изучить сниппеты под STM32F0 (между ними и F1 довольно-таки много общего). Да, если что, у STM32 вполне мощный DMA, так зачем вообще делать шлюз между двумя CAN-шинами программно? Можно же просто при помощи DMA напрямую слать данные туда-сюда. А фильтры настроить аппаратные. Edited August 26, 2021 by Eddy_Em Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
andron_h 0 Posted August 26, 2021 · Report post 2 часа назад, Eddy_Em сказал: Вот пример переходника CAN-USB, там есть и фильтрация сообщений (как софтовая, так и аппаратная). Кстати, функция can_setup у меня практически полностью по ST'шным сниппетам сделана! Советую ТСу внимательно почитать мануал на свой камень + изучить сниппеты под STM32F0 (между ними и F1 довольно-таки много общего). Да, если что, у STM32 вполне мощный DMA, так зачем вообще делать шлюз между двумя CAN-шинами программно? Можно же просто при помощи DMA напрямую слать данные туда-сюда. А фильтры настроить аппаратные. За пример благодарю. Изучу. Попробую переделать без хала. А вот по дма тут вопрос есть. Кана в списке поддерживаемой периферии не нашел в даташите и примеров с использованием дма тоже. DMA: 12-channel DMA controller – Supported peripherals: timers, ADCs, DAC,I2Ss, SPIs, I2Cs and USARTs Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Eddy_Em 0 Posted August 26, 2021 · Report post 37 minutes ago, andron_h said: Кана в списке поддерживаемой периферии не нашел в даташите и примеров с использованием дма тоже. Тогда извиняюсь. Я почему-то был уверен, что DMA и с CAN тоже работает. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
andron_h 0 Posted August 26, 2021 · Report post 18 часов назад, Hunveibin сказал: Извините, непонятно написал. Я имею ввиду - попробуйте в обработчиках прерывания сделать так: HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxHeader, RxData); while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan2) == 0); HAL_CAN_AddTxMessage(&hcan2, &RxHeader,RxData,&TxMailbox); Иначе говоря, сначала копируете принятое сообщение в буфер, и потом проверяете в цикле, можно ли отправить сообщение. И когда освободится хоть один мейлбокс, отправляете. Согласитесь, разница по сравнению с первоначальным вариантом есть. Ну и учитывайте, что в общем случае делать такие проверки в обработчиках прерывания - не самая лучшая идея. Попробовал. Результат тот-же, но только не задержка от запуска до возникновения ошибки увеличилась до 10-12 секунд. Видимо это все от отсутствия буффера. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...