Автор: admin, 20 февраля, 2025
MILUINO SHIELD RS-485
Краткое описание

Данная статья посвящена работе 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.

Дополнительные файлы