Данная статья посвящена работе UART МК К1986ВЕ92 и взаимодействие с ИМС преобразователем ТТЛ в RS-485 К5559ИН10ASI от компании Миландр.
Рассмотрим, каким образом можно принимать и передавать данный по интерфейсу RS-485 на микроконтроллере К1986ВЕ92FI(QI) (аналогично для 1986ВЕ92У1К и 1986ВЕ92УК в металлокерамическом корпусе). При помощи интерфейсной микросхемы К559ИН10ASI (аналогично для ИМС (К)5559ИН10А(Б)У в металлокерамическом корпусе).
Для того, чтобы полноценно описать двунаправленную работу приемо-передатчика изначально надо проинициализировать последовательный асинхронный интерфейс UART на микроконтроллере, так как шилд расширения интерфейса подключается к отладочному комплекту через UART1, то будем его и настраивать:
void UART_InitFunction(void)
{
RST_CLK_PCLKcmd(RST_CLK_PCLK_UART1, ENABLE);
RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTB, ENABLE);
PORT_InitTypeDef PortInit;
UART_InitTypeDef UART_InitStructure;
PortInit.PORT_PULL_UP = PORT_PULL_UP_OFF;
PortInit.PORT_PULL_DOWN = PORT_PULL_DOWN_OFF;
PortInit.PORT_PD_SHM = PORT_PD_SHM_OFF;
PortInit.PORT_PD = PORT_PD_DRIVER;
PortInit.PORT_GFEN = PORT_GFEN_OFF;
PortInit.PORT_FUNC = PORT_FUNC_ALTER;
PortInit.PORT_SPEED = PORT_SPEED_MAXFAST;
PortInit.PORT_MODE = PORT_MODE_DIGITAL;
//Настойка PORTB pins 5 на вывод (UART1_TX)
PortInit.PORT_OE = PORT_OE_OUT;
PortInit.PORT_Pin = PORT_Pin_5;
PORT_Init(MDR_PORTB, &PortInit);
//Настойка PORTB pins 6 на ввод (UART1_RX)
PortInit.PORT_OE = PORT_OE_IN;
PortInit.PORT_Pin = PORT_Pin_6;
PORT_Init(MDR_PORTB, &PortInit);
//Установка предделителя часототы UART1 HCLKdiv = 1
UART_BRGInit(MDR_UART1, UART_HCLKdiv2);
//Настройка параметров UART1: 9600, 8бит, 1 стоп бит, без паритета, откл. буфера FIFO, контроль потока RX/TX
UART_InitStructure.UART_BaudRate = 9600;
UART_InitStructure.UART_WordLength = UART_WordLength8b;
UART_InitStructure.UART_StopBits = UART_StopBits1;
UART_InitStructure.UART_Parity = UART_Parity_No;
UART_InitStructure.UART_FIFOMode = UART_FIFO_OFF;
UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_RXE | UART_HardwareFlowControl_TXE;
//Конфигурирование параметров UART1
UART_Init(MDR_UART1, &UART_InitStructure);
//Конфигурирование параметров UART1
while(UART_Init(MDR_UART1, &UART_InitStructure) != BaudRateValid);
UART_ITConfig(MDR_UART1, UART_IT_RX, ENABLE);
//Команда включения UART1
UART_Cmd(MDR_UART1, ENABLE);
NVIC_EnableIRQ (UART1_IRQn); // Разрешаем прерывания по UART
NVIC_SetPriority(UART1_IRQn, 1); // Устанавливаем первый приоритет прерываниям UART
}Первые строки кода отвечают за вызов функции включения/выключения тактирования периферии.
//Тактирование UART1 - включить
RST_CLK_PCLKcmd(RST_CLK_PCLK_UART1, ENABLE);
//Тактирование порта В, куда подключен UART1 - включить
RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTB, ENABLE);
Далее создаются две переменные структурного типа из подклбченных стандартных библиотек периферии и заполняются поля структуры, отвечающие за настройку порта и интерфейса UART1.
После вызова функции инициализации порта и UART:
PORT_Init(MDR_PORTB, &PortInit);
UART_Init(MDR_UART1, &UART_InitStructure);Необходимо убедиться, что скорость UART установилась корректно, в этом поможет вызов следующей функции:
while(UART_Init(MDR_UART1, &UART_InitStructure) != BaudRateValid);Далее, необходимо настроить прерывание, возникающее, когда UART принял данные из вне, в последствии активировать UART, разрешить по нему прерывания и установить их приоритет.
После написания процедуры инициализации UART, для работы с интерфейсом RS-485, так как он является однонаправленным, надо настроить пин порта, отвечающий, за выбор направления передачи или приёма данных по линии RS-485.
Так как вывод микросхемы подключен к пину 0 порта С микроконтроллера, надо настроить данный пин на выход в режиме порта. Для этого используется следующий код:
void PORTC_Init(void)
{
RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTC, ENABLE);
PORT_InitTypeDef PortInit;
PortInit.PORT_OE = PORT_OE_OUT;
PortInit.PORT_FUNC = PORT_FUNC_PORT;
PortInit.PORT_MODE = PORT_MODE_DIGITAL;
PortInit.PORT_SPEED = PORT_SPEED_SLOW;
PortInit.PORT_Pin = PORT_Pin_0;
PORT_Init(MDR_PORTC, &PortInit);
}Последнее, что остается настроить, это функцию обработки прерываний, которая будет вызываться по приему данных. Которые в этом же обработчикке передаются обратно:
void UART1_IRQHandler(void)
{
if (UART_GetITStatus(MDR_UART1, UART_IT_RX) != RESET)
{
UART_ClearITPendingBit(MDR_UART1, UART_IT_RX);
dataRecive = UART_ReceiveData(MDR_UART1);
while(UART_GetFlagStatus(MDR_UART1, UART_FLAG_BUSY));
PORT_SetBits(MDR_PORTC, PORT_Pin_0);
UART_SendData(MDR_UART1, dataRecive);
while(UART_GetFlagStatus(MDR_UART1, UART_FLAG_BUSY));
PORT_ResetBits(MDR_PORTC, PORT_Pin_0);
}
}Далее поочередно вызываем написанные функции инициализации, очищаем флаг прерывания и переключаем порт в режим приемника:
PORTC_Init();
UART_InitFunction();
UART_ClearITPendingBit(MDR_UART1, UART_IT_RX);
PORT_ResetBits(MDR_PORTC, PORT_Pin_0); Ниже приложен архив проекта, выполненный в Keil uVision MDK-ARM.
