Однажды, появилась необходимость использования в нашем устройстве мультиплексного канала обмена информацией (МКИО), он же ГОСТ Р 52070-2003, он же MIL-STD-1553В. Первоначальный результат поисков несколько удивил: типовые решения выдаваемые поисковой системой, как правило, основывались на использовании ПЛИС. Поскольку решать проблему нужно было быстро, появилась мысль сделать конвертер протокола из MIL-STD-1553 в MODBUS RTU. При этом постараться использовать достаточно недорогие технические решения и микроконтроллер из семейства STM32.
На фото из Википедии: F16, на котором впервые был использована шина MIL-STD-1553В. Наши устройства не летают :), поэтому каких либо ограничений по применению элементной базы нет. Просто у Заказчика приборная сеть построена на основе этой шины. Первая часть статьи описывает прием и передачу по шине МКИО, вторая часть будет про конвертер в MODBUS.
Первый этап любой разработки: поиск информации и чтение документации. После этого этапа в голове сложилось следующее:
— протокол достаточно прост :)
— максимальный кадр 32 байта :)
— имеет довольно жесткий тайминг :(
— довольно дорогие микросхемы и модули :(
После некоторых размышлений остановился на использовании кодера — декодера HI-15530, фирмы HOLT, однако аналогов у это микросхемы достаточно много. Правда не все могут быть доступны в России за разумные деньги и сроки. :)
Вот примерная схема включения этой микросхемы. Правда взята из даташита аналога. :)
Дальше все просто :) Подключаем к портам микропроцессора 16 разрядные шины данных: PARALLEL IN и PARALLEL OUT и управляющие сигналы:
— VALID WORD (Принято корректное слово)
— ENCODER ENABLE (Начало передачи слова)
— COMMAND SYNC (Выбор команда/данные)
Вместо регистра 74LS164 пришлось использовать аналог ЭКФ1533ИР8. Кроме этого используются повторители SN74ALS1035 (ЭКФ1533ЛП17) с открытым коллектором для согласования сигналов 3.3В (STM32) до 5В (HI-15530).
После некоторой переписки с производителями и поставщиками был выбран приемо-передачик EL-15N фирмы ЕЛКУС.
Добавился еще один сигнал управления ST (Включение передатчика)
Получилась вот такая плата.
Началась отладка программного обеспечения. Для имитации обмена данных с каналом был приобретен USB модуль у компании «Модуль», который может быть, как оконечным устройством (ОУ), так и контроллером шины (КШ).
К модулю прилагается программа управления PURUMK. Программа приема и передачи получилась достаточно простой.
Прием 16 разрядного слова происходит по прерыванию от сигнала VALID WORD:
void EXTI9_5_IRQHandler (void) //Valid Word
{
Ctrl_LED3_ON
EXTI->PR|=0x0040; //Очищаем флаг
STD1553_RX_buffer[recieve_count] = GPIOE->IDR;
recieve_count++;
frame_from_channel = 1; //флаг принятого слова
Ctrl_LED3_OFF
}
Обработка флага принятого слова:
if (frame_from_channel)
{
frame_from_channel = 0;
switch (Channel_state)
{
case 0: //обработка командного слова
Device_address_recieved = STD1553_RX_buffer[0];
Device_address_recieved = Device_address_recieved >> 11;
if (Device_address_recieved == Device_address) //запрос по адресу
{
Command_recieved = STD1553_RX_buffer[0]; //сохранение команды в буфере
Command_recieved = Command_recieved & 0x001F; //выделение команды/количества слов
Transmitt_direction = STD1553_RX_buffer[0];
Transmitt_direction = Transmitt_direction & 0x0400;
if (Transmitt_direction == 0x0400) //запрос информации в канал
{
TRANSMITTER_ENABLE_HIGH;
//запуск таймера передачи данных
TIM5->CR1 |= TIM_CR1_CEN; //Bit 0 CEN: Counter enable
TIM5->CNT = Transmitt_word_period; //
Answer_word_flag = 1;
}
else //прием данных из канала
{
Channel_state = 1;
}
}
else
{
recieve_count = 0;
}
break;
case 1: //прием данных
if (recieve_count == Command_recieved + 1)
{
//передача ответного слова
TRANSMITTER_ENABLE_HIGH;
Answer_word_flag = 1;
Command_recieved = 0;
//запуск передачи
TIM5->CR1 |= TIM_CR1_CEN; //Bit 0 CEN: Counter enable
TIM5->CNT = Transmitt_word_period; //
}
break;
} //end of switch
} //end of if
И собственно передача данных в канал. Передача каждого слова в канал происходит по прерыванию таймера.
//передача данных по МКИО
void TIM5_IRQHandler (void) //
{
EXTI->IMR &= ~EXTI_IMR_MR6; //DISABLE Interrupt Mask on line 1
if (Answer_word_flag)
{
SYNC_SELECT_COMMAND;
Answer_word_flag = 0;
}
else
{
SYNC_SELECT_DATA;
}
GPIOD->ODR = STD1553_TX_buffer[transmitt_count];
delay(5);
ENCODER_ENABLE_HIGH; //запись данных в регистр
delay(112);
transmitt_count ++;
ENCODER_ENABLE_LOW; //начало передачи данных в канал
if (transmitt_count > Command_recieved)
{
delay(700);
TIM5->CR1 &= ~TIM_CR1_CEN; //Bit 0 CEN: Counter enable
transmitt_count = 0;
EXTI->IMR |= EXTI_IMR_MR6; //ENABLE Interrupt Mask on line 1
Channel_state = 0;
recieve_count = 0;
TRANSMITTER_ENABLE_LOW;
}
TIM5->SR = 0;
TIM5->CNT = 0;
}
И вот результат.
Аббревиатуры ОУКШ и КШОУ означают, соответственно: оконечное устройство — контроллеру шины, контроллер шины — оконечному устройству. То есть в первом случае запрос на передачу данных от ОУ, а во втором передача данных оконечному устройству. И в том, и другом случае передается по 31 слову. Более 10000 слов принято и передано и ни одной ошибки. :)
Автор: sanders1967